@bian-womp/spark-workbench 0.1.17 → 0.1.19

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.
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultNode.d.ts","sourceRoot":"","sources":["../../../../src/misc/DefaultNode.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAO7D,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA8M3C,CAAC"}
1
+ {"version":3,"file":"DefaultNode.d.ts","sourceRoot":"","sources":["../../../../src/misc/DefaultNode.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAO7D,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA2N3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAMA,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,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,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACvD,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;IAC7D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,2CAqWA"}
1
+ {"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAOA,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,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,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACvD,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;IAC7D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,2CAuWA"}
@@ -1,6 +1,10 @@
1
- export declare function WorkbenchCanvas({ showValues, toString, toElement, }: {
1
+ import React from "react";
2
+ export type WorkbenchCanvasHandle = {
3
+ fitView: () => void;
4
+ };
5
+ export declare const WorkbenchCanvas: React.ForwardRefExoticComponent<{
2
6
  showValues?: boolean;
3
7
  toString: (typeId?: string, value?: unknown) => string;
4
8
  toElement: (typeId?: string, value?: unknown) => JSX.Element;
5
- }): import("react/jsx-runtime").JSX.Element;
9
+ } & React.RefAttributes<WorkbenchCanvasHandle>>;
6
10
  //# sourceMappingURL=WorkbenchCanvas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkbenchCanvas.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchCanvas.tsx"],"names":[],"mappings":"AASA,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,QAAQ,EACR,SAAS,GACV,EAAE;IACD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IACvD,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;CAC9D,2CA6IA"}
1
+ {"version":3,"file":"WorkbenchCanvas.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchCanvas.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAS9E,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,eAAe;iBAGX,OAAO;cACV,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM;eAC3C,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO;+CA0J9D,CAAC"}
@@ -24,6 +24,7 @@ type WorkbenchOverrides = {
24
24
  }) => (handle: string, raw: string | number | undefined) => void;
25
25
  registerUI?: (baseRegisterUI: (wb: AbstractWorkbench) => void, ctx: {
26
26
  wb: AbstractWorkbench;
27
+ wbRunner: GraphRunner;
27
28
  }) => void;
28
29
  getExamples?: (defaults: ExampleDescriptor[]) => ExampleDescriptor[];
29
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchStudio.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchStudio.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,QAAQ,EACR,eAAe,EAWhB,MAAM,wBAAwB,CAAC;AAahC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EACL,UAAU,EAEV,oBAAoB,EACpB,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAEhC,KAAK,iBAAiB,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,MAAM,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IACnE,aAAa,CAAC,EAAE,UAAU,CAAC;CAC5B,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,EAAE,CACT,YAAY,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,EAC1D,GAAG,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KACxB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAClD,SAAS,CAAC,EAAE,CACV,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,EAChE,GAAG,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KACxB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;IACvD,QAAQ,CAAC,EAAE,CACT,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,EACxE,GAAG,EAAE;QACH,MAAM,EAAE,WAAW,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,QAAQ,CAAC;KAEpB,KACE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAChE,UAAU,CAAC,EAAE,CACX,cAAc,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,IAAI,EAC/C,GAAG,EAAE;QAAE,EAAE,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAA;KAAE,KAClD,IAAI,CAAC;IAEV,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,CAAC;CACtE,CAAC;AAonBF,wBAAgB,eAAe,CAAC,EAC9B,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,EAClB,SAAS,GACV,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,oBAAoB,CAAC;IAClC,mBAAmB,EAAE,CAAC,CAAC,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACvD,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;IACzC,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC,2CAyDA"}
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../src/misc/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,qBAAqB,EACtB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,iBAAiB;;;;;;;EA0EvD;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,iBAAiB,UAS1D;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,iBAAiB,UAS5D;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,UAoB1D;AAWD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,OAAO,GACpB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,CA0BjC;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GACpB,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,CAyBvD"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../src/misc/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,qBAAqB,EACtB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,iBAAiB;;;;;;;EAoFvD;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,iBAAiB,UAS1D;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,iBAAiB,UAS5D;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,UAoB1D;AAWD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,OAAO,GACpB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC,CA0BjC;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GACpB,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,CAyBvD"}
@@ -1,4 +1,4 @@
1
- import type { GraphDefinition, Registry } from "@bian-womp/spark-graph";
1
+ import { type GraphDefinition, type Registry } from "@bian-womp/spark-graph";
2
2
  import type { EdgeRunStatus, NodeRunStatus } from "../core/contracts";
