@bian-womp/spark-remote 0.2.28 → 0.2.30
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 +218 -177
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/server/runtime.d.ts +11 -2
- package/lib/cjs/src/server/runtime.d.ts.map +1 -1
- package/lib/esm/index.js +218 -177
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/server/runtime.d.ts +11 -2
- package/lib/esm/src/server/runtime.d.ts.map +1 -1
- package/package.json +3 -3
package/lib/cjs/index.cjs
CHANGED
|
@@ -510,193 +510,234 @@ async function handleCommand(label, env, runtimeApi, ack) {
|
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
-
async function createRuntimeAdapter(createRegistry, send) {
|
|
513
|
+
async function createRuntimeAdapter(createRegistry, send, extensions) {
|
|
514
514
|
const registry = await createRegistry();
|
|
515
515
|
const builder = new sparkGraph.GraphBuilder(registry);
|
|
516
516
|
let graphRuntime;
|
|
517
517
|
let extData = {};
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
else if (d.kind === "register-node") {
|
|
555
|
-
const desc = d.desc || {};
|
|
556
|
-
registry.registerNode({
|
|
557
|
-
id: String(desc.id || ""),
|
|
558
|
-
categoryId: String(desc.categoryId || "compute"),
|
|
559
|
-
displayName: desc.displayName,
|
|
560
|
-
inputs: desc.inputs || {},
|
|
561
|
-
outputs: desc.outputs || {},
|
|
562
|
-
// impl must be empty per frontend registration contract
|
|
563
|
-
impl: () => { },
|
|
564
|
-
});
|
|
565
|
-
}
|
|
518
|
+
// Helper to get current context
|
|
519
|
+
const getContext = () => ({
|
|
520
|
+
registry,
|
|
521
|
+
builder,
|
|
522
|
+
graphRuntime,
|
|
523
|
+
extData,
|
|
524
|
+
});
|
|
525
|
+
// Original implementations - define as separate functions first to allow cross-references
|
|
526
|
+
const originals = {};
|
|
527
|
+
// Define methods that can reference each other
|
|
528
|
+
originals.coerce = async (from, to, value) => {
|
|
529
|
+
const resolved = registry.resolveCoercion(from, to);
|
|
530
|
+
if (!resolved)
|
|
531
|
+
return value;
|
|
532
|
+
if (resolved.kind === "sync")
|
|
533
|
+
return resolved.convert(value);
|
|
534
|
+
const ac = new AbortController();
|
|
535
|
+
return await resolved.convertAsync(value, ac.signal);
|
|
536
|
+
};
|
|
537
|
+
originals.getEnvironment = () => {
|
|
538
|
+
return graphRuntime?.getEnvironment?.() ?? {};
|
|
539
|
+
};
|
|
540
|
+
originals.applyRegistry = async (deltas) => {
|
|
541
|
+
// Pause runtime if exists
|
|
542
|
+
// Apply each delta to the live registry
|
|
543
|
+
for (const d of deltas || []) {
|
|
544
|
+
if (!d || typeof d !== "object")
|
|
545
|
+
continue;
|
|
546
|
+
if (d.kind === "register-enum") {
|
|
547
|
+
registry.registerEnum({
|
|
548
|
+
id: d.id,
|
|
549
|
+
displayName: d.displayName,
|
|
550
|
+
options: d.options || [],
|
|
551
|
+
bakeTarget: d.bakeTarget,
|
|
552
|
+
opts: d.opts,
|
|
553
|
+
});
|
|
566
554
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
},
|
|
575
|
-
async build(def, opts) {
|
|
576
|
-
const env = opts || {};
|
|
577
|
-
graphRuntime = builder.build(def, { environment: env });
|
|
578
|
-
graphRuntime.on("value", (p) => send({ message: { type: "value", payload: p } }));
|
|
579
|
-
graphRuntime.on("invalidate", (p) => send({ message: { type: "invalidate", payload: p } }));
|
|
580
|
-
graphRuntime.on("error", (p) => send({ message: { type: "error", payload: p } }));
|
|
581
|
-
graphRuntime.on("stats", (p) => send({ message: { type: "stats", payload: p } }));
|
|
582
|
-
},
|
|
583
|
-
setExtData(data) {
|
|
584
|
-
if (!data || typeof data !== "object") {
|
|
585
|
-
extData = {};
|
|
586
|
-
return;
|
|
555
|
+
else if (d.kind === "register-type") {
|
|
556
|
+
registry.registerType({
|
|
557
|
+
id: d.id,
|
|
558
|
+
displayName: d.displayName,
|
|
559
|
+
bakeTarget: d.bakeTarget,
|
|
560
|
+
validate: (_v) => true,
|
|
561
|
+
});
|
|
587
562
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const nodes = graphRuntime.getNodeIds();
|
|
600
|
-
for (const nodeId of nodes) {
|
|
601
|
-
const data = graphRuntime.getNodeData(nodeId);
|
|
602
|
-
if (data?.inputs && Object.keys(data.inputs).length > 0) {
|
|
603
|
-
inputs[nodeId] = { ...data.inputs };
|
|
604
|
-
}
|
|
605
|
-
if (data?.outputs && Object.keys(data.outputs).length > 0) {
|
|
606
|
-
outputs[nodeId] = { ...data.outputs };
|
|
607
|
-
}
|
|
563
|
+
else if (d.kind === "register-node") {
|
|
564
|
+
const desc = d.desc || {};
|
|
565
|
+
registry.registerNode({
|
|
566
|
+
id: String(desc.id || ""),
|
|
567
|
+
categoryId: String(desc.categoryId || "compute"),
|
|
568
|
+
displayName: desc.displayName,
|
|
569
|
+
inputs: desc.inputs || {},
|
|
570
|
+
outputs: desc.outputs || {},
|
|
571
|
+
// impl must be empty per frontend registration contract
|
|
572
|
+
impl: () => { },
|
|
573
|
+
});
|
|
608
574
|
}
|
|
575
|
+
}
|
|
576
|
+
// Notify clients (include deltas in invalidate payload)
|
|
577
|
+
send({
|
|
578
|
+
message: {
|
|
579
|
+
type: "invalidate",
|
|
580
|
+
payload: { reason: "registry-changed", deltas },
|
|
581
|
+
},
|
|
582
|
+
});
|
|
583
|
+
};
|
|
584
|
+
originals.build = async (def, opts) => {
|
|
585
|
+
const env = opts || {};
|
|
586
|
+
graphRuntime = builder.build(def, { environment: env });
|
|
587
|
+
graphRuntime.on("value", (p) => send({ message: { type: "value", payload: p } }));
|
|
588
|
+
graphRuntime.on("invalidate", (p) => send({ message: { type: "invalidate", payload: p } }));
|
|
589
|
+
graphRuntime.on("error", (p) => send({ message: { type: "error", payload: p } }));
|
|
590
|
+
graphRuntime.on("stats", (p) => send({ message: { type: "stats", payload: p } }));
|
|
591
|
+
};
|
|
592
|
+
originals.setExtData = (data) => {
|
|
593
|
+
if (!data || typeof data !== "object") {
|
|
594
|
+
extData = {};
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
// Replace to keep semantics deterministic
|
|
598
|
+
extData = { ...data };
|
|
599
|
+
};
|
|
600
|
+
originals.getExtData = () => {
|
|
601
|
+
return extData;
|
|
602
|
+
};
|
|
603
|
+
originals.snapshot = () => {
|
|
604
|
+
const inputs = {};
|
|
605
|
+
const outputs = {};
|
|
606
|
+
if (!graphRuntime)
|
|
609
607
|
return { inputs, outputs };
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
|
|
608
|
+
const nodes = graphRuntime.getNodeIds();
|
|
609
|
+
for (const nodeId of nodes) {
|
|
610
|
+
const data = graphRuntime.getNodeData(nodeId);
|
|
611
|
+
if (data?.inputs && Object.keys(data.inputs).length > 0) {
|
|
612
|
+
inputs[nodeId] = { ...data.inputs };
|
|
613
|
+
}
|
|
614
|
+
if (data?.outputs && Object.keys(data.outputs).length > 0) {
|
|
615
|
+
outputs[nodeId] = { ...data.outputs };
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return { inputs, outputs };
|
|
619
|
+
};
|
|
620
|
+
originals.snapshotFull = () => {
|
|
621
|
+
const snap = originals.snapshot();
|
|
622
|
+
const env = graphRuntime?.getEnvironment?.() ?? {};
|
|
623
|
+
const def = graphRuntime?.getGraphDef();
|
|
624
|
+
return {
|
|
625
|
+
def,
|
|
626
|
+
environment: env,
|
|
627
|
+
inputs: snap.inputs,
|
|
628
|
+
outputs: snap.outputs,
|
|
629
|
+
};
|
|
630
|
+
};
|
|
631
|
+
originals.applySnapshotFull = async (payload) => {
|
|
632
|
+
const def = payload.def;
|
|
633
|
+
if (!def)
|
|
634
|
+
return;
|
|
635
|
+
await originals.build(def, payload.environment);
|
|
636
|
+
// Hydrate inputs/outputs exactly, then re-emit outputs without scheduling runs
|
|
637
|
+
graphRuntime?.hydrate({ inputs: payload.inputs, outputs: payload.outputs }, { reemit: true });
|
|
638
|
+
};
|
|
639
|
+
originals.describeRegistry = () => {
|
|
640
|
+
// types (include enum options when available)
|
|
641
|
+
const types = Array.from(registry.types.entries()).map(([id, d]) => {
|
|
642
|
+
const en = registry.enums.get(id);
|
|
615
643
|
return {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
644
|
+
id,
|
|
645
|
+
displayName: d.displayName,
|
|
646
|
+
bakeTarget: d.bakeTarget,
|
|
647
|
+
...(en ? { options: en.options } : {}),
|
|
620
648
|
};
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
649
|
+
});
|
|
650
|
+
// categories: not directly enumerable; derive from node descriptors
|
|
651
|
+
const nodeDescs = Array.from(registry.nodes.values());
|
|
652
|
+
const catIds = new Set(nodeDescs.map((n) => n.categoryId));
|
|
653
|
+
const categories = Array.from(catIds).map((id) => {
|
|
654
|
+
const cat = registry.categories.get?.(id);
|
|
655
|
+
return { id, displayName: cat?.displayName };
|
|
656
|
+
});
|
|
657
|
+
const nodes = nodeDescs.map((n) => ({
|
|
658
|
+
id: n.id,
|
|
659
|
+
categoryId: n.categoryId,
|
|
660
|
+
displayName: n.displayName,
|
|
661
|
+
inputs: n.inputs || {},
|
|
662
|
+
outputs: n.outputs || {},
|
|
663
|
+
inputDefaults: n.inputDefaults || {},
|
|
664
|
+
}));
|
|
665
|
+
const coercions = registry.listCoercions();
|
|
666
|
+
return { types, categories, nodes, coercions, schemaVersion: 4 };
|
|
667
|
+
};
|
|
668
|
+
originals.update = async (def) => {
|
|
669
|
+
if (!graphRuntime)
|
|
670
|
+
return;
|
|
671
|
+
graphRuntime.update(def, registry);
|
|
672
|
+
send({
|
|
673
|
+
message: {
|
|
674
|
+
type: "invalidate",
|
|
675
|
+
payload: { reason: "graph-updated" },
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
};
|
|
679
|
+
originals.setEnvironment = (env, opts) => {
|
|
680
|
+
if (!graphRuntime)
|
|
681
|
+
return;
|
|
682
|
+
if (opts?.merge) {
|
|
683
|
+
const current = graphRuntime.getEnvironment();
|
|
684
|
+
const next = { ...(current || {}), ...(env || {}) };
|
|
685
|
+
graphRuntime.setEnvironment(next);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
graphRuntime.setEnvironment(env);
|
|
689
|
+
};
|
|
690
|
+
originals.setInput = (nodeId, handle, value) => {
|
|
691
|
+
graphRuntime?.setInput(nodeId, handle, value);
|
|
692
|
+
};
|
|
693
|
+
originals.setInputs = (nodeId, inputs) => {
|
|
694
|
+
graphRuntime?.setInputs(nodeId, inputs);
|
|
695
|
+
};
|
|
696
|
+
originals.triggerExternal = (nodeId, event) => {
|
|
697
|
+
graphRuntime?.triggerExternal(nodeId, event);
|
|
698
|
+
};
|
|
699
|
+
originals.launch = () => {
|
|
700
|
+
graphRuntime?.launch();
|
|
701
|
+
};
|
|
702
|
+
originals.whenIdle = () => {
|
|
703
|
+
return graphRuntime?.whenIdle?.() ?? Promise.resolve();
|
|
704
|
+
};
|
|
705
|
+
originals.dispose = () => {
|
|
706
|
+
graphRuntime?.dispose?.();
|
|
707
|
+
graphRuntime = undefined;
|
|
708
|
+
};
|
|
709
|
+
// Cast to RuntimeApi now that all methods are defined
|
|
710
|
+
const originalsApi = originals;
|
|
711
|
+
// Helper to wrap a method with extension support
|
|
712
|
+
const wrapMethod = (key, original) => {
|
|
713
|
+
const extension = extensions?.[key];
|
|
714
|
+
if (!extension) {
|
|
715
|
+
return original;
|
|
716
|
+
}
|
|
717
|
+
return ((...args) => {
|
|
718
|
+
return extension(original, getContext(), ...args);
|
|
719
|
+
});
|
|
720
|
+
};
|
|
721
|
+
// Create API with extensions applied
|
|
722
|
+
const api = {
|
|
723
|
+
coerce: wrapMethod("coerce", originalsApi.coerce),
|
|
724
|
+
getEnvironment: wrapMethod("getEnvironment", originalsApi.getEnvironment),
|
|
725
|
+
applyRegistry: wrapMethod("applyRegistry", originalsApi.applyRegistry),
|
|
726
|
+
build: wrapMethod("build", originalsApi.build),
|
|
727
|
+
setExtData: wrapMethod("setExtData", originalsApi.setExtData),
|
|
728
|
+
getExtData: wrapMethod("getExtData", originalsApi.getExtData),
|
|
729
|
+
snapshot: wrapMethod("snapshot", originalsApi.snapshot),
|
|
730
|
+
snapshotFull: wrapMethod("snapshotFull", originalsApi.snapshotFull),
|
|
731
|
+
applySnapshotFull: wrapMethod("applySnapshotFull", originalsApi.applySnapshotFull),
|
|
732
|
+
describeRegistry: wrapMethod("describeRegistry", originalsApi.describeRegistry),
|
|
733
|
+
update: wrapMethod("update", originalsApi.update),
|
|
734
|
+
setEnvironment: wrapMethod("setEnvironment", originalsApi.setEnvironment),
|
|
735
|
+
setInput: wrapMethod("setInput", originalsApi.setInput),
|
|
736
|
+
setInputs: wrapMethod("setInputs", originalsApi.setInputs),
|
|
737
|
+
triggerExternal: wrapMethod("triggerExternal", originalsApi.triggerExternal),
|
|
738
|
+
launch: wrapMethod("launch", originalsApi.launch),
|
|
739
|
+
whenIdle: wrapMethod("whenIdle", originalsApi.whenIdle),
|
|
740
|
+
dispose: wrapMethod("dispose", originalsApi.dispose),
|
|
700
741
|
};
|
|
701
742
|
return api;
|
|
702
743
|
}
|