@cnstra/core 1.8.1 → 2.0.1
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/README.md +8 -4
- package/dist/CNS.d.ts +6 -9
- package/dist/CNS.d.ts.map +1 -1
- package/dist/CNSCollateral.d.ts +3 -5
- package/dist/CNSCollateral.d.ts.map +1 -1
- package/dist/CNSInstanceNeuronQueue.d.ts +0 -1
- package/dist/CNSInstanceNeuronQueue.d.ts.map +1 -1
- package/dist/CNSNetwork.d.ts +16 -20
- package/dist/CNSNetwork.d.ts.map +1 -1
- package/dist/CNSNeuronActivationPump.d.ts +5 -5
- package/dist/CNSNeuronActivationPump.d.ts.map +1 -1
- package/dist/CNSPersistOptionsRegistry.d.ts +22 -0
- package/dist/CNSPersistOptionsRegistry.d.ts.map +1 -0
- package/dist/CNSStimulation.d.ts +16 -15
- package/dist/CNSStimulation.d.ts.map +1 -1
- package/dist/CNSStimulationContextStore.d.ts +6 -6
- package/dist/CNSStimulationContextStore.d.ts.map +1 -1
- package/dist/factory/index.d.ts +97 -14
- package/dist/factory/index.d.ts.map +1 -1
- package/dist/index.cjs +285 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +283 -198
- package/dist/index.js.map +1 -1
- package/dist/interfaces/ICNS.d.ts +5 -4
- package/dist/interfaces/ICNS.d.ts.map +1 -1
- package/dist/interfaces/ICNSCollateral.d.ts +3 -3
- package/dist/interfaces/ICNSCollateral.d.ts.map +1 -1
- package/dist/interfaces/ICNSStimulationContextStore.d.ts +5 -6
- package/dist/interfaces/ICNSStimulationContextStore.d.ts.map +1 -1
- package/dist/types/TCNSAfferentPath.d.ts +4 -0
- package/dist/types/TCNSAfferentPath.d.ts.map +1 -0
- package/dist/types/TCNSAxon.d.ts +23 -2
- package/dist/types/TCNSAxon.d.ts.map +1 -1
- package/dist/types/TCNSDendrite.d.ts +6 -6
- package/dist/types/TCNSDendrite.d.ts.map +1 -1
- package/dist/types/TCNSModality.d.ts +5 -0
- package/dist/types/TCNSModality.d.ts.map +1 -0
- package/dist/types/TCNSNeuron.d.ts +3 -3
- package/dist/types/TCNSNeuron.d.ts.map +1 -1
- package/dist/types/TCNSNeuronActivationTask.d.ts +5 -5
- package/dist/types/TCNSNeuronActivationTask.d.ts.map +1 -1
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts +2 -2
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts.map +1 -1
- package/dist/types/TCNSNeuronResponseReturn.d.ts +8 -2
- package/dist/types/TCNSNeuronResponseReturn.d.ts.map +1 -1
- package/dist/types/TCNSPersist.d.ts +16 -0
- package/dist/types/TCNSPersist.d.ts.map +1 -0
- package/dist/types/TCNSSignal.d.ts +4 -3
- package/dist/types/TCNSSignal.d.ts.map +1 -1
- package/dist/types/TCNSStimulationOptions.d.ts +7 -9
- package/dist/types/TCNSStimulationOptions.d.ts.map +1 -1
- package/dist/types/TCNSStimulationQueueItem.d.ts +4 -3
- package/dist/types/TCNSStimulationQueueItem.d.ts.map +1 -1
- package/dist/types/TCNSStimulationResponse.d.ts +10 -11
- package/dist/types/TCNSStimulationResponse.d.ts.map +1 -1
- package/dist/types/TCNSSubscriber.d.ts +1 -1
- package/dist/types/TCNSSubscriber.d.ts.map +1 -1
- package/dist/utils/CNSDrainGuard.d.ts +27 -0
- package/dist/utils/CNSDrainGuard.d.ts.map +1 -0
- package/package.json +17 -5
package/dist/index.cjs
CHANGED
|
@@ -12,12 +12,11 @@ var CNSStimulationContextStore = class {
|
|
|
12
12
|
this.ctx.set(key, value);
|
|
13
13
|
}
|
|
14
14
|
getAll() {
|
|
15
|
-
return
|
|
15
|
+
return new Map(this.ctx);
|
|
16
16
|
}
|
|
17
17
|
setAll(values) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
18
|
+
this.ctx.clear();
|
|
19
|
+
for (const [key, value] of values) this.ctx.set(key, value);
|
|
21
20
|
}
|
|
22
21
|
delete(key) {
|
|
23
22
|
this.ctx.delete(key);
|
|
@@ -164,10 +163,7 @@ var CNSStimulation = class {
|
|
|
164
163
|
* Track active SCCs: SCC index -> count of active neurons in that SCC
|
|
165
164
|
*/
|
|
166
165
|
this.activeSccCounts = /* @__PURE__ */ new Map();
|
|
167
|
-
this.ctx = options?.ctx ?? new CNSStimulationContextStore(
|
|
168
|
-
new Map(Object.entries(options?.contextValues ?? {}))
|
|
169
|
-
);
|
|
170
|
-
this.id = options?.stimulationId || Math.random().toString(36).slice(2);
|
|
166
|
+
this.ctx = options?.ctx ?? new CNSStimulationContextStore();
|
|
171
167
|
this.queue = new CNSNeuronActivationPump(
|
|
172
168
|
(neuronActivationTask) => this.executeActivationTask(neuronActivationTask),
|
|
173
169
|
options?.concurrency,
|
|
@@ -188,7 +184,7 @@ var CNSStimulation = class {
|
|
|
188
184
|
const queuedTasks = this.queue.getQueuedTasks();
|
|
189
185
|
for (const task of [...queuedTasks]) {
|
|
190
186
|
const alreadyTracked = this.failedTasks.some(
|
|
191
|
-
(ft) => ft.task
|
|
187
|
+
(ft) => ft.task === task
|
|
192
188
|
);
|
|
193
189
|
if (!alreadyTracked) {
|
|
194
190
|
this.failedTasks.push({
|
|
@@ -244,11 +240,7 @@ var CNSStimulation = class {
|
|
|
244
240
|
*/
|
|
245
241
|
enqueueTasks(tasks) {
|
|
246
242
|
for (const task of tasks) {
|
|
247
|
-
|
|
248
|
-
...task,
|
|
249
|
-
stimulationId: this.id
|
|
250
|
-
};
|
|
251
|
-
this.queue.enqueue(taskWithId);
|
|
243
|
+
this.queue.enqueue(task);
|
|
252
244
|
}
|
|
253
245
|
this.tryResolveCompleted();
|
|
254
246
|
}
|
|
@@ -261,22 +253,22 @@ var CNSStimulation = class {
|
|
|
261
253
|
/**
|
|
262
254
|
* Mark a neuron as active (being processed)
|
|
263
255
|
*/
|
|
264
|
-
markNeuronActive(
|
|
256
|
+
markNeuronActive(neuron2) {
|
|
265
257
|
if (!this.autoCleanupContextsEnabled) return;
|
|
266
|
-
this.incrementSccCount(
|
|
258
|
+
this.incrementSccCount(neuron2);
|
|
267
259
|
}
|
|
268
260
|
/**
|
|
269
261
|
* Mark a neuron as inactive (finished processing)
|
|
270
262
|
*/
|
|
271
|
-
markNeuronInactive(
|
|
263
|
+
markNeuronInactive(neuron2) {
|
|
272
264
|
if (!this.autoCleanupContextsEnabled) return;
|
|
273
|
-
this.decrementSccCount(
|
|
265
|
+
this.decrementSccCount(neuron2);
|
|
274
266
|
}
|
|
275
267
|
/**
|
|
276
268
|
* Increment the active count for the SCC containing this neuron
|
|
277
269
|
*/
|
|
278
|
-
incrementSccCount(
|
|
279
|
-
const sccIndex = this.cns.network.
|
|
270
|
+
incrementSccCount(neuron2) {
|
|
271
|
+
const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
|
|
280
272
|
if (sccIndex === void 0) return;
|
|
281
273
|
const currentCount = this.activeSccCounts.get(sccIndex) || 0;
|
|
282
274
|
this.activeSccCounts.set(sccIndex, currentCount + 1);
|
|
@@ -284,66 +276,65 @@ var CNSStimulation = class {
|
|
|
284
276
|
/**
|
|
285
277
|
* Decrement the active count for the SCC containing this neuron
|
|
286
278
|
*/
|
|
287
|
-
decrementSccCount(
|
|
288
|
-
const sccIndex = this.cns.network.
|
|
279
|
+
decrementSccCount(neuron2) {
|
|
280
|
+
const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
|
|
289
281
|
if (sccIndex === void 0) return;
|
|
290
282
|
const currentCount = this.activeSccCounts.get(sccIndex) || 0;
|
|
291
283
|
const nextCount = Math.max(0, currentCount - 1);
|
|
292
284
|
this.activeSccCounts.set(sccIndex, nextCount);
|
|
293
285
|
if (currentCount === 0) {
|
|
294
286
|
console.warn(
|
|
295
|
-
`[CNSStimulation] Attempting to decrement SCC count below 0 for neuron
|
|
287
|
+
`[CNSStimulation] Attempting to decrement SCC count below 0 for neuron`
|
|
296
288
|
);
|
|
297
289
|
}
|
|
298
290
|
}
|
|
299
291
|
/**
|
|
300
292
|
* Check if a neuron can be guaranteed not to be visited again
|
|
301
293
|
*/
|
|
302
|
-
canNeuronBeGuaranteedDone(
|
|
294
|
+
canNeuronBeGuaranteedDone(neuron2) {
|
|
303
295
|
if (!this.autoCleanupContextsEnabled) return false;
|
|
304
296
|
return this.cns.network.canNeuronBeGuaranteedDone(
|
|
305
|
-
|
|
297
|
+
neuron2,
|
|
306
298
|
this.activeSccCounts
|
|
307
299
|
);
|
|
308
300
|
}
|
|
309
301
|
cleanupCtxIfNeeded(neuron2) {
|
|
310
|
-
if (this.autoCleanupContextsEnabled && this.canNeuronBeGuaranteedDone(neuron2
|
|
311
|
-
this.ctx.delete(neuron2
|
|
302
|
+
if (this.autoCleanupContextsEnabled && this.canNeuronBeGuaranteedDone(neuron2)) {
|
|
303
|
+
this.ctx.delete(neuron2);
|
|
312
304
|
}
|
|
313
305
|
}
|
|
314
306
|
createSubscriberQueueItem(subscriber, inputSignal) {
|
|
315
307
|
if (this.options?.maxNeuronHops) {
|
|
316
|
-
if (this.nueronVisitMap?.get(subscriber.neuron
|
|
308
|
+
if ((this.nueronVisitMap?.get(subscriber.neuron) ?? 0) >= this.options?.maxNeuronHops) {
|
|
317
309
|
throw new Error(
|
|
318
|
-
`Max neuron hops reached
|
|
310
|
+
`Max neuron hops reached when trying to enqueue subscriber`
|
|
319
311
|
);
|
|
320
312
|
} else {
|
|
321
313
|
this.nueronVisitMap?.set(
|
|
322
|
-
subscriber.neuron
|
|
323
|
-
(this.nueronVisitMap?.get(subscriber.neuron
|
|
314
|
+
subscriber.neuron,
|
|
315
|
+
(this.nueronVisitMap?.get(subscriber.neuron) ?? 0) + 1
|
|
324
316
|
);
|
|
325
317
|
}
|
|
326
318
|
}
|
|
327
319
|
const neuronActivationTask = {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
dendriteCollateralName: subscriber.dendrite.collateral.name,
|
|
320
|
+
neuron: subscriber.neuron,
|
|
321
|
+
dendriteCollateral: subscriber.dendrite.collateral,
|
|
331
322
|
input: inputSignal
|
|
332
323
|
};
|
|
333
324
|
return neuronActivationTask;
|
|
334
325
|
}
|
|
335
326
|
executeActivationTask(neuronActivationTask) {
|
|
336
327
|
const subscribers = this.cns.network.getSubscribers(
|
|
337
|
-
neuronActivationTask.
|
|
328
|
+
neuronActivationTask.dendriteCollateral
|
|
338
329
|
);
|
|
339
330
|
const subscriber = subscribers.find(
|
|
340
|
-
(s) => s.neuron
|
|
331
|
+
(s) => s.neuron === neuronActivationTask.neuron
|
|
341
332
|
);
|
|
342
333
|
if (!subscriber) {
|
|
343
334
|
this.failedTasks.push({
|
|
344
335
|
task: neuronActivationTask,
|
|
345
336
|
error: new Error(
|
|
346
|
-
`Subscriber not found for
|
|
337
|
+
`Subscriber not found for activation task`
|
|
347
338
|
),
|
|
348
339
|
aborted: false
|
|
349
340
|
});
|
|
@@ -352,28 +343,25 @@ var CNSStimulation = class {
|
|
|
352
343
|
}
|
|
353
344
|
const neuron2 = subscriber.neuron;
|
|
354
345
|
const dendrite = subscriber.dendrite;
|
|
355
|
-
const inputSignal = neuronActivationTask.input
|
|
356
|
-
collateralName: neuronActivationTask.input.collateralName,
|
|
357
|
-
payload: neuronActivationTask.input.payload
|
|
358
|
-
} : void 0;
|
|
346
|
+
const inputSignal = neuronActivationTask.input;
|
|
359
347
|
const starter = () => {
|
|
360
|
-
this.markNeuronActive(neuron2
|
|
348
|
+
this.markNeuronActive(neuron2);
|
|
361
349
|
let response;
|
|
362
350
|
try {
|
|
363
351
|
response = dendrite.response(
|
|
364
352
|
inputSignal?.payload,
|
|
365
353
|
neuron2.axon,
|
|
366
354
|
{
|
|
367
|
-
get: () => this.ctx.get(neuron2
|
|
368
|
-
set: (value) => this.ctx.set(neuron2
|
|
369
|
-
delete: () => this.ctx.delete(neuron2
|
|
355
|
+
get: () => this.ctx.get(neuron2),
|
|
356
|
+
set: (value) => this.ctx.set(neuron2, value),
|
|
357
|
+
delete: () => this.ctx.delete(neuron2),
|
|
370
358
|
abortSignal: this.options?.abortSignal,
|
|
371
359
|
cns: this.cns,
|
|
372
|
-
|
|
360
|
+
stimulation: this
|
|
373
361
|
}
|
|
374
362
|
);
|
|
375
363
|
} catch (error) {
|
|
376
|
-
this.markNeuronInactive(neuron2
|
|
364
|
+
this.markNeuronInactive(neuron2);
|
|
377
365
|
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
378
366
|
this.failedTasks.push({
|
|
379
367
|
task: neuronActivationTask,
|
|
@@ -381,6 +369,7 @@ var CNSStimulation = class {
|
|
|
381
369
|
aborted: isAborted
|
|
382
370
|
});
|
|
383
371
|
this.processResponseOrResponses(
|
|
372
|
+
neuron2,
|
|
384
373
|
inputSignal,
|
|
385
374
|
void 0,
|
|
386
375
|
error
|
|
@@ -393,9 +382,7 @@ var CNSStimulation = class {
|
|
|
393
382
|
const timedPromise = maxDuration && maxDuration > 0 ? new Promise((resolve, reject) => {
|
|
394
383
|
const t = setTimeout(() => {
|
|
395
384
|
const err = new Error(
|
|
396
|
-
`Neuron
|
|
397
|
-
neuron2.name
|
|
398
|
-
)}" exceeded maxDuration ${maxDuration}ms`
|
|
385
|
+
`Neuron exceeded maxDuration ${maxDuration}ms`
|
|
399
386
|
);
|
|
400
387
|
reject(err);
|
|
401
388
|
}, maxDuration);
|
|
@@ -414,8 +401,9 @@ var CNSStimulation = class {
|
|
|
414
401
|
return timedPromise.then(
|
|
415
402
|
(signal) => {
|
|
416
403
|
return () => {
|
|
417
|
-
this.markNeuronInactive(neuron2
|
|
404
|
+
this.markNeuronInactive(neuron2);
|
|
418
405
|
return this.processResponseOrResponses(
|
|
406
|
+
neuron2,
|
|
419
407
|
inputSignal,
|
|
420
408
|
signal
|
|
421
409
|
);
|
|
@@ -423,7 +411,7 @@ var CNSStimulation = class {
|
|
|
423
411
|
},
|
|
424
412
|
(error) => {
|
|
425
413
|
return () => {
|
|
426
|
-
this.markNeuronInactive(neuron2
|
|
414
|
+
this.markNeuronInactive(neuron2);
|
|
427
415
|
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
428
416
|
this.failedTasks.push({
|
|
429
417
|
task: neuronActivationTask,
|
|
@@ -431,6 +419,7 @@ var CNSStimulation = class {
|
|
|
431
419
|
aborted: isAborted
|
|
432
420
|
});
|
|
433
421
|
return this.processResponseOrResponses(
|
|
422
|
+
neuron2,
|
|
434
423
|
inputSignal,
|
|
435
424
|
void 0,
|
|
436
425
|
error
|
|
@@ -440,8 +429,9 @@ var CNSStimulation = class {
|
|
|
440
429
|
);
|
|
441
430
|
} else {
|
|
442
431
|
return () => {
|
|
443
|
-
this.markNeuronInactive(neuron2
|
|
432
|
+
this.markNeuronInactive(neuron2);
|
|
444
433
|
return this.processResponseOrResponses(
|
|
434
|
+
neuron2,
|
|
445
435
|
inputSignal,
|
|
446
436
|
response
|
|
447
437
|
);
|
|
@@ -450,28 +440,25 @@ var CNSStimulation = class {
|
|
|
450
440
|
};
|
|
451
441
|
return this.instanceNeuronQueue.run(neuron2, starter);
|
|
452
442
|
}
|
|
453
|
-
processResponseOrResponses(inputSignal, outputSignalOrSignals, error) {
|
|
443
|
+
processResponseOrResponses(emitter, inputSignal, outputSignalOrSignals, error) {
|
|
454
444
|
if (Array.isArray(outputSignalOrSignals)) {
|
|
455
445
|
if (outputSignalOrSignals.length === 0) {
|
|
456
|
-
this.processResponse(inputSignal, void 0, error);
|
|
446
|
+
this.processResponse(emitter, inputSignal, void 0, error);
|
|
457
447
|
return;
|
|
458
448
|
}
|
|
459
449
|
for (const signal of outputSignalOrSignals) {
|
|
460
|
-
this.processResponse(inputSignal, signal, error);
|
|
450
|
+
this.processResponse(emitter, inputSignal, signal, error);
|
|
461
451
|
}
|
|
462
452
|
return;
|
|
463
453
|
}
|
|
464
|
-
this.processResponse(inputSignal, outputSignalOrSignals, error);
|
|
454
|
+
this.processResponse(emitter, inputSignal, outputSignalOrSignals, error);
|
|
465
455
|
}
|
|
466
|
-
processResponse(inputSignal, outputSignal, error) {
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
const subscribers = collateralName ? this.cns.network.getSubscribers(collateralName) : [];
|
|
456
|
+
processResponse(emitter, inputSignal, outputSignal, error) {
|
|
457
|
+
const collateral2 = outputSignal?.collateral;
|
|
458
|
+
const subscribers = collateral2 ? this.cns.network.getSubscribers(collateral2) : [];
|
|
470
459
|
const subscriberActivationTasks = [];
|
|
471
|
-
if (
|
|
472
|
-
if (
|
|
473
|
-
this.cleanupCtxIfNeeded(ownerNeuron);
|
|
474
|
-
}
|
|
460
|
+
if (collateral2 && !error) {
|
|
461
|
+
if (emitter) this.cleanupCtxIfNeeded(emitter);
|
|
475
462
|
for (let i = 0; i < subscribers.length; i++) {
|
|
476
463
|
const task = this.createSubscriberQueueItem(
|
|
477
464
|
subscribers[i],
|
|
@@ -490,8 +477,7 @@ var CNSStimulation = class {
|
|
|
490
477
|
contextValue: this.ctx.getAll(),
|
|
491
478
|
queueLength: this.queue.length + this.scheduledCount,
|
|
492
479
|
stimulation: this,
|
|
493
|
-
|
|
494
|
-
hops: this.options?.maxNeuronHops && ownerNeuron ? this.nueronVisitMap?.get(ownerNeuron.name) ?? 0 : void 0,
|
|
480
|
+
hops: this.options?.maxNeuronHops && emitter ? this.nueronVisitMap?.get(emitter) ?? 0 : void 0,
|
|
495
481
|
error
|
|
496
482
|
});
|
|
497
483
|
} catch (e) {
|
|
@@ -535,24 +521,10 @@ var CNSStimulation = class {
|
|
|
535
521
|
}
|
|
536
522
|
responseToSignal(signalOrSignals) {
|
|
537
523
|
if (Array.isArray(signalOrSignals)) {
|
|
538
|
-
|
|
539
|
-
const ownerNeuron2 = this.cns.network.getParentNeuronByCollateralName(
|
|
540
|
-
signal.collateralName
|
|
541
|
-
);
|
|
542
|
-
if (ownerNeuron2) {
|
|
543
|
-
this.markNeuronActive(ownerNeuron2.name);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
this.processResponseOrResponses(void 0, signalOrSignals);
|
|
524
|
+
this.processResponseOrResponses(void 0, void 0, signalOrSignals);
|
|
547
525
|
return;
|
|
548
526
|
}
|
|
549
|
-
|
|
550
|
-
signalOrSignals.collateralName
|
|
551
|
-
);
|
|
552
|
-
if (ownerNeuron) {
|
|
553
|
-
this.markNeuronActive(ownerNeuron.name);
|
|
554
|
-
}
|
|
555
|
-
this.processResponse(void 0, signalOrSignals);
|
|
527
|
+
this.processResponse(void 0, void 0, signalOrSignals);
|
|
556
528
|
this.tryResolveCompleted();
|
|
557
529
|
}
|
|
558
530
|
};
|
|
@@ -567,10 +539,10 @@ var CNSInstanceNeuronQueue = class {
|
|
|
567
539
|
if (limit === void 0 || limit <= 0) {
|
|
568
540
|
return fn();
|
|
569
541
|
}
|
|
570
|
-
let gate = this.gates.get(neuron2
|
|
542
|
+
let gate = this.gates.get(neuron2);
|
|
571
543
|
if (!gate) {
|
|
572
544
|
gate = { limit, active: 0, waiters: [] };
|
|
573
|
-
this.gates.set(neuron2
|
|
545
|
+
this.gates.set(neuron2, gate);
|
|
574
546
|
} else {
|
|
575
547
|
gate.limit = limit;
|
|
576
548
|
}
|
|
@@ -579,7 +551,7 @@ var CNSInstanceNeuronQueue = class {
|
|
|
579
551
|
try {
|
|
580
552
|
cb();
|
|
581
553
|
} finally {
|
|
582
|
-
const g = this.gates.get(neuron2
|
|
554
|
+
const g = this.gates.get(neuron2);
|
|
583
555
|
g.active = Math.max(0, g.active - 1);
|
|
584
556
|
if (g.waiters.length > 0) {
|
|
585
557
|
const next = g.waiters.shift();
|
|
@@ -598,7 +570,7 @@ var CNSInstanceNeuronQueue = class {
|
|
|
598
570
|
}
|
|
599
571
|
return new Promise((resolve) => {
|
|
600
572
|
const starter = () => {
|
|
601
|
-
const g = this.gates.get(neuron2
|
|
573
|
+
const g = this.gates.get(neuron2);
|
|
602
574
|
g.active++;
|
|
603
575
|
const ret = fn();
|
|
604
576
|
if (ret && typeof ret.then === "function") {
|
|
@@ -618,11 +590,11 @@ var CNSNetwork = class {
|
|
|
618
590
|
this.neurons = neurons;
|
|
619
591
|
/**
|
|
620
592
|
* Strongly Connected Components of the neuron graph.
|
|
621
|
-
* Each component is a set of neuron
|
|
593
|
+
* Each component is a set of neuron objects that can reach each other.
|
|
622
594
|
*/
|
|
623
595
|
this.stronglyConnectedComponents = [];
|
|
624
596
|
/**
|
|
625
|
-
* Quick lookup: neuron
|
|
597
|
+
* Quick lookup: neuron -> SCC index for fast reachability checks.
|
|
626
598
|
*/
|
|
627
599
|
this.neuronToSCC = /* @__PURE__ */ new Map();
|
|
628
600
|
/**
|
|
@@ -634,68 +606,48 @@ var CNSNetwork = class {
|
|
|
634
606
|
*/
|
|
635
607
|
this.sccAncestors = /* @__PURE__ */ new Map();
|
|
636
608
|
/**
|
|
637
|
-
* Fast lookup:
|
|
609
|
+
* Fast lookup: collateral -> list of (neuron, dendrite) subscribers.
|
|
638
610
|
* Built once at construction time.
|
|
639
611
|
*/
|
|
640
612
|
this.subIndex = /* @__PURE__ */ new Map();
|
|
641
|
-
this.neuronIndex = /* @__PURE__ */ new Map();
|
|
642
613
|
this.dendriteIndex = /* @__PURE__ */ new Map();
|
|
643
|
-
this.collateralIndex = /* @__PURE__ */ new
|
|
644
|
-
this.
|
|
614
|
+
this.collateralIndex = /* @__PURE__ */ new Set();
|
|
615
|
+
this.parentNeuronByCollateral = /* @__PURE__ */ new Map();
|
|
645
616
|
this.validateUniqueIdentifiers();
|
|
646
617
|
this.buildIndexes();
|
|
647
618
|
this.buildSCC();
|
|
648
619
|
}
|
|
649
620
|
/**
|
|
650
621
|
* Validate uniqueness constraints:
|
|
651
|
-
* -
|
|
652
|
-
*
|
|
653
|
-
*
|
|
622
|
+
* - (legacy) collateral instances used to be single-owner; in object-identity routing
|
|
623
|
+
* a collateral can be emitted by multiple neurons (fan-in), so we no longer
|
|
624
|
+
* enforce single ownership here.
|
|
654
625
|
* Throws aggregated error if violations are found.
|
|
655
626
|
*/
|
|
656
627
|
validateUniqueIdentifiers() {
|
|
657
|
-
const errors = [];
|
|
658
|
-
const seenNeuronNames = /* @__PURE__ */ new Set();
|
|
659
|
-
for (const neuron2 of this.neurons) {
|
|
660
|
-
const name = neuron2?.name ?? "";
|
|
661
|
-
if (!name || typeof name !== "string" || name.trim().length === 0) {
|
|
662
|
-
errors.push(`Neuron has empty or invalid name: "${name}"`);
|
|
663
|
-
} else if (seenNeuronNames.has(name)) {
|
|
664
|
-
errors.push(`Duplicate neuron name: "${name}"`);
|
|
665
|
-
} else {
|
|
666
|
-
seenNeuronNames.add(name);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
if (errors.length > 0) {
|
|
670
|
-
throw new Error(
|
|
671
|
-
`[CNS] Topology uniqueness validation failed:
|
|
672
|
-
- ` + errors.join(`
|
|
673
|
-
- `)
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
628
|
}
|
|
677
629
|
/**
|
|
678
630
|
* Build the neuron graph where neurons are connected if one can stimulate the other.
|
|
679
631
|
*/
|
|
680
632
|
buildNeuronGraph() {
|
|
681
633
|
const graph = /* @__PURE__ */ new Map();
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
graph.set(neuronId, /* @__PURE__ */ new Set());
|
|
634
|
+
for (const neuron2 of this.neurons) {
|
|
635
|
+
graph.set(neuron2, /* @__PURE__ */ new Set());
|
|
685
636
|
}
|
|
686
637
|
for (const neuron2 of this.neurons) {
|
|
687
638
|
const reachableNeurons = /* @__PURE__ */ new Set();
|
|
688
639
|
for (const axonKey in neuron2.axon) {
|
|
689
640
|
const collateral2 = neuron2.axon[axonKey];
|
|
690
|
-
const
|
|
691
|
-
|
|
641
|
+
const subscribers = this.subIndex.get(
|
|
642
|
+
collateral2
|
|
643
|
+
);
|
|
692
644
|
if (subscribers) {
|
|
693
645
|
for (const { neuron: targetNeuron } of subscribers) {
|
|
694
|
-
reachableNeurons.add(targetNeuron
|
|
646
|
+
reachableNeurons.add(targetNeuron);
|
|
695
647
|
}
|
|
696
648
|
}
|
|
697
649
|
}
|
|
698
|
-
graph.set(neuron2
|
|
650
|
+
graph.set(neuron2, reachableNeurons);
|
|
699
651
|
}
|
|
700
652
|
return graph;
|
|
701
653
|
}
|
|
@@ -704,48 +656,47 @@ var CNSNetwork = class {
|
|
|
704
656
|
*/
|
|
705
657
|
buildSCC() {
|
|
706
658
|
const graph = this.buildNeuronGraph();
|
|
707
|
-
const neuronIds = this.neurons.map((n) => n.name);
|
|
708
659
|
const index = /* @__PURE__ */ new Map();
|
|
709
660
|
const lowlink = /* @__PURE__ */ new Map();
|
|
710
661
|
const onStack = /* @__PURE__ */ new Set();
|
|
711
662
|
const stack = [];
|
|
712
663
|
const components = [];
|
|
713
664
|
let currentIndex = 0;
|
|
714
|
-
const strongConnect = (
|
|
715
|
-
index.set(
|
|
716
|
-
lowlink.set(
|
|
665
|
+
const strongConnect = (neuron2) => {
|
|
666
|
+
index.set(neuron2, currentIndex);
|
|
667
|
+
lowlink.set(neuron2, currentIndex);
|
|
717
668
|
currentIndex++;
|
|
718
|
-
stack.push(
|
|
719
|
-
onStack.add(
|
|
720
|
-
const neighbors = graph.get(
|
|
669
|
+
stack.push(neuron2);
|
|
670
|
+
onStack.add(neuron2);
|
|
671
|
+
const neighbors = graph.get(neuron2) || /* @__PURE__ */ new Set();
|
|
721
672
|
for (const neighbor of Array.from(neighbors)) {
|
|
722
673
|
if (!index.has(neighbor)) {
|
|
723
674
|
strongConnect(neighbor);
|
|
724
675
|
lowlink.set(
|
|
725
|
-
|
|
726
|
-
Math.min(lowlink.get(
|
|
676
|
+
neuron2,
|
|
677
|
+
Math.min(lowlink.get(neuron2), lowlink.get(neighbor))
|
|
727
678
|
);
|
|
728
679
|
} else if (onStack.has(neighbor)) {
|
|
729
680
|
lowlink.set(
|
|
730
|
-
|
|
731
|
-
Math.min(lowlink.get(
|
|
681
|
+
neuron2,
|
|
682
|
+
Math.min(lowlink.get(neuron2), index.get(neighbor))
|
|
732
683
|
);
|
|
733
684
|
}
|
|
734
685
|
}
|
|
735
|
-
if (lowlink.get(
|
|
686
|
+
if (lowlink.get(neuron2) === index.get(neuron2)) {
|
|
736
687
|
const component = /* @__PURE__ */ new Set();
|
|
737
688
|
let w;
|
|
738
689
|
do {
|
|
739
690
|
w = stack.pop();
|
|
740
691
|
onStack.delete(w);
|
|
741
692
|
component.add(w);
|
|
742
|
-
} while (w !==
|
|
693
|
+
} while (w !== neuron2);
|
|
743
694
|
components.push(component);
|
|
744
695
|
}
|
|
745
696
|
};
|
|
746
|
-
for (const
|
|
747
|
-
if (!index.has(
|
|
748
|
-
strongConnect(
|
|
697
|
+
for (const neuron2 of this.neurons) {
|
|
698
|
+
if (!index.has(neuron2)) {
|
|
699
|
+
strongConnect(neuron2);
|
|
749
700
|
}
|
|
750
701
|
}
|
|
751
702
|
this.stronglyConnectedComponents = components;
|
|
@@ -767,10 +718,10 @@ var CNSNetwork = class {
|
|
|
767
718
|
}
|
|
768
719
|
for (let i = 0; i < this.stronglyConnectedComponents.length; i++) {
|
|
769
720
|
const scc = this.stronglyConnectedComponents[i];
|
|
770
|
-
for (const
|
|
771
|
-
const neighbors = neuronGraph.get(
|
|
772
|
-
for (const
|
|
773
|
-
const neighborSccIndex = this.neuronToSCC.get(
|
|
721
|
+
for (const neuron2 of Array.from(scc)) {
|
|
722
|
+
const neighbors = neuronGraph.get(neuron2) || /* @__PURE__ */ new Set();
|
|
723
|
+
for (const neighbor of Array.from(neighbors)) {
|
|
724
|
+
const neighborSccIndex = this.neuronToSCC.get(neighbor);
|
|
774
725
|
if (neighborSccIndex !== void 0 && neighborSccIndex !== i) {
|
|
775
726
|
this.sccDag.get(neighborSccIndex).add(i);
|
|
776
727
|
}
|
|
@@ -831,23 +782,23 @@ var CNSNetwork = class {
|
|
|
831
782
|
* Returns true if the neuron is in a strongly connected component with more than one member,
|
|
832
783
|
* or if it's in a single-member SCC that can reach itself.
|
|
833
784
|
*/
|
|
834
|
-
|
|
835
|
-
const sccIndex = this.neuronToSCC.get(
|
|
785
|
+
getSCCSetByNeuron(neuron2) {
|
|
786
|
+
const sccIndex = this.neuronToSCC.get(neuron2);
|
|
836
787
|
if (sccIndex === void 0) return;
|
|
837
788
|
return this.stronglyConnectedComponents[sccIndex];
|
|
838
789
|
}
|
|
839
790
|
/**
|
|
840
|
-
* Get the SCC index for a given neuron
|
|
791
|
+
* Get the SCC index for a given neuron
|
|
841
792
|
*/
|
|
842
|
-
|
|
843
|
-
return this.neuronToSCC.get(
|
|
793
|
+
getSccIndexByNeuron(neuron2) {
|
|
794
|
+
return this.neuronToSCC.get(neuron2);
|
|
844
795
|
}
|
|
845
796
|
/**
|
|
846
797
|
* Check if a neuron can be guaranteed not to be visited again during the current propagation.
|
|
847
798
|
* This is the core logic for safe context cleanup.
|
|
848
799
|
*/
|
|
849
|
-
canNeuronBeGuaranteedDone(
|
|
850
|
-
const sccIndex = this.neuronToSCC.get(
|
|
800
|
+
canNeuronBeGuaranteedDone(neuron2, activeSccCounts) {
|
|
801
|
+
const sccIndex = this.neuronToSCC.get(neuron2);
|
|
851
802
|
if (sccIndex === void 0) return true;
|
|
852
803
|
if (activeSccCounts.get(sccIndex) && activeSccCounts.get(sccIndex) > 0) {
|
|
853
804
|
return false;
|
|
@@ -863,11 +814,12 @@ var CNSNetwork = class {
|
|
|
863
814
|
}
|
|
864
815
|
buildIndexes() {
|
|
865
816
|
this.subIndex.clear();
|
|
866
|
-
this.
|
|
817
|
+
this.parentNeuronByCollateral.clear();
|
|
818
|
+
this.dendriteIndex.clear();
|
|
819
|
+
this.collateralIndex.clear();
|
|
867
820
|
for (const neuron2 of this.neurons) {
|
|
868
|
-
this.neuronIndex.set(neuron2.name, neuron2);
|
|
869
821
|
for (const dendrite of neuron2.dendrites) {
|
|
870
|
-
const key = dendrite.collateral
|
|
822
|
+
const key = dendrite.collateral;
|
|
871
823
|
const arr = this.subIndex.get(key) ?? [];
|
|
872
824
|
arr.push({ neuron: neuron2, dendrite });
|
|
873
825
|
this.subIndex.set(
|
|
@@ -877,19 +829,16 @@ var CNSNetwork = class {
|
|
|
877
829
|
this.dendriteIndex.set(key, dendrite);
|
|
878
830
|
}
|
|
879
831
|
Object.values(neuron2.axon).forEach((collateral2) => {
|
|
880
|
-
this.
|
|
881
|
-
collateral2
|
|
832
|
+
this.parentNeuronByCollateral.set(
|
|
833
|
+
collateral2,
|
|
882
834
|
neuron2
|
|
883
835
|
);
|
|
884
|
-
this.collateralIndex.
|
|
885
|
-
collateral2.name,
|
|
886
|
-
collateral2
|
|
887
|
-
);
|
|
836
|
+
this.collateralIndex.add(collateral2);
|
|
888
837
|
});
|
|
889
838
|
}
|
|
890
839
|
}
|
|
891
|
-
|
|
892
|
-
return this.
|
|
840
|
+
getParentNeuronByCollateral(collateral2) {
|
|
841
|
+
return this.parentNeuronByCollateral.get(collateral2);
|
|
893
842
|
}
|
|
894
843
|
getDendrites() {
|
|
895
844
|
return Array.from(this.dendriteIndex.values());
|
|
@@ -897,19 +846,8 @@ var CNSNetwork = class {
|
|
|
897
846
|
getCollaterals() {
|
|
898
847
|
return Array.from(this.collateralIndex.values());
|
|
899
848
|
}
|
|
900
|
-
|
|
901
|
-
return
|
|
902
|
-
}
|
|
903
|
-
getCollateralByName(collateralName) {
|
|
904
|
-
return this.collateralIndex.get(
|
|
905
|
-
collateralName
|
|
906
|
-
);
|
|
907
|
-
}
|
|
908
|
-
getNeuronByName(neuronName) {
|
|
909
|
-
return this.neuronIndex.get(neuronName);
|
|
910
|
-
}
|
|
911
|
-
getSubscribers(collateralName) {
|
|
912
|
-
return this.subIndex.get(collateralName) ?? [];
|
|
849
|
+
getSubscribers(collateral2) {
|
|
850
|
+
return this.subIndex.get(collateral2) ?? [];
|
|
913
851
|
}
|
|
914
852
|
};
|
|
915
853
|
|
|
@@ -918,10 +856,6 @@ var CNS = class {
|
|
|
918
856
|
constructor(neurons, options) {
|
|
919
857
|
this.neurons = neurons;
|
|
920
858
|
this.options = options;
|
|
921
|
-
/**
|
|
922
|
-
* Global per-neuron concurrency gates shared across all stimulations.
|
|
923
|
-
*/
|
|
924
|
-
this.neuronGates = /* @__PURE__ */ new Map();
|
|
925
859
|
/**
|
|
926
860
|
* Global task queue used by stimulation to schedule per-neuron gated work.
|
|
927
861
|
* Does not replace per-stimulation concurrency; only coordinates global per-neuron limits.
|
|
@@ -987,10 +921,14 @@ var CNS = class {
|
|
|
987
921
|
}
|
|
988
922
|
stimulate(signalOrSignals, options) {
|
|
989
923
|
const wrapped = this.wrapOnResponse(options?.onResponse);
|
|
990
|
-
const stimulation = new CNSStimulation(
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
924
|
+
const stimulation = new CNSStimulation(
|
|
925
|
+
this,
|
|
926
|
+
this.instanceNeuronQueue,
|
|
927
|
+
{
|
|
928
|
+
...options,
|
|
929
|
+
onResponse: wrapped
|
|
930
|
+
}
|
|
931
|
+
);
|
|
994
932
|
stimulation.responseToSignal(signalOrSignals);
|
|
995
933
|
return stimulation;
|
|
996
934
|
}
|
|
@@ -999,10 +937,14 @@ var CNS = class {
|
|
|
999
937
|
*/
|
|
1000
938
|
activate(tasks, options) {
|
|
1001
939
|
const wrapped = this.wrapOnResponse(options?.onResponse);
|
|
1002
|
-
const stimulation = new CNSStimulation(
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
940
|
+
const stimulation = new CNSStimulation(
|
|
941
|
+
this,
|
|
942
|
+
this.instanceNeuronQueue,
|
|
943
|
+
{
|
|
944
|
+
...options,
|
|
945
|
+
onResponse: wrapped
|
|
946
|
+
}
|
|
947
|
+
);
|
|
1006
948
|
stimulation.enqueueTasks(tasks);
|
|
1007
949
|
return stimulation;
|
|
1008
950
|
}
|
|
@@ -1010,17 +952,63 @@ var CNS = class {
|
|
|
1010
952
|
|
|
1011
953
|
// src/CNSCollateral.ts
|
|
1012
954
|
var CNSCollateral = class {
|
|
1013
|
-
constructor(name) {
|
|
1014
|
-
this.name = name;
|
|
1015
|
-
}
|
|
1016
955
|
createSignal(payload) {
|
|
1017
|
-
return {
|
|
956
|
+
return { collateral: this, payload };
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
// src/utils/CNSDrainGuard.ts
|
|
961
|
+
var CNSDrainGuard = class {
|
|
962
|
+
constructor(guardOptions) {
|
|
963
|
+
this.guardOptions = guardOptions;
|
|
964
|
+
}
|
|
965
|
+
isDraining() {
|
|
966
|
+
return this.currentDrain !== void 0;
|
|
967
|
+
}
|
|
968
|
+
getCurrentStimulation() {
|
|
969
|
+
return this.currentStimulation;
|
|
970
|
+
}
|
|
971
|
+
drain() {
|
|
972
|
+
if (this.currentDrain) return this.currentDrain;
|
|
973
|
+
const stimulation = this.guardOptions.cns.stimulate(
|
|
974
|
+
this.guardOptions.signal,
|
|
975
|
+
this.createStimulationOptions()
|
|
976
|
+
);
|
|
977
|
+
const drain = stimulation.waitUntilComplete().finally(() => {
|
|
978
|
+
if (this.currentDrain !== drain) return;
|
|
979
|
+
this.currentDrain = void 0;
|
|
980
|
+
this.currentStimulation = void 0;
|
|
981
|
+
this.currentAbortController = void 0;
|
|
982
|
+
});
|
|
983
|
+
this.currentStimulation = stimulation;
|
|
984
|
+
this.currentDrain = drain;
|
|
985
|
+
return drain;
|
|
986
|
+
}
|
|
987
|
+
abort(reason) {
|
|
988
|
+
if (!this.currentAbortController) return false;
|
|
989
|
+
if (this.currentAbortController.signal.aborted) return false;
|
|
990
|
+
this.currentAbortController.abort(reason);
|
|
991
|
+
return true;
|
|
992
|
+
}
|
|
993
|
+
createStimulationOptions() {
|
|
994
|
+
const options = this.guardOptions.options;
|
|
995
|
+
if (options?.abortSignal) {
|
|
996
|
+
return options;
|
|
997
|
+
}
|
|
998
|
+
if (typeof AbortController === "undefined") {
|
|
999
|
+
return options ?? {};
|
|
1000
|
+
}
|
|
1001
|
+
this.currentAbortController = new AbortController();
|
|
1002
|
+
return {
|
|
1003
|
+
...options,
|
|
1004
|
+
abortSignal: this.currentAbortController.signal
|
|
1005
|
+
};
|
|
1018
1006
|
}
|
|
1019
1007
|
};
|
|
1020
1008
|
|
|
1021
1009
|
// src/factory/index.ts
|
|
1022
|
-
var collateral = (
|
|
1023
|
-
var neuron = (
|
|
1010
|
+
var collateral = () => new CNSCollateral();
|
|
1011
|
+
var neuron = (axon) => {
|
|
1024
1012
|
const dendrites = [];
|
|
1025
1013
|
const api = {
|
|
1026
1014
|
setConcurrency: (n) => {
|
|
@@ -1045,29 +1033,129 @@ var neuron = (name, axon) => {
|
|
|
1045
1033
|
return api;
|
|
1046
1034
|
}),
|
|
1047
1035
|
axon,
|
|
1048
|
-
name,
|
|
1049
1036
|
concurrency: void 0,
|
|
1050
1037
|
maxDuration: void 0,
|
|
1051
1038
|
dendrites,
|
|
1052
1039
|
dendrite(s) {
|
|
1053
|
-
|
|
1054
|
-
s
|
|
1055
|
-
|
|
1040
|
+
if ("collateral" in s && "response" in s && Array.isArray(s.collateral)) {
|
|
1041
|
+
for (const collateral2 of s.collateral) {
|
|
1042
|
+
dendrites.push({
|
|
1043
|
+
collateral: collateral2,
|
|
1044
|
+
response: s.response
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
} else {
|
|
1048
|
+
dendrites.push(
|
|
1049
|
+
s
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
return api;
|
|
1053
|
+
},
|
|
1054
|
+
modalityDendrite(s) {
|
|
1055
|
+
const {
|
|
1056
|
+
collateral: collateral2,
|
|
1057
|
+
modality: singleModality,
|
|
1058
|
+
modalities: multipleModalities,
|
|
1059
|
+
afferentPaths: singleAfferentPaths,
|
|
1060
|
+
default: singleDefaultHandler,
|
|
1061
|
+
default: globalDefaultHandler,
|
|
1062
|
+
output
|
|
1063
|
+
} = s;
|
|
1064
|
+
const modalityConfigs = multipleModalities ? multipleModalities : singleModality ? [
|
|
1065
|
+
{
|
|
1066
|
+
modality: singleModality,
|
|
1067
|
+
afferentPaths: singleAfferentPaths,
|
|
1068
|
+
default: singleDefaultHandler
|
|
1069
|
+
}
|
|
1070
|
+
] : [];
|
|
1071
|
+
const response = (payload, axon2, ctx) => {
|
|
1072
|
+
const stimulation = ctx.stimulation;
|
|
1073
|
+
const stimOptions = stimulation?.options;
|
|
1074
|
+
const runGlobalDefault = () => {
|
|
1075
|
+
if (!globalDefaultHandler) {
|
|
1076
|
+
throw new Error(
|
|
1077
|
+
`modalityDendrite: No handler found for modality and no default handler provided`
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
const res = globalDefaultHandler(payload, axon2, ctx);
|
|
1081
|
+
if (res && typeof res.then === "function") {
|
|
1082
|
+
return res.then(
|
|
1083
|
+
(result) => output(result, axon2, ctx)
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
return output(res, axon2, ctx);
|
|
1087
|
+
};
|
|
1088
|
+
if (!stimOptions || !stimOptions.modality) {
|
|
1089
|
+
return runGlobalDefault();
|
|
1090
|
+
}
|
|
1091
|
+
const matchingConfig = modalityConfigs.find(
|
|
1092
|
+
(config) => config.modality === stimOptions.modality
|
|
1093
|
+
);
|
|
1094
|
+
if (!matchingConfig) {
|
|
1095
|
+
return runGlobalDefault();
|
|
1096
|
+
}
|
|
1097
|
+
const stimAfferentPath = stimOptions.afferentPath;
|
|
1098
|
+
const handler = stimAfferentPath && matchingConfig.afferentPaths ? matchingConfig.afferentPaths.get(stimAfferentPath) : void 0;
|
|
1099
|
+
const effectiveHandler = handler ?? matchingConfig.default ?? globalDefaultHandler;
|
|
1100
|
+
if (!effectiveHandler) {
|
|
1101
|
+
throw new Error(
|
|
1102
|
+
`modalityDendrite: No handler found for afferent path in modality and no default handler provided`
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
const maybeResult = effectiveHandler(payload, axon2, ctx);
|
|
1106
|
+
if (maybeResult && typeof maybeResult.then === "function") {
|
|
1107
|
+
return maybeResult.then(
|
|
1108
|
+
(result) => output(result, axon2, ctx)
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
try {
|
|
1112
|
+
return output(maybeResult, axon2, ctx);
|
|
1113
|
+
} catch (error) {
|
|
1114
|
+
if (error instanceof Error && error.message.includes(
|
|
1115
|
+
"Cannot read properties of undefined"
|
|
1116
|
+
)) {
|
|
1117
|
+
const axonKeys = axon2 && typeof axon2 === "object" ? Object.keys(axon2) : "not an object";
|
|
1118
|
+
throw new Error(
|
|
1119
|
+
`modalityDendrite: axon.output is undefined. Axon type: ${typeof axon2}, Axon keys: ${Array.isArray(axonKeys) ? axonKeys.join(", ") : axonKeys}. Make sure the neuron was created with the correct axon structure. Original error: ${error.message}`
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1122
|
+
throw error;
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
dendrites.push({
|
|
1126
|
+
collateral: collateral2,
|
|
1127
|
+
response
|
|
1128
|
+
});
|
|
1056
1129
|
return api;
|
|
1057
1130
|
}
|
|
1058
1131
|
};
|
|
1059
1132
|
return api;
|
|
1060
1133
|
};
|
|
1061
1134
|
var withCtx = () => ({
|
|
1062
|
-
neuron: (
|
|
1063
|
-
return neuron(
|
|
1135
|
+
neuron: (axon) => {
|
|
1136
|
+
return neuron(axon);
|
|
1064
1137
|
}
|
|
1065
1138
|
});
|
|
1139
|
+
var afferentPath = (parentAfferentPath) => {
|
|
1140
|
+
return {
|
|
1141
|
+
...parentAfferentPath !== void 0 && {
|
|
1142
|
+
parentAfferentPath
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
};
|
|
1146
|
+
var modality = (afferentPaths) => {
|
|
1147
|
+
return {
|
|
1148
|
+
afferentPaths
|
|
1149
|
+
};
|
|
1150
|
+
};
|
|
1066
1151
|
|
|
1067
1152
|
exports.CNS = CNS;
|
|
1068
1153
|
exports.CNSCollateral = CNSCollateral;
|
|
1154
|
+
exports.CNSDrainGuard = CNSDrainGuard;
|
|
1069
1155
|
exports.CNSStimulationContextStore = CNSStimulationContextStore;
|
|
1156
|
+
exports.afferentPath = afferentPath;
|
|
1070
1157
|
exports.collateral = collateral;
|
|
1158
|
+
exports.modality = modality;
|
|
1071
1159
|
exports.neuron = neuron;
|
|
1072
1160
|
exports.withCtx = withCtx;
|
|
1073
1161
|
//# sourceMappingURL=index.cjs.map
|