@bian-womp/spark-workbench 0.2.25 → 0.2.26
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 +155 -94
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts +9 -0
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +156 -95
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts +9 -0
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchStudio.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkbenchStudio.d.ts","sourceRoot":"","sources":["../../../../src/misc/WorkbenchStudio.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAejE,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AASvE,OAAO,EAGL,kBAAkB,EACnB,MAAM,4BAA4B,CAAC;AAMpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAGL,oBAAoB,EACpB,YAAY,EAGb,MAAM,yBAAyB,CAAC;AAIjC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACtC;AAizBD,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,cAAc,EACd,SAAS,EACT,MAAM,EACN,QAAQ,GACT,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,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,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,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,EAAE,EAAE,iBAAiB,CAAC;QACtB,MAAM,EAAE,YAAY,CAAC;QACrB,eAAe,EAAE,CACf,GAAG,EAAE,eAAe,EACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;KACpB,KAAK,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAChB,GAAG,EAAE,eAAe,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACjD,KAAK,IAAI,CAAC;CACZ,2CAmFA"}
|
|
@@ -13,6 +13,10 @@ export declare class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
13
13
|
runtimeTypeId?: string;
|
|
14
14
|
}>;
|
|
15
15
|
listenersBound: boolean;
|
|
16
|
+
private registryFetched;
|
|
17
|
+
private registryFetching;
|
|
18
|
+
private readonly MAX_REGISTRY_FETCH_ATTEMPTS;
|
|
19
|
+
private readonly INITIAL_RETRY_DELAY_MS;
|
|
16
20
|
constructor(registry: Registry, backend: RemoteExecutionBackend);
|
|
17
21
|
build(def: GraphDefinition): void;
|
|
18
22
|
update(def: GraphDefinition): void;
|
|
@@ -31,6 +35,11 @@ export declare class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
31
35
|
getOutputs(def: GraphDefinition): Record<string, Record<string, unknown>>;
|
|
32
36
|
getInputs(def: GraphDefinition): Record<string, Record<string, unknown>>;
|
|
33
37
|
dispose(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Fetch full registry description from remote and register it locally.
|
|
40
|
+
* Called automatically on first connection with retry mechanism.
|
|
41
|
+
*/
|
|
42
|
+
private fetchRegistry;
|
|
34
43
|
protected ensureRemoteRunner(): Promise<RemoteRunner>;
|
|
35
44
|
}
|
|
36
45
|
//# sourceMappingURL=RemoteGraphRunner.d.ts.map
|
|
@@ -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,EAEL,YAAY,EAEb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EAEtB,eAAe,EACf,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,YAAY,CAAC;IAChC,SAAS,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IAEtC,UAAU;YAEF,OAAO,GAAG,QAAQ;eAAS,OAAO;wBAAkB,MAAM;OAC9D;IACJ,cAAc,UAAS;
|
|
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,EAEL,YAAY,EAEb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EAEtB,eAAe,EACf,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,YAAY,CAAC;IAChC,SAAS,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IAEtC,UAAU;YAEF,OAAO,GAAG,QAAQ;eAAS,OAAO;wBAAkB,MAAM;OAC9D;IACJ,cAAc,UAAS;IACvB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAK;IACjD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;gBAEnC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB;IA8D/D,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAIjC,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAWlC,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAyDjD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,KAAK,IAAI,IAAI;IAIb,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;IAKpD,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;IAWvE,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAOrD,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;IAmBxE,OAAO,IAAI,IAAI;IAaf;;;OAGG;YACW,aAAa;cA6HX,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC;CAuD5D"}
|
package/lib/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, isTypedOutput, getTypedOutputValue, getTypedOutputTypeId, isInputPrivate, getInputTypeId, createSimpleGraphRegistry, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry
|
|
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 { HttpPollingTransport, WebSocketTransport, RemoteRunner } from '@bian-womp/spark-remote';
|
|
3
3
|
import React, { useCallback, useState, useRef, useEffect, useMemo, createContext, useContext, useImperativeHandle } from 'react';
|
|
4
4
|
import { Position, Handle, useUpdateNodeInternals, useReactFlow, ReactFlowProvider, ReactFlow, Background, BackgroundVariant, MiniMap, Controls } from '@xyflow/react';
|
|
@@ -570,6 +570,10 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
570
570
|
super(registry, backend);
|
|
571
571
|
this.valueCache = new Map();
|
|
572
572
|
this.listenersBound = false;
|
|
573
|
+
this.registryFetched = false;
|
|
574
|
+
this.registryFetching = false;
|
|
575
|
+
this.MAX_REGISTRY_FETCH_ATTEMPTS = 3;
|
|
576
|
+
this.INITIAL_RETRY_DELAY_MS = 1000; // 1 second
|
|
573
577
|
// Auto-handle registry-changed invalidations from remote
|
|
574
578
|
// We listen on invalidate and if reason matches, we rehydrate registry and emit a registry event
|
|
575
579
|
this.ensureRemoteRunner().then(async (runner) => {
|
|
@@ -804,11 +808,125 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
804
808
|
super.dispose();
|
|
805
809
|
this.runner = undefined;
|
|
806
810
|
this.transport = undefined;
|
|
811
|
+
this.registryFetched = false; // Reset so registry is fetched again on reconnect
|
|
812
|
+
this.registryFetching = false; // Reset fetching state
|
|
807
813
|
this.emit("transport", {
|
|
808
814
|
state: "disconnected",
|
|
809
815
|
kind: this.backend.kind,
|
|
810
816
|
});
|
|
811
817
|
}
|
|
818
|
+
/**
|
|
819
|
+
* Fetch full registry description from remote and register it locally.
|
|
820
|
+
* Called automatically on first connection with retry mechanism.
|
|
821
|
+
*/
|
|
822
|
+
async fetchRegistry(runner, attempt = 1) {
|
|
823
|
+
if (this.registryFetching) {
|
|
824
|
+
// Already fetching, don't start another fetch
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
this.registryFetching = true;
|
|
828
|
+
try {
|
|
829
|
+
const desc = await runner.describeRegistry();
|
|
830
|
+
// Register types
|
|
831
|
+
for (const t of desc.types) {
|
|
832
|
+
if (t.options) {
|
|
833
|
+
this.registry.registerEnum({
|
|
834
|
+
id: t.id,
|
|
835
|
+
options: t.options,
|
|
836
|
+
bakeTarget: t.bakeTarget,
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
if (!this.registry.types.has(t.id)) {
|
|
841
|
+
this.registry.registerType({
|
|
842
|
+
id: t.id,
|
|
843
|
+
displayName: t.displayName,
|
|
844
|
+
validate: (_v) => true,
|
|
845
|
+
bakeTarget: t.bakeTarget,
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
// Register categories
|
|
851
|
+
for (const c of desc.categories || []) {
|
|
852
|
+
if (!this.registry.categories.has(c.id)) {
|
|
853
|
+
// Create placeholder category descriptor
|
|
854
|
+
const category = {
|
|
855
|
+
id: c.id,
|
|
856
|
+
displayName: c.displayName,
|
|
857
|
+
createRuntime: () => ({
|
|
858
|
+
async onInputsChanged() { },
|
|
859
|
+
}),
|
|
860
|
+
policy: { asyncConcurrency: "switch" },
|
|
861
|
+
};
|
|
862
|
+
this.registry.categories.register(category);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
// Register coercions
|
|
866
|
+
for (const c of desc.coercions) {
|
|
867
|
+
if (c.async) {
|
|
868
|
+
this.registry.registerAsyncCoercion(c.from, c.to, async (v) => v, {
|
|
869
|
+
nonTransitive: c.nonTransitive,
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
this.registry.registerCoercion(c.from, c.to, (v) => v, {
|
|
874
|
+
nonTransitive: c.nonTransitive,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
// Register nodes
|
|
879
|
+
for (const n of desc.nodes) {
|
|
880
|
+
if (!this.registry.nodes.has(n.id)) {
|
|
881
|
+
this.registry.registerNode({
|
|
882
|
+
id: n.id,
|
|
883
|
+
categoryId: n.categoryId,
|
|
884
|
+
displayName: n.displayName,
|
|
885
|
+
inputs: n.inputs || {},
|
|
886
|
+
outputs: n.outputs || {},
|
|
887
|
+
impl: () => { },
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
this.registryFetched = true;
|
|
892
|
+
this.registryFetching = false;
|
|
893
|
+
this.emit("registry", this.registry);
|
|
894
|
+
}
|
|
895
|
+
catch (err) {
|
|
896
|
+
this.registryFetching = false;
|
|
897
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
898
|
+
// Retry with exponential backoff if attempts remaining
|
|
899
|
+
if (attempt < this.MAX_REGISTRY_FETCH_ATTEMPTS) {
|
|
900
|
+
const delayMs = this.INITIAL_RETRY_DELAY_MS * Math.pow(2, attempt - 1);
|
|
901
|
+
console.warn(`Failed to fetch registry (attempt ${attempt}/${this.MAX_REGISTRY_FETCH_ATTEMPTS}), retrying in ${delayMs}ms...`, error);
|
|
902
|
+
// Emit error event for UI feedback
|
|
903
|
+
this.emit("error", {
|
|
904
|
+
kind: "registry",
|
|
905
|
+
message: `Registry fetch failed (attempt ${attempt}/${this.MAX_REGISTRY_FETCH_ATTEMPTS}), retrying...`,
|
|
906
|
+
err: error,
|
|
907
|
+
attempt,
|
|
908
|
+
maxAttempts: this.MAX_REGISTRY_FETCH_ATTEMPTS,
|
|
909
|
+
});
|
|
910
|
+
// Retry after delay
|
|
911
|
+
setTimeout(() => {
|
|
912
|
+
this.fetchRegistry(runner, attempt + 1).catch(() => {
|
|
913
|
+
// Final failure handled below
|
|
914
|
+
});
|
|
915
|
+
}, delayMs);
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
// Max attempts reached, emit final error
|
|
919
|
+
console.error(`Failed to fetch registry after ${this.MAX_REGISTRY_FETCH_ATTEMPTS} attempts:`, error);
|
|
920
|
+
this.emit("error", {
|
|
921
|
+
kind: "registry",
|
|
922
|
+
message: `Failed to fetch registry after ${this.MAX_REGISTRY_FETCH_ATTEMPTS} attempts. Please check your connection and try refreshing.`,
|
|
923
|
+
err: error,
|
|
924
|
+
attempt: this.MAX_REGISTRY_FETCH_ATTEMPTS,
|
|
925
|
+
maxAttempts: this.MAX_REGISTRY_FETCH_ATTEMPTS,
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
812
930
|
// Ensure remote transport/runner
|
|
813
931
|
async ensureRemoteRunner() {
|
|
814
932
|
if (this.runner)
|
|
@@ -854,6 +972,14 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
854
972
|
this.valueCache.clear();
|
|
855
973
|
this.listenersBound = false;
|
|
856
974
|
this.emit("transport", { state: "connected", kind });
|
|
975
|
+
// Auto-fetch registry on first connection (only once)
|
|
976
|
+
if (!this.registryFetched && !this.registryFetching) {
|
|
977
|
+
// Log loading state (UI can listen to transport status for loading indication)
|
|
978
|
+
console.info("Loading registry from remote...");
|
|
979
|
+
this.fetchRegistry(runner).catch(() => {
|
|
980
|
+
// Error handling is done inside fetchRegistry
|
|
981
|
+
});
|
|
982
|
+
}
|
|
857
983
|
return runner;
|
|
858
984
|
}
|
|
859
985
|
}
|
|
@@ -2970,7 +3096,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
2970
3096
|
}, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", fitView: true, children: [jsx(Background, { id: "workbench-canvas-background", variant: BackgroundVariant.Dots, gap: 12, size: 1 }), jsx(MiniMap, {}), jsx(Controls, {}), jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, onAdd: addNodeAt, onClose: onCloseMenu }), !!nodeAtMenu && (jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, onClose: onCloseNodeMenu }))] }) }) }));
|
|
2971
3097
|
});
|
|
2972
3098
|
|
|
2973
|
-
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
3099
|
+
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, backendOptions, overrides, onInit, onChange, }) {
|
|
2974
3100
|
const { wb, runner, registry, def, selectedNodeId, runAutoLayout } = useWorkbenchContext();
|
|
2975
3101
|
const [transportStatus, setTransportStatus] = useState({
|
|
2976
3102
|
state: "local",
|
|
@@ -3019,11 +3145,14 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3019
3145
|
return overrides.getExamples(defaultExamples);
|
|
3020
3146
|
return defaultExamples;
|
|
3021
3147
|
}, [overrides, defaultExamples]);
|
|
3022
|
-
const [hydrated, setHydrated] = useState(false);
|
|
3023
3148
|
const lastAutoLaunched = useRef(undefined);
|
|
3024
3149
|
const autoLayoutRan = useRef(false);
|
|
3025
3150
|
const canvasRef = useRef(null);
|
|
3026
3151
|
const uploadInputRef = useRef(null);
|
|
3152
|
+
const [registryReady, setRegistryReady] = useState(() => {
|
|
3153
|
+
// For local backends, registry is always ready
|
|
3154
|
+
return backendKind === "local";
|
|
3155
|
+
});
|
|
3027
3156
|
// Expose init callback with setInitialGraph helper
|
|
3028
3157
|
const initCalled = useRef(false);
|
|
3029
3158
|
useEffect(() => {
|
|
@@ -3082,7 +3211,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3082
3211
|
const { registry: r, def } = await ex.load();
|
|
3083
3212
|
// Keep registry consistent with backend:
|
|
3084
3213
|
// - For local backend, allow example to provide its own registry
|
|
3085
|
-
// - For remote backend,
|
|
3214
|
+
// - For remote backend, registry is automatically managed by RemoteGraphRunner
|
|
3086
3215
|
if (backendKind === "local") {
|
|
3087
3216
|
if (r) {
|
|
3088
3217
|
setRegistry(r);
|
|
@@ -3195,79 +3324,8 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3195
3324
|
const triggerUpload = useCallback(() => {
|
|
3196
3325
|
uploadInputRef.current?.click();
|
|
3197
3326
|
}, []);
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
const transport = kind === "remote-http"
|
|
3201
|
-
? new HttpPollingTransport(base)
|
|
3202
|
-
: new WebSocketTransport(base);
|
|
3203
|
-
await transport.connect();
|
|
3204
|
-
const rr = new RemoteRunner(transport);
|
|
3205
|
-
const desc = await rr.describeRegistry();
|
|
3206
|
-
const r = new Registry();
|
|
3207
|
-
// Types
|
|
3208
|
-
for (const t of desc.types) {
|
|
3209
|
-
if (t.options) {
|
|
3210
|
-
r.registerEnum({
|
|
3211
|
-
id: t.id,
|
|
3212
|
-
options: t.options,
|
|
3213
|
-
bakeTarget: t.bakeTarget,
|
|
3214
|
-
});
|
|
3215
|
-
}
|
|
3216
|
-
else {
|
|
3217
|
-
r.registerType({
|
|
3218
|
-
id: t.id,
|
|
3219
|
-
displayName: t.displayName,
|
|
3220
|
-
validate: (_v) => true,
|
|
3221
|
-
bakeTarget: t.bakeTarget,
|
|
3222
|
-
});
|
|
3223
|
-
}
|
|
3224
|
-
}
|
|
3225
|
-
// Categories: create placeholders for display name
|
|
3226
|
-
for (const c of desc.categories || []) {
|
|
3227
|
-
// If you later expose real category descriptors, register them here
|
|
3228
|
-
// For now, rely on ComputeCategory for behavior
|
|
3229
|
-
const category = {
|
|
3230
|
-
id: c.id,
|
|
3231
|
-
displayName: c.displayName,
|
|
3232
|
-
createRuntime: () => ({
|
|
3233
|
-
async onInputsChanged() { },
|
|
3234
|
-
}),
|
|
3235
|
-
policy: { asyncConcurrency: "switch" },
|
|
3236
|
-
};
|
|
3237
|
-
r.categories.register(category);
|
|
3238
|
-
}
|
|
3239
|
-
// Coercions (client-side no-op to satisfy validation) if provided
|
|
3240
|
-
for (const c of desc.coercions) {
|
|
3241
|
-
if (c.async) {
|
|
3242
|
-
r.registerAsyncCoercion(c.from, c.to, async (v) => v, {
|
|
3243
|
-
nonTransitive: c.nonTransitive,
|
|
3244
|
-
});
|
|
3245
|
-
}
|
|
3246
|
-
else {
|
|
3247
|
-
r.registerCoercion(c.from, c.to, (v) => v, {
|
|
3248
|
-
nonTransitive: c.nonTransitive,
|
|
3249
|
-
});
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
// Nodes (use no-op impl for compute)
|
|
3253
|
-
for (const n of desc.nodes) {
|
|
3254
|
-
r.registerNode({
|
|
3255
|
-
id: n.id,
|
|
3256
|
-
categoryId: n.categoryId,
|
|
3257
|
-
displayName: n.displayName,
|
|
3258
|
-
inputs: n.inputs || {},
|
|
3259
|
-
outputs: n.outputs || {},
|
|
3260
|
-
impl: () => { },
|
|
3261
|
-
});
|
|
3262
|
-
}
|
|
3263
|
-
setRegistry(r);
|
|
3264
|
-
wb.setRegistry(r);
|
|
3265
|
-
await transport.close();
|
|
3266
|
-
}
|
|
3267
|
-
catch (err) {
|
|
3268
|
-
console.error("Failed to hydrate registry from backend:", err);
|
|
3269
|
-
}
|
|
3270
|
-
}, [setRegistry, wb]);
|
|
3327
|
+
// Registry is now automatically fetched by RemoteGraphRunner on first connection
|
|
3328
|
+
// No need for manual hydration
|
|
3271
3329
|
// Ensure initial example is loaded (and sync when example prop changes)
|
|
3272
3330
|
useEffect(() => {
|
|
3273
3331
|
if (!example)
|
|
@@ -3278,6 +3336,21 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3278
3336
|
const off = runner.on("transport", (s) => setTransportStatus(s));
|
|
3279
3337
|
return () => off();
|
|
3280
3338
|
}, [runner]);
|
|
3339
|
+
// Track registry readiness for remote backends
|
|
3340
|
+
useEffect(() => {
|
|
3341
|
+
// For local backends, registry is always ready
|
|
3342
|
+
if (backendKind === "local") {
|
|
3343
|
+
setRegistryReady(true);
|
|
3344
|
+
return;
|
|
3345
|
+
}
|
|
3346
|
+
// Reset readiness when switching to remote backend
|
|
3347
|
+
setRegistryReady(false);
|
|
3348
|
+
// For remote backends, wait for registry event
|
|
3349
|
+
const off = runner.on("registry", () => {
|
|
3350
|
+
setRegistryReady(true);
|
|
3351
|
+
});
|
|
3352
|
+
return () => off();
|
|
3353
|
+
}, [runner, backendKind]);
|
|
3281
3354
|
useEffect(() => {
|
|
3282
3355
|
if (!engine)
|
|
3283
3356
|
return;
|
|
@@ -3299,25 +3372,13 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3299
3372
|
// ignore
|
|
3300
3373
|
}
|
|
3301
3374
|
}, [engine, runner, wb, backendKind]);
|
|
3302
|
-
//
|
|
3303
|
-
|
|
3304
|
-
let hydrate;
|
|
3305
|
-
if (backendKind === "remote-http" && httpBaseUrl) {
|
|
3306
|
-
hydrate = hydrateFromBackend("remote-http", httpBaseUrl);
|
|
3307
|
-
}
|
|
3308
|
-
else if (backendKind === "remote-ws" && wsUrl) {
|
|
3309
|
-
hydrate = hydrateFromBackend("remote-ws", wsUrl);
|
|
3310
|
-
}
|
|
3311
|
-
if (hydrate) {
|
|
3312
|
-
hydrate.then(() => {
|
|
3313
|
-
setHydrated(true);
|
|
3314
|
-
});
|
|
3315
|
-
}
|
|
3316
|
-
}, [backendKind, httpBaseUrl, wsUrl, hydrateFromBackend, setHydrated]);
|
|
3375
|
+
// Registry is automatically fetched by RemoteGraphRunner when it connects
|
|
3376
|
+
// Run auto layout after registry is hydrated (for remote backends)
|
|
3317
3377
|
useEffect(() => {
|
|
3318
3378
|
if (autoLayoutRan.current)
|
|
3319
3379
|
return;
|
|
3320
|
-
|
|
3380
|
+
// Wait for registry to be ready for remote backends
|
|
3381
|
+
if (backendKind !== "local" && !registryReady)
|
|
3321
3382
|
return;
|
|
3322
3383
|
const cur = wb.export();
|
|
3323
3384
|
const positions = wb.getPositions();
|
|
@@ -3326,7 +3387,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
3326
3387
|
autoLayoutRan.current = true;
|
|
3327
3388
|
runAutoLayout();
|
|
3328
3389
|
}
|
|
3329
|
-
}, [wb, runAutoLayout, backendKind,
|
|
3390
|
+
}, [wb, runAutoLayout, backendKind, registryReady, registry]);
|
|
3330
3391
|
const baseSetInput = useCallback((handle, raw) => {
|
|
3331
3392
|
if (!selectedNodeId)
|
|
3332
3393
|
return;
|
|
@@ -3582,7 +3643,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
|
|
|
3582
3643
|
if (runner.isRunning())
|
|
3583
3644
|
runner.dispose();
|
|
3584
3645
|
onBackendKindChange(v);
|
|
3585
|
-
}, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, overrides: overrides, onInit: onInit, onChange: onChange }) }));
|
|
3646
|
+
}, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, backendOptions: backendOptions, overrides: overrides, onInit: onInit, onChange: onChange }) }));
|
|
3586
3647
|
}
|
|
3587
3648
|
|
|
3588
3649
|
export { AbstractWorkbench, CLIWorkbench, DefaultNode, DefaultNodeContent, DefaultNodeHeader, DefaultUIExtensionRegistry, InMemoryWorkbench, Inspector, LocalGraphRunner, NodeHandles, RemoteGraphRunner, WorkbenchCanvas, WorkbenchContext, WorkbenchProvider, WorkbenchStudio, formatDataUrlAsLabel, formatDeclaredTypeSignature, getNodeBorderClassNames, preformatValueForDisplay, resolveOutputDisplay, summarizeDeep, toReactFlow, useQueryParamBoolean, useQueryParamString, useThrottledValue, useWorkbenchBridge, useWorkbenchContext, useWorkbenchGraphTick, useWorkbenchGraphUiTick, useWorkbenchVersionTick };
|