@bian-womp/spark-workbench 0.2.25 → 0.2.27

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":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAOnD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,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,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,2CAmbA"}
1
+ {"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/misc/Inspector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAOnD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,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,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,2CAggBA"}
@@ -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;AAgBjE,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AASjC,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;AA82BD,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,2CAkFA"}
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;AA+yBD,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,2CA+GA"}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { GraphDefinition } from "@bian-womp/spark-protocol";
2
+ import type { GraphDefinition, RegistryError, SystemError } from "@bian-womp/spark-protocol";
3
3
  import type { Registry, ValidationIssue } from "@bian-womp/spark-graph";
4
4
  import { InMemoryWorkbench } from "../../core/InMemoryWorkbench";
5
5
  import type { HandleIssue, NodeRunStatus, EdgeRunStatus, DebugEvent } from "../../core/contracts";
@@ -67,6 +67,12 @@ export interface WorkbenchContextValue {
67
67
  validationGlobal: ValidationIssue[];
68
68
  events: Array<DebugEvent>;
69
69
  clearEvents: () => void;
70
+ systemErrors: SystemError[];
71
+ registryErrors: RegistryError[];
72
+ clearSystemErrors: () => void;
73
+ clearRegistryErrors: () => void;
74
+ removeSystemError: (index: number) => void;
75
+ removeRegistryError: (index: number) => void;
70
76
  isRunning: () => boolean;
71
77
  engineKind: () => EngineKind | undefined;
72
78
  start: (engine: EngineKind) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkbenchContext.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/WorkbenchContext.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkbenchContext.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/WorkbenchContext.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"WorkbenchContext.provider.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/WorkbenchContext.provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAMf,OAAO,EAAE,KAAK,QAAQ,EAAwB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAmB,MAAM,4BAA4B,CAAC;AAa3E,OAAO,EAGL,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAI5B,wBAAgB,iBAAiB,CAAC,EAChC,EAAE,EACF,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE;IACD,EAAE,EAAE,iBAAiB,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAokBA"}
1
+ {"version":3,"file":"WorkbenchContext.provider.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/WorkbenchContext.provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAQf,OAAO,EAAE,KAAK,QAAQ,EAAwB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAmB,MAAM,4BAA4B,CAAC;AAa3E,OAAO,EAGL,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAI5B,wBAAgB,iBAAiB,CAAC,EAChC,EAAE,EACF,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,QAAQ,GACT,EAAE;IACD,EAAE,EAAE,iBAAiB,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAwnBA"}
@@ -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;gBAEX,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;cAYC,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC;CA6C5D"}
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, Registry } from '@bian-womp/spark-graph';
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
  }
@@ -1519,6 +1645,16 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
1519
1645
  const [edgeStatus, setEdgeStatus] = useState({});
1520
1646
  const [events, setEvents] = useState([]);
1521
1647
  const clearEvents = useCallback(() => setEvents([]), []);
1648
+ const [systemErrors, setSystemErrors] = useState([]);
1649
+ const [registryErrors, setRegistryErrors] = useState([]);
1650
+ const clearSystemErrors = useCallback(() => setSystemErrors([]), []);
1651
+ const clearRegistryErrors = useCallback(() => setRegistryErrors([]), []);
1652
+ const removeSystemError = useCallback((index) => {
1653
+ setSystemErrors((prev) => prev.filter((_, idx) => idx !== index));
1654
+ }, []);
1655
+ const removeRegistryError = useCallback((index) => {
1656
+ setRegistryErrors((prev) => prev.filter((_, idx) => idx !== index));
1657
+ }, []);
1522
1658
  // Fallback progress animation: drive progress to 100% over ~2 minutes
1523
1659
  const FALLBACK_TOTAL_MS = 2 * 60 * 1000;
1524
1660
  const [fallbackStarts, setFallbackStarts] = useState({});
