@cnstra/core 2.4.0 → 2.6.0

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.
Files changed (65) hide show
  1. package/dist/CNS.d.ts +32 -10
  2. package/dist/CNS.d.ts.map +1 -1
  3. package/dist/CNSCollateral.d.ts +2 -2
  4. package/dist/CNSCollateral.d.ts.map +1 -1
  5. package/dist/CNSNetwork.d.ts +7 -7
  6. package/dist/CNSNetwork.d.ts.map +1 -1
  7. package/dist/CNSStimulation.d.ts +55 -15
  8. package/dist/CNSStimulation.d.ts.map +1 -1
  9. package/dist/CNSStimulationContextStore.d.ts +1 -1
  10. package/dist/CNSStimulationContextStore.d.ts.map +1 -1
  11. package/dist/factory/index.d.ts +26 -82
  12. package/dist/factory/index.d.ts.map +1 -1
  13. package/dist/index.cjs +235 -136
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +1 -14
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +236 -134
  18. package/dist/index.js.map +1 -1
  19. package/dist/utils/CNSStimulationGate.d.ts +7 -7
  20. package/dist/utils/CNSStimulationGate.d.ts.map +1 -1
  21. package/package.json +4 -1
  22. package/dist/CNSPersistOptionsRegistry.d.ts +0 -28
  23. package/dist/CNSPersistOptionsRegistry.d.ts.map +0 -1
  24. package/dist/interfaces/ICNS.d.ts +0 -20
  25. package/dist/interfaces/ICNS.d.ts.map +0 -1
  26. package/dist/interfaces/ICNSCollateral.d.ts +0 -6
  27. package/dist/interfaces/ICNSCollateral.d.ts.map +0 -1
  28. package/dist/interfaces/ICNSStimulationContextStore.d.ts +0 -8
  29. package/dist/interfaces/ICNSStimulationContextStore.d.ts.map +0 -1
  30. package/dist/types/TCNSAfferentPath.d.ts +0 -4
  31. package/dist/types/TCNSAfferentPath.d.ts.map +0 -1
  32. package/dist/types/TCNSAxon.d.ts +0 -26
  33. package/dist/types/TCNSAxon.d.ts.map +0 -1
  34. package/dist/types/TCNSDendrite.d.ts +0 -9
  35. package/dist/types/TCNSDendrite.d.ts.map +0 -1
  36. package/dist/types/TCNSHandlerContext.d.ts +0 -24
  37. package/dist/types/TCNSHandlerContext.d.ts.map +0 -1
  38. package/dist/types/TCNSLocalContextValueStore.d.ts +0 -6
  39. package/dist/types/TCNSLocalContextValueStore.d.ts.map +0 -1
  40. package/dist/types/TCNSModality.d.ts +0 -5
  41. package/dist/types/TCNSModality.d.ts.map +0 -1
  42. package/dist/types/TCNSNeuron.d.ts +0 -12
  43. package/dist/types/TCNSNeuron.d.ts.map +0 -1
  44. package/dist/types/TCNSNeuronActivationTask.d.ts +0 -8
  45. package/dist/types/TCNSNeuronActivationTask.d.ts.map +0 -1
  46. package/dist/types/TCNSNeuronActivationTaskFailure.d.ts +0 -7
  47. package/dist/types/TCNSNeuronActivationTaskFailure.d.ts.map +0 -1
  48. package/dist/types/TCNSNeuronResponseReturn.d.ts +0 -9
  49. package/dist/types/TCNSNeuronResponseReturn.d.ts.map +0 -1
  50. package/dist/types/TCNSOptions.d.ts +0 -11
  51. package/dist/types/TCNSOptions.d.ts.map +0 -1
  52. package/dist/types/TCNSPersist.d.ts +0 -16
  53. package/dist/types/TCNSPersist.d.ts.map +0 -1
  54. package/dist/types/TCNSSignal.d.ts +0 -6
  55. package/dist/types/TCNSSignal.d.ts.map +0 -1
  56. package/dist/types/TCNSStimulationOptions.d.ts +0 -14
  57. package/dist/types/TCNSStimulationOptions.d.ts.map +0 -1
  58. package/dist/types/TCNSStimulationQueueItem.d.ts +0 -11
  59. package/dist/types/TCNSStimulationQueueItem.d.ts.map +0 -1
  60. package/dist/types/TCNSStimulationResponse.d.ts +0 -17
  61. package/dist/types/TCNSStimulationResponse.d.ts.map +0 -1
  62. package/dist/types/TCNSStimulationSerializedContextValue.d.ts +0 -4
  63. package/dist/types/TCNSStimulationSerializedContextValue.d.ts.map +0 -1
  64. package/dist/types/TCNSSubscriber.d.ts +0 -7
  65. package/dist/types/TCNSSubscriber.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -39,6 +39,13 @@ var CNSDendriteContext = class {
39
39
  get global() {
40
40
  return this.cns.global;
41
41
  }
42
+ // The caller-supplied per-stimulation context (`stimulate(sig, {stimulationContext})`),
43
+ // the same value on every hop — the environment-agnostic way to correlate logs to a
44
+ // run (pass `{ stimulationId, attemptNumber }`). Prototype getter like `global`:
45
+ // zero extra allocation, read only where a handler reaches for it.
46
+ get stimulationContext() {
47
+ return this.stimulation.options?.stimulationContext;
48
+ }
42
49
  get() {
43
50
  return this.stimulation.getContext().get(this.neuron);
44
51
  }
@@ -50,21 +57,24 @@ var CNSDendriteContext = class {
50
57
  }
51
58
  };
