@bian-womp/spark-workbench 0.1.2 → 0.1.3
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 +76 -12
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/examples/reactflow/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/Inspector.d.ts.map +1 -1
- package/lib/esm/index.js +77 -13
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/examples/reactflow/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/Inspector.d.ts.map +1 -1
- package/package.json +7 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../../src/examples/reactflow/WorkbenchStudio.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../../src/examples/reactflow/WorkbenchStudio.tsx"],"names":[],"mappings":"AA0gBA,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,MAAM,EACN,cAAc,EACd,OAAO,EACP,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,aAAa,EACb,KAAK,EACL,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,kBAAkB,GACnB,EAAE;IACD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,OAAO,GAAG,aAAa,GAAG,WAAW,CAAC;IACnD,mBAAmB,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,WAAW,KAAK,IAAI,CAAC;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,aAAa,EAAE,OAAO,CAAC;IACvB,qBAAqB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C,2CAiDA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,SAAS,EACT,QAAQ,GACT,EAAE;IACD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACxD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,
|
|
1
|
+
{"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,SAAS,EACT,QAAQ,GACT,EAAE;IACD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACxD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,2CA6UA"}
|
package/lib/esm/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, createSimpleGraphRegistry, createSimpleGraphDef, createValidationGraphRegistry, createValidationGraphDef, createProgressGraphRegistry, createProgressGraphDef, createAsyncGraphRegistry, createAsyncGraphDef } from '@bian-womp/spark-graph';
|
|
1
|
+
import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, createSimpleGraphRegistry, createSimpleGraphDef, createValidationGraphRegistry, createValidationGraphDef, createProgressGraphRegistry, createProgressGraphDef, createAsyncGraphRegistry, createAsyncGraphDef, Registry } from '@bian-womp/spark-graph';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React, { createContext, useContext, useMemo, useState, useCallback, useEffect, useRef } from 'react';
|
|
4
|
+
import { HttpPollingTransport, WebSocketTransport, RemoteRunner } from '@bian-womp/spark-remote';
|
|
4
5
|
import ReactFlow, { Handle, Position, useReactFlow, Background, MiniMap, Controls } from 'reactflow';
|
|
5
6
|
import 'reactflow/dist/style.css';
|
|
6
7
|
import cx from 'classnames';
|
|
7
8
|
import { XCircleIcon, WarningCircleIcon } from '@phosphor-icons/react';
|
|
8
|
-
import { HttpPollingTransport, WebSocketTransport, RemoteRunner } from '@bian-womp/spark-remote';
|
|
9
9
|
|
|
10
10
|
class DefaultUIExtensionRegistry {
|
|
11
11
|
constructor() {
|
|
@@ -1155,7 +1155,8 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1155
1155
|
return (jsxs("div", { className: `${widthClass} border-l border-gray-300 p-3 flex flex-col h-full min-h-0 overflow-hidden`, children: [jsx("div", { className: "font-semibold mb-2", children: "Inspector" }), jsx("div", { className: "flex-1 overflow-auto", children: !selectedNode && !selectedEdge ? (jsxs("div", { children: [jsx("div", { className: "text-gray-500", children: "Select a node or edge." }), globalValidationIssues && globalValidationIssues.length > 0 && (jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsx("ul", { className: "list-disc ml-4", children: globalValidationIssues.map((m, i) => (jsxs("li", { className: "flex items-center gap-1", children: [jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsx("span", { children: `${m.code}: ${m.message}` })] }, i))) })] }))] })) : selectedEdge ? (jsxs("div", { children: [jsxs("div", { className: "mb-2", children: [jsxs("div", { children: ["Edge: ", selectedEdge.id] }), jsxs("div", { children: [selectedEdge.source.nodeId, ".", selectedEdge.source.handle, " \u2192", " ", selectedEdge.target.nodeId, ".", selectedEdge.target.handle] }), jsxs("div", { children: ["Type: ", selectedEdge.typeId] })] }), selectedEdgeValidation.length > 0 && (jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxs("li", { className: "flex items-center gap-1", children: [jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsx("span", { children: `${m.code}: ${m.message}` })] }, i))) })] }))] })) : (jsxs("div", { children: [selectedNode && (jsxs("div", { className: "mb-2", children: [jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxs("div", { children: ["Type: ", selectedNode.typeId] }), !!selectedNodeStatus?.lastError && (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 ??
|
|
1156
1156
|
selectedNodeStatus.lastError) }))] })), jsxs("div", { className: "mb-2", children: [jsx("div", { className: "font-semibold mb-1", children: "Inputs" }), inputHandles.length === 0 ? (jsx("div", { className: "text-gray-500", children: "No inputs" })) : (inputHandles.map((h) => {
|
|
1157
1157
|
const typeId = (selectedDesc?.inputs ?? {})[h];
|
|
1158
|
-
const isLinked = def.edges.some((e) => e.target.nodeId === selectedNodeId &&
|
|
1158
|
+
const isLinked = def.edges.some((e) => e.target.nodeId === selectedNodeId &&
|
|
1159
|
+
e.target.handle === h);
|
|
1159
1160
|
const commonProps = {
|
|
1160
1161
|
style: { flex: 1 },
|
|
1161
1162
|
disabled: isLinked,
|
|
@@ -1174,7 +1175,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
1174
1175
|
const orig = originals[h] ?? toDisplay(typeId, current);
|
|
1175
1176
|
setDrafts((d) => ({ ...d, [h]: orig }));
|
|
1176
1177
|
};
|
|
1177
|
-
const isEnum = typeId?.
|
|
1178
|
+
const isEnum = typeId?.includes("enum:");
|
|
1178
1179
|
const inIssues = selectedNodeHandleValidation.inputs.filter((m) => m.handle === h);
|
|
1179
1180
|
const hasValidation = inIssues.length > 0;
|
|
1180
1181
|
const hasErr = inIssues.some((m) => m.level === "error");
|
|
@@ -1537,6 +1538,60 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1537
1538
|
setExampleState(key);
|
|
1538
1539
|
onExampleChange?.(key);
|
|
1539
1540
|
}, [runner, wb, onExampleChange, runAutoLayout]);
|
|
1541
|
+
const hydrateFromBackend = useCallback(async (kind, base) => {
|
|
1542
|
+
try {
|
|
1543
|
+
const transport = kind === "remote-http"
|
|
1544
|
+
? new HttpPollingTransport(base)
|
|
1545
|
+
: new WebSocketTransport(base);
|
|
1546
|
+
await transport.connect();
|
|
1547
|
+
const rr = new RemoteRunner(transport);
|
|
1548
|
+
const desc = await rr.describeRegistry();
|
|
1549
|
+
const r = new Registry();
|
|
1550
|
+
// Types
|
|
1551
|
+
for (const t of desc.types) {
|
|
1552
|
+
r.registerType({
|
|
1553
|
+
id: t.id,
|
|
1554
|
+
displayName: t.displayName,
|
|
1555
|
+
validate: (_v) => true,
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
// Categories: create placeholders for display name
|
|
1559
|
+
for (const c of desc.categories || []) {
|
|
1560
|
+
// If you later expose real category descriptors, register them here
|
|
1561
|
+
// For now, rely on ComputeCategory for behavior
|
|
1562
|
+
const category = {
|
|
1563
|
+
id: c.id,
|
|
1564
|
+
displayName: c.displayName,
|
|
1565
|
+
createRuntime: () => ({
|
|
1566
|
+
async onInputsChanged() { },
|
|
1567
|
+
}),
|
|
1568
|
+
policy: { mode: "push", asyncConcurrency: "switch" },
|
|
1569
|
+
};
|
|
1570
|
+
r.categories.register(category);
|
|
1571
|
+
}
|
|
1572
|
+
// Coercions (client-side no-op to satisfy validation) if provided
|
|
1573
|
+
for (const c of desc.coercions) {
|
|
1574
|
+
r.registerCoercion(c.from, c.to, (v) => v);
|
|
1575
|
+
}
|
|
1576
|
+
// Nodes (use no-op impl for compute)
|
|
1577
|
+
for (const n of desc.nodes) {
|
|
1578
|
+
r.registerNode({
|
|
1579
|
+
id: n.id,
|
|
1580
|
+
categoryId: n.categoryId,
|
|
1581
|
+
displayName: n.displayName,
|
|
1582
|
+
inputs: n.inputs || {},
|
|
1583
|
+
outputs: n.outputs || {},
|
|
1584
|
+
impl: () => { },
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
setRegistry(r);
|
|
1588
|
+
wb.setRegistry(r);
|
|
1589
|
+
await transport.close();
|
|
1590
|
+
}
|
|
1591
|
+
catch (err) {
|
|
1592
|
+
console.error("Failed to hydrate registry from backend:", err);
|
|
1593
|
+
}
|
|
1594
|
+
}, [setRegistry, wb]);
|
|
1540
1595
|
// Ensure initial example is loaded (and sync when example prop changes)
|
|
1541
1596
|
useEffect(() => {
|
|
1542
1597
|
applyExample(example ?? "simple");
|
|
@@ -1559,6 +1614,15 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1559
1614
|
// ignore
|
|
1560
1615
|
}
|
|
1561
1616
|
}, [engine, runner, wb]);
|
|
1617
|
+
// When switching to remote backend, auto-hydrate registry from backend
|
|
1618
|
+
useEffect(() => {
|
|
1619
|
+
if (backendKind === "remote-http" && httpBaseUrl) {
|
|
1620
|
+
void hydrateFromBackend("remote-http", httpBaseUrl);
|
|
1621
|
+
}
|
|
1622
|
+
else if (backendKind === "remote-ws" && wsUrl) {
|
|
1623
|
+
void hydrateFromBackend("remote-ws", wsUrl);
|
|
1624
|
+
}
|
|
1625
|
+
}, [backendKind, httpBaseUrl, wsUrl, hydrateFromBackend]);
|
|
1562
1626
|
useEffect(() => {
|
|
1563
1627
|
if (autoLayoutRan.current)
|
|
1564
1628
|
return;
|
|
@@ -1595,33 +1659,33 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1595
1659
|
.map(map);
|
|
1596
1660
|
};
|
|
1597
1661
|
switch (typeId) {
|
|
1598
|
-
case "float": {
|
|
1662
|
+
case "base.float": {
|
|
1599
1663
|
const n = Number(raw);
|
|
1600
1664
|
value = Number.isFinite(n) ? n : 0;
|
|
1601
1665
|
break;
|
|
1602
1666
|
}
|
|
1603
|
-
case "bool": {
|
|
1667
|
+
case "base.bool": {
|
|
1604
1668
|
value = Boolean(raw);
|
|
1605
1669
|
break;
|
|
1606
1670
|
}
|
|
1607
|
-
case "string": {
|
|
1671
|
+
case "base.string": {
|
|
1608
1672
|
value = String(raw);
|
|
1609
1673
|
break;
|
|
1610
1674
|
}
|
|
1611
|
-
case "float[]": {
|
|
1675
|
+
case "base.float[]": {
|
|
1612
1676
|
value = parseArray(String(raw), (x) => Number(x));
|
|
1613
1677
|
break;
|
|
1614
1678
|
}
|
|
1615
|
-
case "bool[]": {
|
|
1679
|
+
case "base.bool[]": {
|
|
1616
1680
|
value = parseArray(String(raw), (x) => /^(true|1)$/i.test(x));
|
|
1617
1681
|
break;
|
|
1618
1682
|
}
|
|
1619
|
-
case "vec3": {
|
|
1683
|
+
case "base.vec3": {
|
|
1620
1684
|
const arr = parseArray(String(raw), (x) => Number(x));
|
|
1621
1685
|
value = [arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0];
|
|
1622
1686
|
break;
|
|
1623
1687
|
}
|
|
1624
|
-
case "vec3[]": {
|
|
1688
|
+
case "base.vec3[]": {
|
|
1625
1689
|
try {
|
|
1626
1690
|
const parsed = JSON.parse(String(raw));
|
|
1627
1691
|
if (Array.isArray(parsed)) {
|
|
@@ -1653,13 +1717,13 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1653
1717
|
const toDisplay = useCallback((typeId, value) => {
|
|
1654
1718
|
if (value === undefined || value === null)
|
|
1655
1719
|
return "";
|
|
1656
|
-
if (typeId && typeId.
|
|
1720
|
+
if (typeId && typeId.includes("enum:")) {
|
|
1657
1721
|
const n = Number(value);
|
|
1658
1722
|
const label = registry.getEnumLabel(typeId, n);
|
|
1659
1723
|
return label ?? String(n);
|
|
1660
1724
|
}
|
|
1661
1725
|
const round4 = (n) => Math.round(Number(n) * 10000) / 10000;
|
|
1662
|
-
if (typeId === "vec3" && Array.isArray(value)) {
|
|
1726
|
+
if (typeId === "base.vec3" && Array.isArray(value)) {
|
|
1663
1727
|
const a = value;
|
|
1664
1728
|
return [round4(a[0] ?? 0), round4(a[1] ?? 0), round4(a[2] ?? 0)].join(",");
|
|
1665
1729
|
}
|