@@ -1701,7 +1837,10 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
1701
1837
  if (remoteDef && Array.isArray(remoteDef.nodes)) {
1702
1838
  // Mutate current def in-place to avoid emitting graphChanged and causing update loop
1703
1839
  const cur = wb.export();
1704
- const byId = new Map((remoteDef.nodes || []).map((n) => [n.nodeId, n]));
1840
+ const byId = new Map((remoteDef.nodes || []).map((n) => [
1841
+ n.nodeId,
1842
+ n,
1843
+ ]));
1705
1844
  let changed = false;
1706
1845
  for (const n of cur.nodes) {
1707
1846
  const rn = byId.get(n.nodeId);
@@ -1733,6 +1872,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
1733
1872
  const off2 = runner.on("error", (e) => {
1734
1873
  const edgeError = e;
1735
1874
  const nodeError = e;
1875
+ const registryError = e;
1876
+ const systemError = e;
1736
1877
  if (edgeError.kind === "edge-convert") {
1737
1878
  const edgeId = edgeError.edgeId;
1738
1879
  setEdgeStatus((s) => ({
@@ -1740,7 +1881,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
1740
1881
  [edgeId]: { ...s[edgeId], lastError: edgeError.err },
1741
1882
  }));
1742
1883
  }
1743
- else if (nodeError.nodeId) {
1884
+ else if (nodeError.kind === "node-run" && nodeError.nodeId) {
1744
1885
  const nodeId = nodeError.nodeId;
1745
1886
  const runId = nodeError.runId;
1746
1887
  setNodeStatus((s) => ({
@@ -1758,6 +1899,27 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
1758
1899
  };
1759
1900
  }
1760
1901
  }
1902
+ else if (registryError.kind === "registry") {
1903
+ // Track registry errors for UI display
1904
+ setRegistryErrors((prev) => {
1905
+ // Avoid duplicates by checking message
1906
+ if (prev.some((err) => err.message === registryError.message)) {
1907
+ return prev;
1908
+ }
1909
+ return [...prev, registryError];
1910
+ });
1911
+ }
1912
+ else if (systemError.kind === "system") {
1913
+ // Track custom errors for UI display
1914
+ setSystemErrors((prev) => {
1915
+ // Avoid duplicates by checking message and code
1916
+ if (prev.some((err) => err.message === systemError.message &&
1917
+ err.code === systemError.code)) {
1918
+ return prev;
1919
+ }
1920
+ return [...prev, systemError];
1921
+ });
1922
+ }
1761
1923
  return add("runner", "error")(e);
1762
1924
  });
1763
1925
  const off3 = runner.on("invalidate", (e) => {
@@ -2005,6 +2167,12 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
2005
2167
  validationGlobal,
2006
2168
  events,
2007
2169
  clearEvents,
2170
+ systemErrors,
2171
+ registryErrors,
2172
+ clearSystemErrors,
2173
+ clearRegistryErrors,
2174
+ removeSystemError,
2175
+ removeRegistryError,
2008
2176
  isRunning,
2009
2177
  engineKind,
2010
2178
  start,
@@ -2026,6 +2194,12 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, child
2026
2194
  nodeStatus,
2027
2195
  edgeStatus,
2028
2196
  valuesTick,
2197
+ systemErrors,
2198
+ registryErrors,
2199
+ clearSystemErrors,
2200
+ clearRegistryErrors,
2201
+ removeSystemError,
2202
+ removeRegistryError,
2029
2203
  inputsMap,
2030
2204
  outputsMap,
2031
2205
  validationByNode,
@@ -2092,7 +2266,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
2092
2266
  return String(value ?? "");
2093
2267
  }
2094
2268
  };
2095
- const { registry, def, selectedNodeId, selectedEdgeId, inputsMap, outputsMap, outputTypesMap, nodeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, } = useWorkbenchContext();
2269
+ const { registry, def, selectedNodeId, selectedEdgeId, inputsMap, outputsMap, outputTypesMap, nodeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, systemErrors, registryErrors, clearSystemErrors, clearRegistryErrors, removeSystemError, removeRegistryError, } = useWorkbenchContext();
2096
2270
  const nodeValidationIssues = validationByNode.issues;
2097
2271
  const edgeValidationIssues = validationByEdge.issues;
2098
2272
  const nodeValidationHandles = validationByNode;
@@ -2178,7 +2352,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
2178
2352
  }
2179
2353
  catch { }
2180
2354
  };
2181
- return (jsxs("div", { className: `${widthClass} border-l border-gray-300 p-3 flex flex-col h-full min-h-0 overflow-hidden`, children: [contextPanel && jsx("div", { className: "mb-2", children: contextPanel }), jsx("div", { className: "font-semibold mb-2", children: "Inspector" }), jsxs("div", { className: "text-xs text-gray-500 mb-2", children: ["valuesTick: ", valuesTick] }), 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}` }), !!m.data?.edgeId && (jsx("button", { className: "ml-2 text-[10px] px-1 py-[2px] border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
2355
+ return (jsxs("div", { className: `${widthClass} border-l border-gray-300 p-3 flex flex-col h-full min-h-0 overflow-hidden`, children: [contextPanel && jsx("div", { className: "mb-2", children: contextPanel }), systemErrors.length > 0 && (jsxs("div", { className: "mb-2 space-y-1", children: [systemErrors.map((err, i) => (jsxs("div", { className: "text-xs text-red-700 bg-red-50 border border-red-200 rounded px-2 py-1 flex items-start justify-between gap-2", children: [jsxs("div", { className: "flex-1", children: [jsx("div", { className: "font-semibold", children: err.code ? `Error ${err.code}` : "Error" }), jsx("div", { className: "break-words", children: err.message })] }), jsx("button", { className: "text-red-500 hover:text-red-700 text-[10px] px-1", onClick: () => removeSystemError(i), title: "Dismiss", children: "\u00D7" })] }, i))), systemErrors.length > 1 && (jsx("button", { className: "text-xs text-red-600 hover:text-red-800 underline", onClick: clearSystemErrors, children: "Clear all" }))] })), registryErrors.length > 0 && (jsxs("div", { className: "mb-2 space-y-1", children: [registryErrors.map((err, i) => (jsxs("div", { className: "text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded px-2 py-1 flex items-start justify-between gap-2", children: [jsxs("div", { className: "flex-1", children: [jsx("div", { className: "font-semibold", children: "Registry Error" }), jsx("div", { className: "break-words", children: err.message }), err.attempt && err.maxAttempts && (jsxs("div", { className: "text-[10px] text-amber-600 mt-1", children: ["Attempt ", err.attempt, " of ", err.maxAttempts] }))] }), jsx("button", { className: "text-amber-500 hover:text-amber-700 text-[10px] px-1", onClick: () => removeRegistryError(i), title: "Dismiss", children: "\u00D7" })] }, i))), registryErrors.length > 1 && (jsx("button", { className: "text-xs text-amber-600 hover:text-amber-800 underline", onClick: clearRegistryErrors, children: "Clear all" }))] })), jsx("div", { className: "font-semibold mb-2", children: "Inspector" }), jsxs("div", { className: "text-xs text-gray-500 mb-2", children: ["valuesTick: ", valuesTick] }), 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}` }), !!m.data?.edgeId && (jsx("button", { className: "ml-2 text-[10px] px-1 py-[2px] border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
2182
2356
  e.stopPropagation();
2183
2357
  deleteEdgeById(m.data?.edgeId);
2184
2358
  }, title: "Delete referenced edge", children: "Delete edge" }))] }, 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] }), jsx("div", { className: "mt-1", children: jsx("button", { className: "text-xs px-2 py-1 border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
@@ -2970,7 +3144,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
2970
3144
  }, 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
3145
  });
2972
3146
 
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, }) {
3147
+ 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
3148
  const { wb, runner, registry, def, selectedNodeId, runAutoLayout } = useWorkbenchContext();
2975
3149
  const [transportStatus, setTransportStatus] = useState({
2976
3150
  state: "local",
@@ -3019,17 +3193,17 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3019
3193
  return overrides.getExamples(defaultExamples);
3020
3194
  return defaultExamples;
3021
3195
  }, [overrides, defaultExamples]);
3022
- const [hydrated, setHydrated] = useState(false);
3023
3196
  const lastAutoLaunched = useRef(undefined);
3024
3197
  const autoLayoutRan = useRef(false);
3025
3198
  const canvasRef = useRef(null);
3026
3199
  const uploadInputRef = useRef(null);
3200
+ const [registryReady, setRegistryReady] = useState(() => {
3201
+ // For local backends, registry is always ready
3202
+ return backendKind === "local";
3203
+ });
3027
3204
  // Expose init callback with setInitialGraph helper
3028
- const initCalled = useRef(false);
3205
+ // Note: This runs whenever runner changes (e.g., when Flow is enabled and backendOptions changes)
3029
3206
  useEffect(() => {
3030
- if (initCalled.current)
3031
- return;
3032
- initCalled.current = true;
3033
3207
  if (!onInit)
3034
3208
  return;
3035
3209
  const setInitialGraph = async (d, inputs) => {
@@ -3082,7 +3256,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3082
3256
  const { registry: r, def } = await ex.load();
3083
3257
  // Keep registry consistent with backend:
3084
3258
  // - For local backend, allow example to provide its own registry
3085
- // - For remote backend, NEVER overwrite the hydrated remote registry
3259
+ // - For remote backend, registry is automatically managed by RemoteGraphRunner
3086
3260
  if (backendKind === "local") {
3087
3261
  if (r) {
3088
3262
  setRegistry(r);
@@ -3195,79 +3369,8 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3195
3369
  const triggerUpload = useCallback(() => {
3196
3370
  uploadInputRef.current?.click();
3197
3371
  }, []);
3198
- const hydrateFromBackend = useCallback(async (kind, base) => {
3199
- try {
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]);
3372
+ // Registry is now automatically fetched by RemoteGraphRunner on first connection
3373
+ // No need for manual hydration
3271
3374
  // Ensure initial example is loaded (and sync when example prop changes)
3272
3375
  useEffect(() => {
3273
3376
  if (!example)
@@ -3278,6 +3381,21 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3278
3381
  const off = runner.on("transport", (s) => setTransportStatus(s));
3279
3382
  return () => off();
3280
3383
  }, [runner]);
3384
+ // Track registry readiness for remote backends
3385
+ useEffect(() => {
3386
+ // For local backends, registry is always ready
3387
+ if (backendKind === "local") {
3388
+ setRegistryReady(true);
3389
+ return;
3390
+ }
3391
+ // Reset readiness when switching to remote backend
3392
+ setRegistryReady(false);
3393
+ // For remote backends, wait for registry event
3394
+ const off = runner.on("registry", () => {
3395
+ setRegistryReady(true);
3396
+ });
3397
+ return () => off();
3398
+ }, [runner, backendKind]);
3281
3399
  useEffect(() => {
3282
3400
  if (!engine)
3283
3401
  return;
@@ -3299,25 +3417,13 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3299
3417
  // ignore
3300
3418
  }
3301
3419
  }, [engine, runner, wb, backendKind]);
3302
- // When switching to remote backend, auto-hydrate registry from backend
3303
- useEffect(() => {
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]);
3420
+ // Registry is automatically fetched by RemoteGraphRunner when it connects
3421
+ // Run auto layout after registry is hydrated (for remote backends)
3317
3422
  useEffect(() => {
3318
3423
  if (autoLayoutRan.current)
3319
3424
  return;
3320
- if (backendKind !== "local" && !hydrated)
3425
+ // Wait for registry to be ready for remote backends
3426
+ if (backendKind !== "local" && !registryReady)
3321
3427
  return;
3322
3428
  const cur = wb.export();
3323
3429
  const positions = wb.getPositions();
@@ -3326,7 +3432,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3326
3432
  autoLayoutRan.current = true;
3327
3433
  runAutoLayout();
3328
3434
  }
3329
- }, [wb, runAutoLayout, backendKind, hydrated]);
3435
+ }, [wb, runAutoLayout, backendKind, registryReady, registry]);
3330
3436
  const baseSetInput = useCallback((handle, raw) => {
3331
3437
  if (!selectedNodeId)
3332
3438
  return;
@@ -3543,7 +3649,19 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3543
3649
  function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, backendOptions, overrides, onInit, onChange, }) {
3544
3650
  const [registry, setRegistry] = useState(createSimpleGraphRegistry());
3545
3651
  const [wb] = useState(() => new InMemoryWorkbench({ ui: new DefaultUIExtensionRegistry() }));
3652
+ // Store previous runner for cleanup
3653
+ const prevRunnerRef = useRef(null);
3546
3654
  const runner = useMemo(() => {
3655
+ // Dispose previous runner if it exists
3656
+ if (prevRunnerRef.current) {
3657
+ try {
3658
+ prevRunnerRef.current.dispose();
3659
+ }
3660
+ catch (err) {
3661
+ console.warn("Error disposing previous runner:", err);
3662
+ }
3663
+ }
3664
+ let newRunner;
3547
3665
  if (backendKind === "remote-http") {
3548
3666
  const backend = {
3549
3667
  kind: "remote-http",
@@ -3555,9 +3673,9 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
3555
3673
  onCustomEvent: backendOptions.onCustomEvent,
3556
3674
  }),
3557
3675
  };
3558
- return new RemoteGraphRunner(registry, backend);
3676
+ newRunner = new RemoteGraphRunner(registry, backend);
3559
3677
  }
3560
- if (backendKind === "remote-ws") {
3678
+ else if (backendKind === "remote-ws") {
3561
3679
  const backend = {
3562
3680
  kind: "remote-ws",
3563
3681
  url: wsUrl,
@@ -3568,10 +3686,27 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
3568
3686
  onCustomEvent: backendOptions.onCustomEvent,
3569
3687
  }),
3570
3688
  };
3571
- return new RemoteGraphRunner(registry, backend);
3689
+ newRunner = new RemoteGraphRunner(registry, backend);
3572
3690
  }
3573
- return new LocalGraphRunner(registry);
3691
+ else {
3692
+ newRunner = new LocalGraphRunner(registry);
3693
+ }
3694
+ prevRunnerRef.current = newRunner;
3695
+ return newRunner;
3574
3696
  }, [registry, backendKind, httpBaseUrl, wsUrl, backendOptions]);
3697
+ // Cleanup runner on unmount
3698
+ useEffect(() => {
3699
+ return () => {
3700
+ if (prevRunnerRef.current) {
3701
+ try {
3702
+ prevRunnerRef.current.dispose();
3703
+ }
3704
+ catch (err) {
3705
+ console.warn("Error disposing runner on unmount:", err);
3706
+ }
3707
+ }
3708
+ };
3709
+ }, []);
3575
3710
  // Allow external UI registration (e.g., node renderers) with access to wb
3576
3711
  useEffect(() => {
3577
3712
  const baseRegisterUI = (_wb) => { };
@@ -3582,7 +3717,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
3582
3717
  if (runner.isRunning())
3583
3718
  runner.dispose();
3584
3719
  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 }) }));
3720
+ }, 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
3721
  }
3587
3722
 
3588
3723
  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 };