3
3
  import type { SimpleIssue, HandleIssue } from "../core/contracts";
4
4
  export interface RFNode {
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/misc/mapping.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/misc/mapping.ts"],"names":[],"mappings":"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"}
@@ -5,5 +5,5 @@ export declare function resolveOutputDisplay(raw: unknown, declared: string | st
5
5
  };
6
6
  export declare function formatDeclaredTypeSignature(declared: string | string[] | undefined): string;
7
7
  export declare function preformatValueForDisplay(typeId: string | undefined, value: unknown, registry?: Registry): string | undefined;
8
- export declare function summarizeDeep(value: unknown, registry?: Registry): unknown;
8
+ export declare function summarizeDeep(value: unknown): unknown;
9
9
  //# sourceMappingURL=value.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"value.d.ts","sourceRoot":"","sources":["../../../../src/misc/value.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACtC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAWrC;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACtC,MAAM,CAGR;AAGD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,GAAG,SAAS,CA8BpB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAqD1E"}
1
+ {"version":3,"file":"value.d.ts","sourceRoot":"","sources":["../../../../src/misc/value.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACtC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAWrC;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GACtC,MAAM,CAGR;AAGD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,GAAG,SAAS,CA8BpB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAqDrD"}
package/lib/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, isTypedOutput, createSimpleGraphRegistry, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, Registry } from '@bian-womp/spark-graph';
1
+ import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, isTypedOutput, isInputPrivate, getInputTypeId, createSimpleGraphRegistry, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, Registry } from '@bian-womp/spark-graph';
2
2
  import { RemoteEngine, HttpPollingTransport, WebSocketTransport, RemoteRunner } from '@bian-womp/spark-remote';
3
- import React, { useCallback, useState, useEffect, useMemo, createContext, useContext, useRef } from 'react';
3
+ import React, { useCallback, useState, useEffect, useMemo, createContext, useContext, useRef, useImperativeHandle } from 'react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
  import { XCircleIcon, WarningCircleIcon } from '@phosphor-icons/react';
6
6
  import ReactFlow, { Handle, Position, useReactFlow, Background, MiniMap, Controls } from 'reactflow';
