@bian-womp/spark-remote 0.2.47 → 0.2.49

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 CHANGED
@@ -241,12 +241,14 @@ async function createRuntimeAdapter(createRegistry, send, extensions) {
241
241
  const registry = await createRegistry();
242
242
  const builder = new sparkGraph.GraphBuilder(registry);
243
243
  let graphRuntime;
244
+ let engine;
244
245
  let extData = {};
245
246
  // Helper to get current context
246
247
  const getContext = () => ({
247
248
  registry,
248
249
  builder,
249
250
  graphRuntime,
251
+ engine,
250
252
  extData,
251
253
  });
252
254
  // Original implementations - define as separate functions first to allow cross-references
@@ -417,21 +419,81 @@ async function createRuntimeAdapter(createRegistry, send, extensions) {
417
419
  graphRuntime.setEnvironment(env);
418
420
  },
419
421
  setInput: (nodeId, handle, value) => {
420
- graphRuntime?.setInput(nodeId, handle, value);
422
+ // If engine exists, use it; otherwise fall back to direct runtime access
423
+ if (engine) {
424
+ engine.setInput(nodeId, handle, value);
425
+ }
426
+ else {
427
+ graphRuntime?.setInput(nodeId, handle, value);
428
+ }
421
429
  },
422
430
  setInputs: (nodeId, inputs) => {
423
- graphRuntime?.setInputs(nodeId, inputs);
431
+ if (engine) {
432
+ engine.setInputs(nodeId, inputs);
433
+ }
434
+ else {
435
+ graphRuntime?.setInputs(nodeId, inputs);
436
+ }
424
437
  },
425
438
  triggerExternal: (nodeId, event) => {
426
- graphRuntime?.triggerExternal(nodeId, event);
439
+ if (engine) {
440
+ engine.triggerExternal(nodeId, event);
441
+ }
442
+ else {
443
+ graphRuntime?.triggerExternal(nodeId, event);
444
+ }
445
+ },
446
+ launch: (opts) => {
447
+ if (!graphRuntime) {
448
+ throw new Error("Cannot launch: graph runtime not built");
449
+ }
450
+ // Dispose existing engine if any
451
+ if (engine) {
452
+ engine.dispose();
453
+ engine = undefined;
454
+ }
455
+ // Create new engine using shared factory
456
+ engine = sparkGraph.createEngine(graphRuntime, opts);
457
+ // Launch the engine
458
+ if (engine) {
459
+ engine.launch(opts?.invalidate);
460
+ }
461
+ },
462
+ step: async () => {
463
+ if (!engine)
464
+ return;
465
+ // Type guard for StepEngine
466
+ if ("step" in engine && typeof engine.step === "function") {
467
+ await engine.step();
468
+ }
469
+ },
470
+ computeNode: async (nodeId) => {
471
+ if (!engine)
472
+ return;
473
+ // Type guard for PullEngine
474
+ if ("computeNode" in engine && typeof engine.computeNode === "function") {
475
+ await engine.computeNode(nodeId);
476
+ }
427
477
  },
428
- launch: (invalidate) => {
429
- graphRuntime?.launch(invalidate);
478
+ flush: async () => {
479
+ if (!engine)
480
+ return;
481
+ // Type guard for BatchedEngine
482
+ if ("flush" in engine && typeof engine.flush === "function") {
483
+ await engine.flush();
484
+ }
430
485
  },
431
486
  whenIdle: () => {
487
+ if (engine) {
488
+ return engine.whenIdle();
489
+ }
432
490
  return graphRuntime?.whenIdle?.() ?? Promise.resolve();
433
491
  },
434
492
  dispose: () => {
493
+ if (engine) {
494
+ engine.dispose();
495
+ engine = undefined;
496
+ }
435
497
  graphRuntime?.dispose?.();
436
498
  graphRuntime = undefined;
437
499
  },
@@ -442,6 +504,10 @@ async function createRuntimeAdapter(createRegistry, send, extensions) {
442
504
  if (!extension) {
443
505
  return original;
444
506
  }
507
+ // Handle optional methods that might be undefined
508
+ if (!original) {
509
+ return original;
510
+ }
445
511
  return ((...args) => {
446
512
  return extension(original, getContext(), ...args);
447
513
  });
@@ -499,9 +565,12 @@ class RemoteEngine {
499
565
  this.emit("stats", msg.payload);
500
566
  }
501
567
  }
502
- launch(invalidate) {
568
+ launch(invalidate, engineConfig) {
503
569
  this.transport.send({
504
- message: { type: "Launch", payload: { invalidate } },
570
+ message: {
571
+ type: "Launch",
572
+ payload: { invalidate, ...engineConfig },
573
+ },
505
574
  });
506
575
  }
507
576
  setInput(nodeId, handle, value) {
@@ -645,6 +714,7 @@ class RuntimeApiClient {
645
714
  this.transportEventListeners = new Set();
646
715
  this.disposed = false;
647
716
  this.config = config;
717
+ this.runnerId = options?.runnerId;
648
718
  if (options?.onCustomEvent) {
649
719
  this.customEventListeners.add(options.onCustomEvent);
650
720
  }
@@ -693,8 +763,11 @@ class RuntimeApiClient {
693
763
  if (this.connectingPromise) {
694
764
  return this.connectingPromise;
695
765
  }
696
- const kind = this.config.kind;
697
- this.emitTransportStatus({ state: "connecting", kind });
766
+ this.emitTransportStatus({
767
+ state: "connecting",
768
+ kind: this.config.kind,
769
+ runnerId: this.runnerId,
770
+ });
698
771
  // Create connection promise to prevent concurrent connections
699
772
  this.connectingPromise = (async () => {
700
773
  try {
@@ -707,12 +780,20 @@ class RuntimeApiClient {
707
780
  });
708
781
  // Create engine with connected transport
709
782
  this.engine = new RemoteEngine(transport);
710
- this.emitTransportStatus({ state: "connected", kind });
783
+ this.emitTransportStatus({
784
+ state: "connected",
785
+ kind: this.config.kind,
786
+ runnerId: this.runnerId,
787
+ });
711
788
  }
712
789
  catch (error) {
713
790
  // Clear connecting promise on error so retry is possible
714
791
  this.connectingPromise = undefined;
715
- this.emitTransportStatus({ state: "disconnected", kind });
792
+ this.emitTransportStatus({
793
+ state: "disconnected",
794
+ kind: this.config.kind,
795
+ runnerId: this.runnerId,
796
+ });
716
797
  throw error;
717
798
  }
718
799
  finally {
@@ -733,7 +814,7 @@ class RuntimeApiClient {
733
814
  const type = msg.type;
734
815
  // Standard runtime events: stats, value, error, invalidate
735
816
  // These are handled by RemoteEngine via transport subscription
736
- // Custom events are anything else (e.g., flow-opened, flow-latest)
817
+ // Custom events are anything else
737
818
  if (!["stats", "value", "error", "invalidate"].includes(type)) {
738
819
  // Emit to custom event listeners (constructor callback is auto-subscribed)
739
820
  for (const listener of this.customEventListeners) {
@@ -749,8 +830,11 @@ class RuntimeApiClient {
749
830
  this.transportEventListeners.add(listener);
750
831
  // Immediately emit current status if connected
751
832
  if (this.transport) {
752
- const kind = this.config.kind;
753
- listener({ state: "connected", kind });
833
+ listener({
834
+ state: "connected",
835
+ kind: this.config.kind,
836
+ runnerId: this.runnerId,
837
+ });
754
838
  }
755
839
  return () => {
756
840
  this.transportEventListeners.delete(listener);
@@ -871,6 +955,33 @@ class RuntimeApiClient {
871
955
  }
872
956
  return this.engine;
873
957
  }
958
+ async launch(opts) {
959
+ const transport = await this.ensureConnected();
960
+ await transport.request({
961
+ message: {
962
+ type: "Launch",
963
+ payload: opts,
964
+ },
965
+ });
966
+ }
967
+ async step() {
968
+ const transport = await this.ensureConnected();
969
+ await transport.request({
970
+ message: { type: "Step" },
971
+ });
972
+ }
973
+ async computeNode(nodeId) {
974
+ const transport = await this.ensureConnected();
975
+ await transport.request({
976
+ message: { type: "ComputeNode", payload: { nodeId } },
977
+ });
978
+ }
979
+ async flush() {
980
+ const transport = await this.ensureConnected();
981
+ await transport.request({
982
+ message: { type: "Flush" },
983
+ });
984
+ }
874
985
  /**
875
986
  * Dispose the client and close the transport connection.
876
987
  * Idempotent: safe to call multiple times.
@@ -898,7 +1009,11 @@ class RuntimeApiClient {
898
1009
  // Clear listeners
899
1010
  this.customEventListeners.clear();
900
1011
  this.transportEventListeners.clear();
901
- this.emitTransportStatus({ state: "disconnected", kind: this.config.kind });
1012
+ this.emitTransportStatus({
1013
+ state: "disconnected",
1014
+ kind: this.config.kind,
1015
+ runnerId: this.runnerId,
1016
+ });
902
1017
  }
903
1018
  }
904
1019
 
@@ -1009,8 +1124,43 @@ class RuntimeApiServer {
1009
1124
  break;
1010
1125
  }
1011
1126
  case "Launch": {
1012
- this.logCommand("Launch", env);
1013
- this.runtimeApi.launch(msg.payload.invalidate);
1127
+ const launchPayload = msg.payload;
1128
+ this.logCommand("Launch", env, {
1129
+ engine: launchPayload.engine,
1130
+ invalidate: launchPayload.invalidate,
1131
+ });
1132
+ this.runtimeApi.launch({
1133
+ invalidate: launchPayload.invalidate,
1134
+ engine: launchPayload.engine,
1135
+ batched: launchPayload.batched,
1136
+ hybrid: launchPayload.hybrid,
1137
+ });
1138
+ ack();
1139
+ break;
1140
+ }
1141
+ case "Step": {
1142
+ this.logCommand("Step", env);
1143
+ if (this.runtimeApi.step) {
1144
+ await this.runtimeApi.step();
1145
+ }
1146
+ ack();
1147
+ break;
1148
+ }
1149
+ case "ComputeNode": {
1150
+ this.logCommand("ComputeNode", env, {
1151
+ nodeId: msg.payload.nodeId,
1152
+ });
1153
+ if (this.runtimeApi.computeNode) {
1154
+ await this.runtimeApi.computeNode(msg.payload.nodeId);
1155
+ }
1156
+ ack();
1157
+ break;
1158
+ }
1159
+ case "Flush": {
1160
+ this.logCommand("Flush", env);
1161
+ if (this.runtimeApi.flush) {
1162
+ await this.runtimeApi.flush();
1163
+ }
1014
1164
  ack();
1015
1165
  break;
1016
1166
  }