@cnstra/core 2.6.0 → 3.0.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/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  export { CNS } from './CNS';
2
2
  export { CNSCollateral } from './CNSCollateral';
3
- export { CNSStimulationContextStore } from './CNSStimulationContextStore';
4
3
  export { CNSStimulationGate } from './utils/CNSStimulationGate';
5
- export type { TCNSStimulationGateOptions, TCNSStimulationGateSignal } from './utils/CNSStimulationGate';
6
- export { collateral, neuron, neuronFactory, withCtx, withGlobal, afferentPath, modality, } from './factory/index';
4
+ export type { TCNSStimulationGateOptions } from './utils/CNSStimulationGate';
5
+ export { collateral, neuron, neuronFactory, withGlobal, afferentPath, modality, } from './factory/index';
7
6
  export type { TNeuronFactory } from './factory/index';
8
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAKhE,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAGxG,OAAO,EACH,UAAU,EACV,MAAM,EACN,aAAa,EACb,OAAO,EACP,UAAU,EACV,YAAY,EACZ,QAAQ,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAKhE,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAG7E,OAAO,EACH,UAAU,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,YAAY,EACZ,QAAQ,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,39 +1,14 @@
1
- // src/CNSStimulationContextStore.ts
2
- var CNSStimulationContextStore = class {
3
- constructor(ctx) {
4
- this.ctx = ctx;
5
- }
6
- get(key) {
7
- return this.ctx?.get(key);
8
- }
9
- set(key, value) {
10
- (this.ctx ?? (this.ctx = /* @__PURE__ */ new Map())).set(key, value);
11
- }
12
- getAll() {
13
- return this.ctx ? new Map(this.ctx) : /* @__PURE__ */ new Map();
14
- }
15
- setAll(values) {
16
- const ctx = this.ctx ?? (this.ctx = /* @__PURE__ */ new Map());
17
- ctx.clear();
18
- for (const [key, value] of values) ctx.set(key, value);
19
- }
20
- delete(key) {
21
- this.ctx?.delete(key);
22
- }
23
- };
24
-
25
1
  // src/CNSStimulation.ts
26
2
  var TASK_DENDRITE = /* @__PURE__ */ Symbol("cnstra.taskDendrite");