@@ -657,6 +657,14 @@ function useWorkbenchBridge(wb) {
657
657
  return;
658
658
  if (!params.sourceHandle || !params.targetHandle)
659
659
  return;
660
+ // Prevent duplicate edges between the same endpoints
661
+ const def = wb.export();
662
+ const exists = def.edges.some((e) => e.source.nodeId === params.source &&
663
+ e.source.handle === params.sourceHandle &&
664
+ e.target.nodeId === params.target &&
665
+ e.target.handle === params.targetHandle);
666
+ if (exists)
667
+ return;
660
668
  wb.connect({
661
669
  source: { nodeId: params.source, handle: params.sourceHandle },
662
670
  target: { nodeId: params.target, handle: params.targetHandle },
@@ -855,7 +863,7 @@ function preformatValueForDisplay(typeId, value, registry) {
855
863
  }
856
864
  return undefined;
857
865
  }
858
- function summarizeDeep(value, registry) {
866
+ function summarizeDeep(value) {
859
867
  // Strings: summarize data URLs and trim extremely long strings
860
868
  if (typeof value === "string") {
861
869
  if (value.startsWith("data:")) {
@@ -914,7 +922,9 @@ function toReactFlow(def, positions, registry, opts) {
914
922
  const nodeHandleMap = {};
915
923
  const nodes = def.nodes.map((n) => {
916
924
  const desc = registry.nodes.get(n.typeId);
917
- const inputHandles = Object.entries(desc?.inputs ?? {}).map(([id, typeId]) => ({ id, typeId }));
925
+ const inputHandles = Object.entries(desc?.inputs ?? {})
926
+ .filter(([id]) => !isInputPrivate(desc?.inputs, id))
927
+ .map(([id, v]) => ({ id, typeId: getInputTypeId(desc?.inputs, id) }));
918
928
  const outputHandles = Object.entries(desc?.outputs ?? {}).map(([id, typeId]) => ({ id, typeId: formatDeclaredTypeSignature(typeId) }));
919
929
  nodeHandleMap[n.nodeId] = {
920
930
  inputs: new Set(inputHandles.map((h) => h.id)),
@@ -1108,8 +1118,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, children, }) {
1108
1118
  layers.push(layer);
1109
1119
  q.splice(0, q.length, ...next);
1110
1120
  }
1111
- const X = 480;
1112
- const Y = 240;
1121
+ const X = 960;
1122
+ const Y = 480;
1113
1123
  const pos = {};
1114
1124
  layers.forEach((layer, layerIndex) => {
1115
1125
  layer.forEach((id, itemIndex) => {
@@ -1519,7 +1529,9 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
1519
1529
  const selectedDesc = selectedNode
1520
1530
  ? registry.nodes.get(selectedNode.typeId)
1521
1531
  : undefined;
1522
- const inputHandles = Object.keys(selectedDesc?.inputs ?? {});
1532
+ const inputHandles = Object.entries(selectedDesc?.inputs ?? {})
1533
+ .filter(([k]) => !isInputPrivate(selectedDesc?.inputs, k))
1534
+ .map(([k]) => k);
1523
1535
  const outputHandles = Object.keys(selectedDesc?.outputs ?? {});
1524
1536
  const nodeInputs = selectedNodeId ? inputsMap[selectedNodeId] ?? {} : {};
1525
1537
  const nodeOutputs = selectedNodeId ? outputsMap[selectedNodeId] ?? {} : {};
@@ -1566,7 +1578,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
1566
1578
  const nextDrafts = { ...drafts };
1567
1579
  const nextOriginals = { ...originals };
1568
1580
  for (const h of handles) {
1569
- const typeId = desc?.inputs?.[h];
1581
+ const typeId = getInputTypeId(desc?.inputs, h);
1570
1582
  const current = nodeInputs[h];
1571
1583
  const display = safeToString(typeId, current);
1572
1584
  const wasOriginal = originals[h];
@@ -1586,7 +1598,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
1586
1598
  const widthClass = debug ? "w-[480px]" : "w-[320px]";
1587
1599
  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 ??
1588
1600
  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) => {
1589
- const typeId = (selectedDesc?.inputs ?? {})[h];
1601
+ const typeId = getInputTypeId(selectedDesc?.inputs, h);
1590
1602
  const isLinked = def.edges.some((e) => e.target.nodeId === selectedNodeId &&
1591
1603
  e.target.handle === h);
1592
1604
  const commonProps = {
@@ -1614,7 +1626,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
1614
1626
  const title = inIssues
1615
1627
  .map((v) => `${v.code}: ${v.message}`)
1616
1628
  .join("; ");
1617
- return (jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxs("label", { className: "w-32", children: [h, jsx("span", { className: "text-gray-500 ml-1 text-[11px]", children: selectedDesc?.inputs?.[h] })] }), hasValidation && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 w-full", value: current !== undefined && current !== null
1629
+ return (jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxs("label", { className: "w-32 flex flex-col", children: [jsx("span", { children: h }), jsx("span", { className: "text-gray-500 text-[11px]", children: typeId })] }), hasValidation && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 w-full", value: current !== undefined && current !== null
1618
1630
  ? String(current)
1619
1631
  : "", onChange: (e) => {
1620
1632
  const val = e.target.value;
@@ -1659,7 +1671,7 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
1659
1671
  const ROW_SIZE = 22;
1660
1672
  const maxRows = Math.max(inputEntries.length, outputEntries.length);
1661
1673
  const minHeight = HEADER_SIZE + maxRows * ROW_SIZE;
1662
- const minWidth = data.showValues ? 320 : 160;
1674
+ const minWidth = data.showValues ? 320 : 240;
1663
1675
  const topFor = (i) => HEADER_SIZE + i * ROW_SIZE + ROW_SIZE / 2;
1664
1676
  const hasError = !!status.lastError;
1665
1677
  const hasValidationError = validation.issues.some((i) => i.level === "error");
@@ -1692,7 +1704,13 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
1692
1704
  const title = vIssues
1693
1705
  .map((v) => `${v.code}: ${v.message}`)
1694
1706
  .join("; ");
1695
- return (jsxs(React.Fragment, { children: [jsx(Handle, { id: entry.id, type: "target", position: Position.Left, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { left: -5, top: topFor(i) } }), jsxs("div", { className: "absolute left-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: { top: topFor(i) - 8 }, title: `${entry.id}: ${entry.typeId}`, children: [entry.id, hasAny && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "ml-1", title: title })), showValues && (jsx("span", { className: "ml-1 opacity-60", children: toString(entry.typeId, inputValues?.[entry.id]) }))] })] }, `in-${entry.id}`));
1707
+ return (jsxs(React.Fragment, { children: [jsx(Handle, { id: entry.id, type: "target", position: Position.Left, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { left: -5, top: topFor(i) } }), jsxs("div", { className: "absolute left-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1708
+ top: topFor(i) - 8,
1709
+ right: "50%",
1710
+ whiteSpace: "nowrap",
1711
+ overflow: "hidden",
1712
+ textOverflow: "ellipsis",
1713
+ }, title: `${entry.id}: ${entry.typeId}`, children: [entry.id, hasAny && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "ml-1", title: title })), showValues && (jsx("span", { className: "ml-1 opacity-60", children: toString(entry.typeId, inputValues?.[entry.id]) }))] })] }, `in-${entry.id}`));
1696
1714
  }), outputEntries.map((entry, i) => {
1697
1715
  const vIssues = validation.outputs.filter((v) => v.handle === entry.id);
1698
1716
  const hasAny = vIssues.length > 0;
@@ -1701,7 +1719,14 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
1701
1719
  .map((v) => `${v.code}: ${v.message}`)
1702
1720
  .join("; ");
1703
1721
  const resolved = resolveOutputDisplay(outputValues?.[entry.id], entry.typeId);
1704
- return (jsxs(React.Fragment, { children: [jsx(Handle, { id: entry.id, type: "source", position: Position.Right, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400 !rounded-none", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { right: -5, top: topFor(i) } }), jsxs("div", { className: "absolute right-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: { top: topFor(i) - 8, textAlign: "right" }, title: `${entry.id}: ${entry.typeId}`, children: [entry.id, resolved.typeId && (jsxs("span", { className: "ml-1 opacity-60", children: ["(", resolved.typeId, ")"] })), hasAny && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "ml-1", title: title })), showValues && (jsx("span", { className: "ml-1 opacity-60", children: toString(resolved.typeId, resolved.value) }))] })] }, `out-${entry.id}`));
1722
+ return (jsxs(React.Fragment, { children: [jsx(Handle, { id: entry.id, type: "source", position: Position.Right, isConnectable: isConnectable, className: cx("!w-3 !h-3 !bg-white !dark:bg-stone-900 !border-gray-500 dark:!border-gray-400 !rounded-none", hasAny && (hasErr ? "!border-red-500" : "!border-amber-500")), style: { right: -5, top: topFor(i) } }), jsxs("div", { className: "absolute right-2 text-[11px] text-gray-700 dark:text-gray-300 pointer-events-none", style: {
1723
+ top: topFor(i) - 8,
1724
+ textAlign: "right",
1725
+ left: "50%",
1726
+ whiteSpace: "nowrap",
1727
+ overflow: "hidden",
1728
+ textOverflow: "ellipsis",
1729
+ }, title: `${entry.id}: ${entry.typeId}`, children: [entry.id, resolved.typeId && (jsxs("span", { className: "ml-1 opacity-60", children: ["(", resolved.typeId, ")"] })), hasAny && (jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "ml-1", title: title })), showValues && (jsx("span", { className: "ml-1 opacity-60", children: toString(resolved.typeId, resolved.value) }))] })] }, `out-${entry.id}`));
1705
1730
  })] }));
1706
1731
  });
1707
1732
  DefaultNode.displayName = "DefaultNode";
@@ -1840,11 +1865,21 @@ function NodeContextMenu({ open, clientPos, nodeId, onClose, }) {
1840
1865
  }, children: [jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleDelete, children: "Delete" }), jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleDuplicate, children: "Duplicate" }), canRunPull && (jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleRunPull, children: "Run (pull)" })), jsx("div", { className: "h-px bg-gray-200 my-1" }), jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleCopyId, children: "Copy Node ID" })] }));