52
59
  var CNSStimulationResponseImpl = class {
53
- constructor(stimulation, store, inputSignal, outputSignal, queueLength, hops, error) {
60
+ constructor(stimulation, store, inputSignal, outputSignal, queueLength, pendingActivations, activeActivations, hops, error, neuron2) {
54
61
  this.stimulation = stimulation;
55
62
  this.store = store;
56
63
  this.inputSignal = inputSignal;
57
64
  this.outputSignal = outputSignal;
58
65
  this.queueLength = queueLength;
66
+ this.pendingActivations = pendingActivations;
67
+ this.activeActivations = activeActivations;
59
68
  this.hops = hops;
60
69
  this.error = error;
70
+ this.neuron = neuron2;
61
71
  }
62
72
  get contextValue() {
63
73
  return this.store ? this.store.getAll() : /* @__PURE__ */ new Map();
64
74
  }
65
75
  };
66
76
  var CNSStimulation = class {
67
- constructor(cns, instanceNeuronQueue, options, onResponse) {
77
+ constructor(cns, instanceNeuronQueue, options, onResponse, onDrain) {
68
78
  this.cns = cns;
69
79
  this.options = options;
70
80
  this.qHead = 0;
@@ -75,9 +85,20 @@ var CNSStimulation = class {
75
85
  // Re-entrancy guard for the pump loop.
76
86
  this.pumping = false;
77
87
  this.needsPump = false;
88
+ // Nesting depth of the current synchronous turn. Only the outermost close
89
+ // announces a drain - see beginTurn/endTurn.
90
+ this.turnDepth = 0;
78
91
  this.scheduledCount = 0;
92
+ // Activations belonging to signals of an in-progress array fan-out that have
93
+ // not been handed to processResponse yet, so the task objects do not exist.
94
+ // processResponse enqueues synchronously, so the first signal's whole subtree
95
+ // drains before the second signal is even looked at; without this counter
96
+ // that subtree's leaf sees an empty queue and reads as "all work done".
97
+ // Counted in activations, not signals, so every public counter shares a unit.
98
+ this.reservedActivations = 0;
79
99
  this.isCompleted = false;
80
100
  this.completionRejected = false;
101
+ this.onDrain = onDrain;
81
102
  this.ctxStore = options?.ctx;
82
103
  this.instanceNeuronQueue = instanceNeuronQueue;
83
104
  this.onResponse = onResponse;
@@ -174,18 +195,28 @@ var CNSStimulation = class {
174
195
  (cb) => {
175
196
  this.activeOperations--;
176
197
  this.activeTasks.delete(task);
177
- if (typeof cb === "function") cb();
178
- if (this.qSize > 0 && this.canStartOperation) {
179
- if (this.pumping) this.needsPump = true;
180
- else this.pump();
198
+ this.beginTurn();
199
+ try {
200
+ if (typeof cb === "function") cb();
201
+ if (this.qSize > 0 && this.canStartOperation) {
202
+ if (this.pumping) this.needsPump = true;
203
+ else this.pump();
204
+ }
205
+ } finally {
206
+ this.endTurn();
181
207
  }
182
208
  },
183
209
  (err) => {
184
210
  this.activeOperations--;
185
211
  this.activeTasks.delete(task);
186
- if (this.qSize > 0 && this.canStartOperation) {
187
- if (this.pumping) this.needsPump = true;
188
- else this.pump();
212
+ this.beginTurn();
213
+ try {
214
+ if (this.qSize > 0 && this.canStartOperation) {
215
+ if (this.pumping) this.needsPump = true;
216
+ else this.pump();
217
+ }
218
+ } finally {
219
+ this.endTurn();
189
220
  }
190
221
  throw err;
191
222
  }
@@ -201,10 +232,54 @@ var CNSStimulation = class {
201
232
  this.pump();
202
233
  }
203
234
  }
235
+ /**
236
+ * Open a synchronous turn. Turns nest: a drain is announced only when the
237
+ * outermost one closes, so an enqueue that happens while the pump is already
238
+ * running does not produce its own boundary.
239
+ */
240
+ beginTurn() {
241
+ this.turnDepth++;
242
+ }
243
+ /**
244
+ * Close a synchronous turn and, if it was the outermost and nothing more can
245
+ * run without yielding to the event loop, announce the drain.
246
+ *
247
+ * This is the only place the synchronous frontier is observable. A response
248
+ * cannot serve the purpose: responses are emitted when an activation
249
+ * *finishes*, but a turn just as often ends when one *starts* and returns a
250
+ * promise - at which point there is nothing left to emit a response from.
251
+ */
252
+ endTurn() {
253
+ if (--this.turnDepth > 0) return;
254
+ const onDrain = this.onDrain;
255
+ if (!onDrain) return;
256
+ if (this.pumping) return;
257
+ if (this.qSize > 0 && this.canStartOperation) return;
258
+ this.turnDepth++;
259
+ try {
260
+ onDrain({
261
+ stimulation: this,
262
+ queueLength: this.pendingActivations + this.activeOperations,
263
+ pendingActivations: this.pendingActivations,
264
+ activeActivations: this.activeOperations
265
+ });
266
+ } finally {
267
+ this.turnDepth--;
268
+ }
269
+ }
270
+ /**
271
+ * Activations that exist (or are reserved) but whose dendrite body has not
272
+ * been invoked yet: sitting in the ring buffer, created and held in
273
+ * pendingTasks, or reserved by an array fan-out mid-dispatch. Subscribers
274
+ * parked behind an async onResponse land here too - their body has not run.
275
+ */
276
+ get pendingActivations() {
277
+ return this.qSize + this.scheduledCount + this.reservedActivations;
278
+ }
204
279
  tryResolveCompleted() {
205
280
  if (this.isCompleted) return;
206
281
  const noActive = this.activeOperations === 0;
207
- const noPending = this.qSize + this.scheduledCount === 0;
282
+ const noPending = this.pendingActivations === 0;
208
283
  const aborted = !!this.options?.abortSignal?.aborted;
209
284
  if (noPending && noActive || aborted && noActive && !noPending) {
210
285
  if (aborted) {
@@ -266,6 +341,19 @@ var CNSStimulation = class {
266
341
  getFailedTasks() {
267
342
  return this.failedTasks ? [...this.failedTasks] : [];
268
343
  }
344
+ /**
345
+ * The current outstanding frontier — every task that has not completed:
346
+ * queued, active, and pending (awaiting an async onResponse), plus any
347
+ * failed/aborted tasks. This is the set to persist for resume: re-activating
348
+ * it re-runs exactly the not-yet-done work. Safe to call at any point during
349
+ * a run (for progress) or after it fails.
350
+ */
351
+ getOutstandingTasks() {
352
+ return [
353
+ ...this.getAllActivationTasks(),
354
+ ...this.getFailedTasks().map((f) => f.task)
355
+ ];
356
+ }
269
357
  /**
270
358
  * Get the context store for this stimulation
271
359
  */
@@ -276,10 +364,15 @@ var CNSStimulation = class {
276
364
  * Enqueue activation tasks directly into the stimulation queue
277
365
  */
278
366
  enqueueTasks(tasks) {
279
- for (const task of tasks) {
280
- this.qEnqueue(task);
367
+ this.beginTurn();
368
+ try {
369
+ for (const task of tasks) {
370
+ this.qEnqueue(task);
371
+ }
372
+ this.tryResolveCompleted();
373
+ } finally {
374
+ this.endTurn();
281
375
  }
282
- this.tryResolveCompleted();
283
376
  }
284
377
  get concurrencyEnabled() {
285
378
  return this.options?.concurrency !== void 0 && this.options?.concurrency > 0;
@@ -380,14 +473,19 @@ var CNSStimulation = class {
380
473
  }
381
474
  }
382
475
  if (!subscriber) {
476
+ const error = new Error(`Subscriber not found for activation task`);
383
477
  this.pushFailedTask({
384
478
  task: neuronActivationTask,
385
- error: new Error(
386
- `Subscriber not found for activation task`
387
- ),
479
+ error,
388
480
  aborted: false
389
481
  });
390
482
  return () => {
483
+ this.processResponseOrResponses(
484
+ void 0,
485
+ neuronActivationTask.input,
486
+ void 0,
487
+ error
488
+ );
391
489
  };
392
490
  }
393
491
  const neuron2 = subscriber.neuron;
@@ -434,13 +532,13 @@ var CNSStimulation = class {
434
532
  error: error instanceof Error ? error : new Error(String(error)),
435
533
  aborted: isAborted
436
534
  });
437
- this.processResponseOrResponses(
438
- neuron2,
439
- inputSignal,
440
- void 0,
441
- error
442
- );
443
535
  return () => {
536
+ this.processResponseOrResponses(
537
+ neuron2,
538
+ inputSignal,
539
+ void 0,
540
+ error
541
+ );
444
542
  };
445
543
  }
446
544
  const maxDuration = neuron2.maxDuration;
@@ -510,8 +608,26 @@ var CNSStimulation = class {
510
608
  this.processResponse(emitter, inputSignal, void 0, error);
511
609
  return;
512
610
  }
513
- for (const signal of outputSignalOrSignals) {
514
- this.processResponse(emitter, inputSignal, signal, error);
611
+ let perSignal;
612
+ if (!error) {
613
+ perSignal = new Array(outputSignalOrSignals.length);
614
+ let reserved = 0;
615
+ for (let i = 0; i < outputSignalOrSignals.length; i++) {
616
+ const c = outputSignalOrSignals[i]?.collateral;
617
+ const n = c ? this.cns.network.getSubscribers(c).length : 0;
618
+ perSignal[i] = n;
619
+ reserved += n;
620
+ }
621
+ this.reservedActivations += reserved;
622
+ }
623
+ for (let i = 0; i < outputSignalOrSignals.length; i++) {
624
+ if (perSignal) this.reservedActivations -= perSignal[i];
625
+ this.processResponse(
626
+ emitter,
627
+ inputSignal,
628
+ outputSignalOrSignals[i],
629
+ error
630
+ );
515
631
  }
516
632
  return;
517
633
  }
@@ -565,9 +681,12 @@ var CNSStimulation = class {
565
681
  this.ctxStore,
566
682
  inputSignal,
567
683
  outputSignal,
568
- this.qSize + this.scheduledCount,
684
+ this.pendingActivations + this.activeOperations,
685
+ this.pendingActivations,
686
+ this.activeOperations,
569
687
  this.options?.maxNeuronHops && emitter ? this.neuronVisitMap?.get(emitter) ?? 0 : void 0,
570
- error
688
+ error,
689
+ emitter
571
690
  )
572
691
  );
573
692
  } catch (e) {
@@ -583,21 +702,35 @@ var CNSStimulation = class {
583
702
  if (maybePromise && typeof maybePromise.then === "function") {
584
703
  maybePromise.then(
585
704
  () => {
586
- for (let i = 0; i < subscriberActivationTasks.length; i++) {
587
- this.scheduledCount--;
588
- this.pendingTasks?.delete(subscriberActivationTasks[i]);
589
- this.qEnqueue(subscriberActivationTasks[i]);
705
+ this.beginTurn();
706
+ try {
707
+ for (let i = 0; i < subscriberActivationTasks.length; i++) {
708
+ this.scheduledCount--;
709
+ this.pendingTasks?.delete(
710
+ subscriberActivationTasks[i]
711
+ );
712
+ this.qEnqueue(subscriberActivationTasks[i]);
713
+ }
714
+ this.tryResolveCompleted();
715
+ } finally {
716
+ this.endTurn();
590
717
  }
591
- this.tryResolveCompleted();
592
718
  },
593
719
  (error2) => {
594
720
  this.onResponseError = error2 instanceof Error ? error2 : new Error(String(error2));
595
- for (let i = 0; i < subscriberActivationTasks.length; i++) {
596
- this.scheduledCount--;
597
- this.pendingTasks?.delete(subscriberActivationTasks[i]);
598
- this.qEnqueue(subscriberActivationTasks[i]);
721
+ this.beginTurn();
722
+ try {
723
+ for (let i = 0; i < subscriberActivationTasks.length; i++) {
724
+ this.scheduledCount--;
725
+ this.pendingTasks?.delete(
726
+ subscriberActivationTasks[i]
727
+ );
728
+ this.qEnqueue(subscriberActivationTasks[i]);
729
+ }
730
+ this.tryResolveCompleted();
731
+ } finally {
732
+ this.endTurn();
599
733
  }
600
- this.tryResolveCompleted();
601
734
  }
602
735
  );
603
736
  return;
@@ -610,12 +743,21 @@ var CNSStimulation = class {
610
743
  this.tryResolveCompleted();
611
744
  }
612
745
  responseToSignal(signalOrSignals) {
613
- if (Array.isArray(signalOrSignals)) {
614
- this.processResponseOrResponses(void 0, void 0, signalOrSignals);
615
- return;
746
+ this.beginTurn();
747
+ try {
748
+ if (Array.isArray(signalOrSignals)) {
749
+ this.processResponseOrResponses(
750
+ void 0,
751
+ void 0,
752
+ signalOrSignals
753
+ );
754
+ return;
755
+ }
756
+ this.processResponse(void 0, void 0, signalOrSignals);
757
+ this.tryResolveCompleted();
758
+ } finally {
759
+ this.endTurn();
616
760
  }
617
- this.processResponse(void 0, void 0, signalOrSignals);
618
- this.tryResolveCompleted();
619
761
  }
620
762
  };
621
763
 
@@ -962,6 +1104,10 @@ var CNS = class {
962
1104
  * Global response listeners applied to every stimulation.
963
1105
  */
964
1106
  this.globalResponseListeners = [];
1107
+ /**
1108
+ * Global batch-boundary listeners applied to every stimulation.
1109
+ */
1110
+ this.globalDrainListeners = [];
965
1111
  this.network = new CNSNetwork(this.neurons);
966
1112
  this.global = global;
967
1113
  }
@@ -975,6 +1121,50 @@ var CNS = class {
975
1121
  if (idx >= 0) this.globalResponseListeners.splice(idx, 1);
976
1122
  };
977
1123
  }
1124
+ /**
1125
+ * Register a listener called once at the end of every synchronous turn of
1126
+ * every stimulation - see {@link TCNSStimulationDrain}. This is how an
1127
+ * integration (a state manager, an in-memory database) installs a single
1128
+ * commit point for the whole organism instead of passing `onDrain` per call.
1129
+ *
1130
+ * Returns an unsubscribe function.
1131
+ */
1132
+ addDrainListener(listener) {
1133
+ this.globalDrainListeners.push(listener);
1134
+ let active = true;
1135
+ return () => {
1136
+ if (!active) return;
1137
+ active = false;
1138
+ const idx = this.globalDrainListeners.indexOf(listener);
1139
+ if (idx >= 0) this.globalDrainListeners.splice(idx, 1);
1140
+ };
1141
+ }
1142
+ /**
1143
+ * Fan a drain out to the local and global listeners, or return undefined when
1144
+ * there are none so the stimulation can skip the boundary check entirely.
1145
+ *
1146
+ * Listener errors are isolated: a drain is a notification, and one broken
1147
+ * flush must not stop the others or derail the stimulation that triggered it.
1148
+ */
1149
+ wrapOnDrain(local) {
1150
+ if (this.globalDrainListeners.length === 0 && !local) return void 0;
1151
+ return (d) => {
1152
+ if (local) {
1153
+ try {
1154
+ local(d);
1155
+ } catch (error) {
1156
+ console.error("[CNS] onDrain listener threw", error);
1157
+ }
1158
+ }
1159
+ for (let i = 0; i < this.globalDrainListeners.length; i++) {
1160
+ try {
1161
+ this.globalDrainListeners[i](d);
1162
+ } catch (error) {
1163
+ console.error("[CNS] drain listener threw", error);
1164
+ }
1165
+ }
1166
+ };
1167
+ }
978
1168
  wrapOnResponse(local) {
979
1169
  if (this.globalResponseListeners.length === 0 && !local) {
980
1170
  return void 0;
@@ -1022,7 +1212,8 @@ var CNS = class {
1022
1212
  this,
1023
1213
  this.instanceNeuronQueue,
1024
1214
  options,
1025
- wrapped
1215
+ wrapped,
1216
+ this.wrapOnDrain(options?.onDrain)
1026
1217
  );
1027
1218
  stimulation.responseToSignal(signalOrSignals);
1028
1219
  return stimulation;
@@ -1036,79 +1227,14 @@ var CNS = class {
1036
1227
  this,
1037
1228
  this.instanceNeuronQueue,
1038
1229
  options,
1039
- wrapped
1230
+ wrapped,
1231
+ this.wrapOnDrain(options?.onDrain)
1040
1232
  );
1041
1233
  stimulation.enqueueTasks(tasks);
1042
1234
  return stimulation;
1043
1235
  }
1044
1236
  };
1045
1237
 
1046
- // src/CNSPersistOptionsRegistry.ts
1047
- var CNSPersistOptionsRegistry = class {
1048
- constructor() {
1049
- this.neurons = /* @__PURE__ */ new Map();
1050
- this.neuronNames = /* @__PURE__ */ new WeakMap();
1051
- this.collaterals = /* @__PURE__ */ new Map();
1052
- this.stimulations = /* @__PURE__ */ new Map();
1053
- }
1054
- addNeuron(neuron2, options) {
1055
- this.neurons.set(options.name, neuron2);
1056
- this.neuronNames.set(neuron2, options.name);
1057
- }
1058
- getNeuron(name) {
1059
- return this.neurons.get(name);
1060
- }
1061
- getNeuronName(neuron2) {
1062
- return this.neuronNames.get(neuron2);
1063
- }
1064
- getNamedNeurons() {
1065
- return this.neurons;
1066
- }
1067
- getCollateralName(collateral2) {
1068
- for (const [name, col] of this.collaterals) {
1069
- if (col === collateral2) return name;
1070
- }
1071
- return void 0;
1072
- }
1073
- removeNeuron(name) {
1074
- const neuron2 = this.neurons.get(name);
1075
- if (neuron2) this.neuronNames.delete(neuron2);
1076
- this.neurons.delete(name);
1077
- }
1078
- addCollateral(collateral2, options) {
1079
- this.collaterals.set(options.name, collateral2);
1080
- }
1081
- getCollateral(name) {
1082
- return this.collaterals.get(name);
1083
- }
1084
- removeCollateral(name) {
1085
- this.collaterals.delete(name);
1086
- }
1087
- addStimulation(stimulation, options) {
1088
- this.stimulations.set(options.stimulationId, stimulation);
1089
- }
1090
- getStimulation(stimulationId) {
1091
- return this.stimulations.get(stimulationId);
1092
- }
1093
- removeStimulation(stimulationId) {
1094
- this.stimulations.delete(stimulationId);
1095
- }
1096
- register(name, neuron2, collateralNames) {
1097
- this.addNeuron(neuron2, { name, neuron: neuron2 });
1098
- for (const [key, col] of Object.entries(neuron2.axon)) {
1099
- this.addCollateral(col, {
1100
- name: collateralNames?.[key] ?? key,
1101
- collateral: col
1102
- });
1103
- }
1104
- return this;
1105
- }
1106
- registerCollateral(name, collateral2) {
1107
- this.addCollateral(collateral2, { name, collateral: collateral2 });
1108
- return this;
1109
- }
1110
- };
1111
-
1112
1238
  // src/CNSCollateral.ts
1113
1239
  var CNSCollateral = class {
1114
1240
  createSignal(payload) {
@@ -1311,40 +1437,13 @@ var modality = (afferentPaths) => {
1311
1437
  afferentPaths
1312
1438
  };
1313
1439
  };
1314
- var createPersistRegistry = (namedNeurons) => {
1315
- const registry = new CNSPersistOptionsRegistry();
1316
- for (const [name, entry] of Object.entries(namedNeurons)) {
1317
- const isEntry = "neuron" in entry && !("axon" in entry);
1318
- const neuron2 = isEntry ? entry.neuron : entry;
1319
- const colNames = isEntry ? entry.collaterals ?? {} : {};
1320
- registry.addNeuron(neuron2, { name, neuron: neuron2 });
1321
- for (const [key, col] of Object.entries(neuron2.axon)) {
1322
- registry.addCollateral(col, {
1323
- name: colNames[key] ?? key,
1324
- collateral: col
1325
- });
1326
- }
1327
- }
1328
- return registry;
1329
- };
1330
- var createCNS = (namedNeurons, options) => {
1331
- const neurons = Object.values(namedNeurons).map(
1332
- (entry) => entry && typeof entry === "object" && "neuron" in entry ? entry.neuron : entry
1333
- );
1334
- const cns = new CNS(neurons, options, options?.global);
1335
- const registry = createPersistRegistry(namedNeurons);
1336
- return { cns, registry };
1337
- };
1338
1440
 
1339
1441
  exports.CNS = CNS;
1340
1442
  exports.CNSCollateral = CNSCollateral;
1341
- exports.CNSPersistOptionsRegistry = CNSPersistOptionsRegistry;
1342
1443
  exports.CNSStimulationContextStore = CNSStimulationContextStore;
1343
1444
  exports.CNSStimulationGate = CNSStimulationGate;
1344
1445
  exports.afferentPath = afferentPath;
1345
1446
  exports.collateral = collateral;
1346
- exports.createCNS = createCNS;
1347
- exports.createPersistRegistry = createPersistRegistry;
1348
1447
  exports.modality = modality;
1349
1448
  exports.neuron = neuron;
1350
1449
  exports.neuronFactory = neuronFactory;