@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.
- package/dist/CNS.d.ts +32 -10
- package/dist/CNS.d.ts.map +1 -1
- package/dist/CNSCollateral.d.ts +2 -2
- package/dist/CNSCollateral.d.ts.map +1 -1
- package/dist/CNSNetwork.d.ts +7 -7
- package/dist/CNSNetwork.d.ts.map +1 -1
- package/dist/CNSStimulation.d.ts +55 -15
- package/dist/CNSStimulation.d.ts.map +1 -1
- package/dist/CNSStimulationContextStore.d.ts +1 -1
- package/dist/CNSStimulationContextStore.d.ts.map +1 -1
- package/dist/factory/index.d.ts +26 -82
- package/dist/factory/index.d.ts.map +1 -1
- package/dist/index.cjs +235 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +236 -134
- package/dist/index.js.map +1 -1
- package/dist/utils/CNSStimulationGate.d.ts +7 -7
- package/dist/utils/CNSStimulationGate.d.ts.map +1 -1
- package/package.json +4 -1
- package/dist/CNSPersistOptionsRegistry.d.ts +0 -28
- package/dist/CNSPersistOptionsRegistry.d.ts.map +0 -1
- package/dist/interfaces/ICNS.d.ts +0 -20
- package/dist/interfaces/ICNS.d.ts.map +0 -1
- package/dist/interfaces/ICNSCollateral.d.ts +0 -6
- package/dist/interfaces/ICNSCollateral.d.ts.map +0 -1
- package/dist/interfaces/ICNSStimulationContextStore.d.ts +0 -8
- package/dist/interfaces/ICNSStimulationContextStore.d.ts.map +0 -1
- package/dist/types/TCNSAfferentPath.d.ts +0 -4
- package/dist/types/TCNSAfferentPath.d.ts.map +0 -1
- package/dist/types/TCNSAxon.d.ts +0 -26
- package/dist/types/TCNSAxon.d.ts.map +0 -1
- package/dist/types/TCNSDendrite.d.ts +0 -9
- package/dist/types/TCNSDendrite.d.ts.map +0 -1
- package/dist/types/TCNSHandlerContext.d.ts +0 -24
- package/dist/types/TCNSHandlerContext.d.ts.map +0 -1
- package/dist/types/TCNSLocalContextValueStore.d.ts +0 -6
- package/dist/types/TCNSLocalContextValueStore.d.ts.map +0 -1
- package/dist/types/TCNSModality.d.ts +0 -5
- package/dist/types/TCNSModality.d.ts.map +0 -1
- package/dist/types/TCNSNeuron.d.ts +0 -12
- package/dist/types/TCNSNeuron.d.ts.map +0 -1
- package/dist/types/TCNSNeuronActivationTask.d.ts +0 -8
- package/dist/types/TCNSNeuronActivationTask.d.ts.map +0 -1
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts +0 -7
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts.map +0 -1
- package/dist/types/TCNSNeuronResponseReturn.d.ts +0 -9
- package/dist/types/TCNSNeuronResponseReturn.d.ts.map +0 -1
- package/dist/types/TCNSOptions.d.ts +0 -11
- package/dist/types/TCNSOptions.d.ts.map +0 -1
- package/dist/types/TCNSPersist.d.ts +0 -16
- package/dist/types/TCNSPersist.d.ts.map +0 -1
- package/dist/types/TCNSSignal.d.ts +0 -6
- package/dist/types/TCNSSignal.d.ts.map +0 -1
- package/dist/types/TCNSStimulationOptions.d.ts +0 -14
- package/dist/types/TCNSStimulationOptions.d.ts.map +0 -1
- package/dist/types/TCNSStimulationQueueItem.d.ts +0 -11
- package/dist/types/TCNSStimulationQueueItem.d.ts.map +0 -1
- package/dist/types/TCNSStimulationResponse.d.ts +0 -17
- package/dist/types/TCNSStimulationResponse.d.ts.map +0 -1
- package/dist/types/TCNSStimulationSerializedContextValue.d.ts +0 -4
- package/dist/types/TCNSStimulationSerializedContextValue.d.ts.map +0 -1
- package/dist/types/TCNSSubscriber.d.ts +0 -7
- 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
|
-
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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.
|
|
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
|
-
|
|
280
|
-
|
|
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
|
|
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
|
-
|
|
514
|
-
|
|
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.
|
|
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
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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;
|