1841
1866
  }
1842
1867
 
1843
- function WorkbenchCanvas({ showValues, toString, toElement, }) {
1868
+ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, ref) => {
1844
1869
  const { wb, registry, inputsMap, outputsMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, } = useWorkbenchContext();
1845
1870
  const ioValues = { inputs: inputsMap, outputs: outputsMap };
1846
1871
  const nodeValidation = validationByNode;
1847
1872
  const edgeValidation = validationByEdge.errors;
1873
+ // Expose imperative API
1874
+ const rfInstanceRef = useRef(null);
1875
+ useImperativeHandle(ref, () => ({
1876
+ fitView: () => {
1877
+ try {
1878
+ rfInstanceRef.current?.fitView({ padding: 0.2 });
1879
+ }
1880
+ catch { }
1881
+ },
1882
+ }));
1848
1883
  const { onConnect, onNodesChange, onEdgesChange, onEdgesDelete, onNodesDelete, onSelectionChange, } = useWorkbenchBridge(wb);
1849
1884
  const { nodeTypes, resolveNodeType } = useMemo(() => {
1850
1885
  // Build nodeTypes map using UI extension registry
@@ -1920,8 +1955,8 @@ function WorkbenchCanvas({ showValues, toString, toElement, }) {
1920
1955
  const addNodeAt = (typeId, pos) => {
1921
1956
  wb.addNode({ typeId, position: pos });
1922
1957
  };
1923
- return (jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxs(ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, selectionOnDrag: true, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onSelectionChange: onSelectionChange, deleteKeyCode: ["Backspace", "Delete"], fitView: true, children: [jsx(Background, {}), jsx(MiniMap, {}), jsx(Controls, {}), jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, onAdd: addNodeAt, onClose: () => setMenuOpen(false) }), jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, onClose: () => setNodeMenuOpen(false) })] }) }));
1924
- }
1958
+ return (jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxs(ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, selectionOnDrag: true, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onSelectionChange: onSelectionChange, deleteKeyCode: ["Backspace", "Delete"], fitView: true, onInit: (inst) => (rfInstanceRef.current = inst), children: [jsx(Background, {}), jsx(MiniMap, {}), jsx(Controls, {}), jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, onAdd: addNodeAt, onClose: () => setMenuOpen(false) }), jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, onClose: () => setNodeMenuOpen(false) })] }) }));
1959
+ });
1925
1960
 