27
3
  var CNSDendriteContext = class {
28
- constructor(stimulation, neuron2, abortSignal, cns) {
4
+ constructor(stimulation, abortSignal, cns) {
29
5
  this.stimulation = stimulation;
30
- this.neuron = neuron2;
31
6
  this.abortSignal = abortSignal;
32
7
  this.cns = cns;
33
8
  }
34
- // Prototype getter, not a constructor field: the per-activation allocation is
35
- // unchanged (still 4 fields) and you only pay a single `cns.global` read on the
36
- // dendrites that actually reach for it. Value getter, so `{ global }` destructuring is safe.
9
+ // Prototype getter, not a constructor field: you only pay a single `cns.global`
10
+ // read on the dendrites that actually reach for it. Value getter, so
11
+ // `{ global }` destructuring is safe.
37
12
  get global() {
38
13
  return this.cns.global;
39
14
  }
@@ -44,20 +19,10 @@ var CNSDendriteContext = class {
44
19
  get stimulationContext() {
45
20
  return this.stimulation.options?.stimulationContext;
46
21
  }
47
- get() {
48
- return this.stimulation.getContext().get(this.neuron);
49
- }
50
- set(value) {
51
- this.stimulation.getContext().set(this.neuron, value);
52
- }
53
- delete() {
54
- this.stimulation.getContext().delete(this.neuron);
55
- }
56
22
  };
57
23
  var CNSStimulationResponseImpl = class {
58
- constructor(stimulation, store, inputSignal, outputSignal, queueLength, pendingActivations, activeActivations, hops, error, neuron2) {
24
+ constructor(stimulation, inputSignal, outputSignal, queueLength, pendingActivations, activeActivations, hops, error, neuron2) {
59
25
  this.stimulation = stimulation;
60
- this.store = store;
61
26
  this.inputSignal = inputSignal;
62
27
  this.outputSignal = outputSignal;
63
28
  this.queueLength = queueLength;
@@ -67,9 +32,6 @@ var CNSStimulationResponseImpl = class {
67
32
  this.error = error;
68
33
  this.neuron = neuron2;
69
34
  }
70
- get contextValue() {
71
- return this.store ? this.store.getAll() : /* @__PURE__ */ new Map();
72
- }
73
35
  };
74
36
  var CNSStimulation = class {
75
37
  constructor(cns, instanceNeuronQueue, options, onResponse, onDrain) {
@@ -97,15 +59,11 @@ var CNSStimulation = class {
97
59
  this.isCompleted = false;
98
60
  this.completionRejected = false;
99
61
  this.onDrain = onDrain;
100
- this.ctxStore = options?.ctx;
101
62
  this.instanceNeuronQueue = instanceNeuronQueue;
102
63
  this.onResponse = onResponse;
103
64
  if (this.options?.maxNeuronHops) {
104
65
  this.neuronVisitMap = /* @__PURE__ */ new Map();
105
66
  }
106
- if (this.autoCleanupContextsEnabled) {
107
- this.activeSccCounts = /* @__PURE__ */ new Map();
108
- }
109
67
  }
110
68
  pushFailedTask(failure) {
111
69
  (this.failedTasks ?? (this.failedTasks = [])).push(failure);
@@ -119,10 +77,6 @@ var CNSStimulation = class {
119
77
  this.completionError = error;
120
78
  this.rejectCompleted?.(error);
121
79
  }
122
- /** Lazily-created neuron context store (see {@link ctxStore}). */
123
- get ctx() {
124
- return this.ctxStore ?? (this.ctxStore = new CNSStimulationContextStore());
125
- }
126
80
  // ----- Inlined activation queue / pump -----
127
81
  get canStartOperation() {
128
82
  const limit = this.options?.concurrency ?? Infinity;
@@ -352,12 +306,6 @@ var CNSStimulation = class {
352
306
  ...this.getFailedTasks().map((f) => f.task)
353
307
  ];
354
308
  }
355
- /**
356
- * Get the context store for this stimulation
357
- */
358
- getContext() {
359
- return this.ctx;
360
- }
361
309
  /**
362
310
  * Enqueue activation tasks directly into the stimulation queue
363
311
  */
@@ -375,67 +323,6 @@ var CNSStimulation = class {
375
323
  get concurrencyEnabled() {
376
324
  return this.options?.concurrency !== void 0 && this.options?.concurrency > 0;
377
325
  }
378
- get autoCleanupContextsEnabled() {
379
- return this.cns?.options?.autoCleanupContexts ?? false;
380
- }
381
- /**
382
- * Mark a neuron as active (being processed)
383
- */
384
- markNeuronActive(neuron2) {
385
- if (!this.autoCleanupContextsEnabled) return;
386
- this.incrementSccCount(neuron2);
387
- }
388
- /**
389
- * Mark a neuron as inactive (finished processing)
390
- */
391
- markNeuronInactive(neuron2) {
392
- if (!this.autoCleanupContextsEnabled) return;
393
- this.decrementSccCount(neuron2);
394
- }
395
- /**
396
- * Increment the active count for the SCC containing this neuron
397
- */
398
- incrementSccCount(neuron2) {
399
- const counts = this.activeSccCounts;
400
- if (!counts) return;
401
- const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
402
- if (sccIndex === void 0) return;
403
- const currentCount = counts.get(sccIndex) || 0;
404
- counts.set(sccIndex, currentCount + 1);
405
- }
406
- /**
407
- * Decrement the active count for the SCC containing this neuron
408
- */
409
- decrementSccCount(neuron2) {
410
- const counts = this.activeSccCounts;
411
- if (!counts) return;
412
- const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
413
- if (sccIndex === void 0) return;
414
- const currentCount = counts.get(sccIndex) || 0;
415
- const nextCount = Math.max(0, currentCount - 1);
416
- counts.set(sccIndex, nextCount);
417
- if (currentCount === 0) {
418
- console.warn(
419
- `[CNSStimulation] Attempting to decrement SCC count below 0 for neuron`
420
- );
421
- }
422
- }
423
- /**
424
- * Check if a neuron can be guaranteed not to be visited again
425
- */
426
- canNeuronBeGuaranteedDone(neuron2) {
427
- if (!this.autoCleanupContextsEnabled || !this.activeSccCounts)
428
- return false;
429
- return this.cns.network.canNeuronBeGuaranteedDone(
430
- neuron2,
431
- this.activeSccCounts
432
- );
433
- }
434
- cleanupCtxIfNeeded(neuron2) {
435
- if (this.autoCleanupContextsEnabled && this.canNeuronBeGuaranteedDone(neuron2)) {
436
- this.ctxStore?.delete(neuron2);
437
- }
438
- }
439
326
  createSubscriberQueueItem(subscriber, inputSignal) {
440
327
  if (this.options?.maxNeuronHops) {
441
328
  if ((this.neuronVisitMap?.get(subscriber.neuron) ?? 0) >= this.options?.maxNeuronHops) {
@@ -509,7 +396,6 @@ var CNSStimulation = class {
509
396
  );
510
397
  }
511
398
  runStarter(neuron2, dendrite, inputSignal, neuronActivationTask) {
512
- this.markNeuronActive(neuron2);
513
399
  let response;
514
400
  try {
515
401
  response = dendrite.response(
@@ -517,13 +403,11 @@ var CNSStimulation = class {
517
403
  neuron2.axon,
518
404
  new CNSDendriteContext(
519
405
  this,
520
- neuron2,
521
406
  this.options?.abortSignal,
522
407
  this.cns
523
408
  )
524
409
  );
525
410
  } catch (error) {
526
- this.markNeuronInactive(neuron2);
527
411
  const isAborted = this.options?.abortSignal?.aborted ?? false;
528
412
  this.pushFailedTask({
529
413
  task: neuronActivationTask,
@@ -563,7 +447,6 @@ var CNSStimulation = class {
563
447
  return timedPromise.then(
564
448
  (signal) => {
565
449
  return () => {
566
- this.markNeuronInactive(neuron2);
567
450
  return this.processResponseOrResponses(
568
451
  neuron2,
569
452
  inputSignal,
@@ -573,7 +456,6 @@ var CNSStimulation = class {
573
456
  },
574
457
  (error) => {
575
458
  return () => {
576
- this.markNeuronInactive(neuron2);
577
459
  const isAborted = this.options?.abortSignal?.aborted ?? false;
578
460
  this.pushFailedTask({
579
461
  task: neuronActivationTask,
@@ -591,7 +473,6 @@ var CNSStimulation = class {
591
473
  );
592
474
  } else {
593
475
  return () => {
594
- this.markNeuronInactive(neuron2);
595
476
  return this.processResponseOrResponses(
596
477
  neuron2,
597
478
  inputSignal,
@@ -637,7 +518,6 @@ var CNSStimulation = class {
637
518
  const onResponse = this.onResponse;
638
519
  if (!onResponse) {
639
520
  if (collateral2 && !error) {
640
- if (emitter) this.cleanupCtxIfNeeded(emitter);
641
521
  const n = subscribers.length;
642
522
  if (n > 0) {
643
523
  const tasks = new Array(n);
@@ -659,7 +539,6 @@ var CNSStimulation = class {
659
539
  }
660
540
  const subscriberActivationTasks = [];
661
541
  if (collateral2 && !error) {
662
- if (emitter) this.cleanupCtxIfNeeded(emitter);
663
542
  const pending = this.pendingTasks ?? (this.pendingTasks = /* @__PURE__ */ new Set());
664
543
  for (let i = 0; i < subscribers.length; i++) {
665
544
  const task = this.createSubscriberQueueItem(
@@ -676,7 +555,6 @@ var CNSStimulation = class {
676
555
  maybePromise = onResponse(
677
556
  new CNSStimulationResponseImpl(
678
557
  this,
679
- this.ctxStore,
680
558
  inputSignal,
681
559
  outputSignal,
682
560
  this.pendingActivations + this.activeOperations,
@@ -822,8 +700,9 @@ var CNSNetwork = class {
822
700
  * Strongly Connected Components of the neuron graph.
823
701
  * Each component is a set of neuron objects that can reach each other.
824
702
  *
825
- * Computed lazily on first access: the SCC machinery is only needed for
826
- * `autoCleanupContexts` (off by default), so most networks never pay for it.
703
+ * Computed lazily on first access: the SCC machinery only drives graph
704
+ * introspection (`getSCCSetByNeuron`, `canNeuronBeGuaranteedDone`), so a
705
+ * network that never inspects reachability never pays for it.
827
706
  */
828
707
  this._stronglyConnectedComponents = [];
829
708
  this.sccBuilt = false;
@@ -1109,16 +988,20 @@ var CNS = class {
1109
988
  this.network = new CNSNetwork(this.neurons);
1110
989
  this.global = global;
1111
990
  }
1112
- addResponseListener(listener) {
1113
- this.globalResponseListeners.push(listener);
991
+ /** Push a listener onto a list; return an idempotent unsubscribe. */
992
+ addListener(list, listener) {
993
+ list.push(listener);
1114
994
  let active = true;
1115
995
  return () => {
1116
996
  if (!active) return;
1117
997
  active = false;
1118
- const idx = this.globalResponseListeners.indexOf(listener);
1119
- if (idx >= 0) this.globalResponseListeners.splice(idx, 1);
998
+ const idx = list.indexOf(listener);
999
+ if (idx >= 0) list.splice(idx, 1);
1120
1000
  };
1121
1001
  }
1002
+ addResponseListener(listener) {
1003
+ return this.addListener(this.globalResponseListeners, listener);
1004
+ }
1122
1005
  /**
1123
1006
  * Register a listener called once at the end of every synchronous turn of
1124
1007
  * every stimulation - see {@link TCNSStimulationDrain}. This is how an
@@ -1128,14 +1011,7 @@ var CNS = class {
1128
1011
  * Returns an unsubscribe function.
1129
1012
  */
1130
1013
  addDrainListener(listener) {
1131
- this.globalDrainListeners.push(listener);
1132
- let active = true;
1133
- return () => {
1134
- if (!active) return;
1135
- active = false;
1136
- const idx = this.globalDrainListeners.indexOf(listener);
1137
- if (idx >= 0) this.globalDrainListeners.splice(idx, 1);
1138
- };
1014
+ return this.addListener(this.globalDrainListeners, listener);
1139
1015
  }
1140
1016
  /**
1141
1017
  * Fan a drain out to the local and global listeners, or return undefined when
@@ -1204,15 +1080,18 @@ var CNS = class {
1204
1080
  }
1205
1081
  };
1206
1082
  }
1207
- stimulate(signalOrSignals, options) {
1208
- const wrapped = this.wrapOnResponse(options?.onResponse);
1209
- const stimulation = new CNSStimulation(
1083
+ /** Build a stimulation (wired listeners, unseeded). Shared by stimulate/activate. */
1084
+ createStimulation(options) {
1085
+ return new CNSStimulation(
1210
1086
  this,
1211
1087
  this.instanceNeuronQueue,
1212
1088
  options,
1213
- wrapped,
1089
+ this.wrapOnResponse(options?.onResponse),
1214
1090
  this.wrapOnDrain(options?.onDrain)
1215
1091
  );
1092
+ }
1093
+ stimulate(signalOrSignals, options) {
1094
+ const stimulation = this.createStimulation(options);
1216
1095
  stimulation.responseToSignal(signalOrSignals);
1217
1096
  return stimulation;
1218
1097
  }
@@ -1220,14 +1099,7 @@ var CNS = class {
1220
1099
  * Start a stimulation with activation tasks directly
1221
1100
  */
1222
1101
  activate(tasks, options) {
1223
- const wrapped = this.wrapOnResponse(options?.onResponse);
1224
- const stimulation = new CNSStimulation(
1225
- this,
1226
- this.instanceNeuronQueue,
1227
- options,
1228
- wrapped,
1229
- this.wrapOnDrain(options?.onDrain)
1230
- );
1102
+ const stimulation = this.createStimulation(options);
1231
1103
  stimulation.enqueueTasks(tasks);
1232
1104
  return stimulation;
1233
1105
  }
@@ -1415,13 +1287,11 @@ var neuron = (axon) => {
1415
1287
  };
1416
1288
  var neuronFactory = () => {
1417
1289
  const factory = {
1418
- withCtx: () => factory,
1419
1290
  withGlobal: () => factory,
1420
1291
  neuron: (axon) => neuron(axon)
1421
1292
  };
1422
1293
  return factory;
1423
1294
  };
1424
- var withCtx = () => neuronFactory();
1425
1295
  var withGlobal = () => neuronFactory();
1426
1296
  var afferentPath = (parentAfferentPath) => {
1427
1297
  return {
@@ -1436,6 +1306,6 @@ var modality = (afferentPaths) => {
1436
1306
  };
1437
1307
  };
1438
1308
 
1439
- export { CNS, CNSCollateral, CNSStimulationContextStore, CNSStimulationGate, afferentPath, collateral, modality, neuron, neuronFactory, withCtx, withGlobal };
1309
+ export { CNS, CNSCollateral, CNSStimulationGate, afferentPath, collateral, modality, neuron, neuronFactory, withGlobal };
1440
1310
  //# sourceMappingURL=index.js.map
1441
1311
  //# sourceMappingURL=index.js.map