1926
1961
  function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, }) {
1927
1962
  const { wb, runner, registry, def, selectedNodeId, runAutoLayout } = useWorkbenchContext();
@@ -1929,7 +1964,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
1929
1964
  const selectedDesc = selectedNode
1930
1965
  ? registry.nodes.get(selectedNode.typeId)
1931
1966
  : undefined;
1932
- const [exampleState, setExampleState] = useState(example ?? "simple");
1967
+ const [exampleState, setExampleState] = useState(example ?? "");
1933
1968
  const defaultExamples = useMemo(() => [
1934
1969
  {
1935
1970
  id: "simple",
@@ -1971,6 +2006,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
1971
2006
  }, [overrides, defaultExamples]);
1972
2007
  const lastAutoLaunched = useRef(undefined);
1973
2008
  const autoLayoutRan = useRef(false);
2009
+ const canvasRef = useRef(null);
1974
2010
  const applyExample = useCallback(async (key) => {
1975
2011
  if (runner.isRunning()) {
1976
2012
  alert(`Stop engine before switching example.`);
@@ -1991,6 +2027,27 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
1991
2027
  setExampleState(key);
1992
2028
  onExampleChange?.(key);
1993
2029
  }, [runner, wb, onExampleChange, runAutoLayout, examples, setRegistry]);
2030
+ const downloadGraph = useCallback(() => {
2031
+ try {
2032
+ const def = wb.export();
2033
+ const pretty = JSON.stringify(def, null, 2);
2034
+ const blob = new Blob([pretty], { type: "application/json" });
2035
+ const url = URL.createObjectURL(blob);
2036
+ const a = document.createElement("a");
2037
+ const d = new Date();
2038
+ const pad = (n) => String(n).padStart(2, "0");
2039
+ const ts = `${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}`;
2040
+ a.href = url;
2041
+ a.download = `spark-graph-${ts}.json`;
2042
+ document.body.appendChild(a);
2043
+ a.click();
2044
+ a.remove();
2045
+ URL.revokeObjectURL(url);
2046
+ }
2047
+ catch (err) {
2048
+ alert(String(err?.message ?? err));
2049
+ }
2050
+ }, [wb]);
1994
2051
  const hydrateFromBackend = useCallback(async (kind, base) => {
1995
2052
  try {
1996
2053
  const transport = kind === "remote-http"
@@ -2064,7 +2121,9 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2064
2121
  }, [setRegistry, wb]);
2065
2122
  // Ensure initial example is loaded (and sync when example prop changes)
2066
2123
  useEffect(() => {
2067
- applyExample(example ?? "simple");
2124
+ if (!example)
2125
+ return;
2126
+ applyExample(example);
2068
2127
  }, [example, wb]);
2069
2128
  useEffect(() => {
2070
2129
  if (!engine)
@@ -2135,7 +2194,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2135
2194
  break;
2136
2195
  }
2137
2196
  case "base.bool": {
2138
- value = Boolean(raw);
2197
+ value = raw === "true" || raw === "1" ? true : false;
2139
2198
  break;
2140
2199
  }
2141
2200
  case "base.string": {
@@ -2272,14 +2331,14 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2272
2331
  return overrides.toElement(baseToElement, { registry });
2273
2332
  return baseToElement;
2274
2333
  }, [overrides, baseToElement, registry]);
2275
- 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: [runner.isRunning() ? (jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsx("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
2334
+ 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: [runner.isRunning() ? (jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
2276
2335
  ? "Stop engine before switching example"
2277
- : undefined, children: examples.map((ex) => (jsx("option", { value: ex.id, children: ex.label }, ex.id))) }), jsx("label", { className: "ml-2 text-sm", children: "Backend:" }), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
2336
+ : undefined, children: [jsx("option", { value: "", children: "Select Example\u2026" }), examples.map((ex) => (jsx("option", { value: ex.id, children: ex.label }, ex.id)))] }), jsx("label", { className: "ml-2 text-sm", children: "Backend:" }), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
2278
2337
  ? "Stop engine before switching backend"
2279
2338
  : 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" && (jsx("input", { className: "ml-2 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" && (jsx("input", { className: "ml-2 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: runner.getRunningEngine() ?? engine ?? "", onChange: (e) => {
2280
2339
  const kind = e.target.value || undefined;
2281
2340
  onEngineChange?.(kind);
2282
- }, children: [jsx("option", { value: "", children: "Select Engine\u2026" }), jsx("option", { value: "push", children: "Push" }), jsx("option", { value: "batched", children: "Batched" }), jsx("option", { value: "pull", children: "Pull" }), jsx("option", { value: "hybrid", children: "Hybrid" }), jsx("option", { value: "step", children: "Step" })] }), runner.getRunningEngine() === "step" && (jsx("button", { className: "ml-2", onClick: () => runner.step(), disabled: !runner.isRunning(), children: "Step" })), runner.getRunningEngine() === "batched" && (jsx("button", { className: "ml-2", onClick: () => runner.flush(), disabled: !runner.isRunning(), children: "Flush" })), runner.isRunning() ? (jsx("button", { onClick: () => runner.dispose(), disabled: !runner.isRunning(), children: "Stop" })) : (jsx("button", { onClick: () => {
2341
+ }, children: [jsx("option", { value: "", children: "Select Engine\u2026" }), jsx("option", { value: "push", children: "Push" }), jsx("option", { value: "batched", children: "Batched" }), jsx("option", { value: "pull", children: "Pull" }), jsx("option", { value: "hybrid", children: "Hybrid" }), jsx("option", { value: "step", children: "Step" })] }), runner.getRunningEngine() === "step" && (jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.step(), disabled: !runner.isRunning(), children: "Step" })), runner.getRunningEngine() === "batched" && (jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.flush(), disabled: !runner.isRunning(), children: "Flush" })), runner.isRunning() ? (jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: () => runner.dispose(), disabled: !runner.isRunning(), children: "Stop" })) : (jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: () => {
2283
2342
  const kind = engine;
2284
2343
  if (!kind)
2285
2344
  return alert("Select an engine first.");
@@ -2289,7 +2348,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
2289
2348
  catch (err) {
2290
2349
  alert(String(err?.message ?? err));
2291
2350
  }
2292
- }, disabled: !engine, children: "Start" })), jsx("button", { onClick: runAutoLayout, children: "Auto Layout" }), jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsx("span", { children: "Debug events" })] }), jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsx("span", { children: "Show values in nodes" })] })] }), jsxs("div", { className: "flex flex-1 min-h-0", children: [jsx("div", { className: "flex-1 min-w-0", children: jsx(WorkbenchCanvas, { showValues: showValues, toString: toString, toElement: toElement }) }), jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement })] })] }));
2351
+ }, disabled: !engine, children: "Start" })), jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: runAutoLayout, children: "Auto Layout" }), jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: downloadGraph, children: "Download Graph" }), jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsx("span", { children: "Debug events" })] }), jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsx("span", { children: "Show values in nodes" })] })] }), jsxs("div", { className: "flex flex-1 min-h-0", children: [jsx("div", { className: "flex-1 min-w-0", children: jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement }) }), jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement })] })] }));
2293
2352
  }
2294
2353
  function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, }) {
2295
2354
  const [registry, setRegistry] = useState(createSimpleGraphRegistry());
@@ -2305,9 +2364,9 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
2305
2364
  // Allow external UI registration (e.g., node renderers) with access to wb
2306
2365
  useEffect(() => {
2307
2366
  const baseRegisterUI = (_wb) => { };
2308
- overrides?.registerUI?.(baseRegisterUI, { wb });
2367
+ overrides?.registerUI?.(baseRegisterUI, { wb, wbRunner: runner });
2309
2368
  // eslint-disable-next-line react-hooks/exhaustive-deps
2310
- }, [wb, overrides]);
2369
+ }, [wb, runner, overrides]);
2311
2370
  return (jsx(WorkbenchProvider, { wb: wb, runner: runner, registry: registry, setRegistry: setRegistry, children: jsx(WorkbenchStudioCanvas, { setRegistry: setRegistry, autoScroll: autoScroll, onAutoScrollChange: onAutoScrollChange, example: example, onExampleChange: onExampleChange, engine: engine, onEngineChange: onEngineChange, backendKind: backendKind, onBackendKindChange: (v) => {
2312
2371
  if (runner.isRunning())
2313
2372
  runner.dispose();