@cnstra/core 2.1.0 → 2.2.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 +40 -0
- package/dist/CNS.d.ts.map +1 -1
- package/dist/CNSPersistOptionsRegistry.d.ts +4 -0
- package/dist/CNSPersistOptionsRegistry.d.ts.map +1 -1
- package/dist/CNSStimulation.d.ts +40 -10
- 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 +17 -9
- package/dist/factory/index.d.ts.map +1 -1
- package/dist/index.cjs +332 -240
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +332 -240
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/CNSNeuronActivationPump.d.ts +0 -27
- package/dist/CNSNeuronActivationPump.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,79 +1,153 @@
|
|
|
1
1
|
// src/CNSStimulationContextStore.ts
|
|
2
2
|
var CNSStimulationContextStore = class {
|
|
3
|
-
constructor(ctx
|
|
3
|
+
constructor(ctx) {
|
|
4
4
|
this.ctx = ctx;
|
|
5
5
|
}
|
|
6
6
|
get(key) {
|
|
7
|
-
return this.ctx
|
|
7
|
+
return this.ctx?.get(key);
|
|
8
8
|
}
|
|
9
9
|
set(key, value) {
|
|
10
|
-
this.ctx.set(key, value);
|
|
10
|
+
(this.ctx ?? (this.ctx = /* @__PURE__ */ new Map())).set(key, value);
|
|
11
11
|
}
|
|
12
12
|
getAll() {
|
|
13
|
-
return new Map(this.ctx);
|
|
13
|
+
return this.ctx ? new Map(this.ctx) : /* @__PURE__ */ new Map();
|
|
14
14
|
}
|
|
15
15
|
setAll(values) {
|
|
16
|
-
this.ctx.
|
|
17
|
-
|
|
16
|
+
const ctx = this.ctx ?? (this.ctx = /* @__PURE__ */ new Map());
|
|
17
|
+
ctx.clear();
|
|
18
|
+
for (const [key, value] of values) ctx.set(key, value);
|
|
18
19
|
}
|
|
19
20
|
delete(key) {
|
|
20
|
-
this.ctx
|
|
21
|
+
this.ctx?.delete(key);
|
|
21
22
|
}
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
// src/
|
|
25
|
-
var
|
|
26
|
-
constructor(
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
25
|
+
// src/CNSStimulation.ts
|
|
26
|
+
var CNSDendriteContext = class {
|
|
27
|
+
constructor(stimulation, neuron2, abortSignal, cns) {
|
|
28
|
+
this.stimulation = stimulation;
|
|
29
|
+
this.neuron = neuron2;
|
|
29
30
|
this.abortSignal = abortSignal;
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.
|
|
34
|
-
|
|
31
|
+
this.cns = cns;
|
|
32
|
+
}
|
|
33
|
+
get() {
|
|
34
|
+
return this.stimulation.getContext().get(this.neuron);
|
|
35
|
+
}
|
|
36
|
+
set(value) {
|
|
37
|
+
this.stimulation.getContext().set(this.neuron, value);
|
|
38
|
+
}
|
|
39
|
+
delete() {
|
|
40
|
+
this.stimulation.getContext().delete(this.neuron);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var CNSStimulationResponseImpl = class {
|
|
44
|
+
constructor(stimulation, store, inputSignal, outputSignal, queueLength, hops, error) {
|
|
45
|
+
this.stimulation = stimulation;
|
|
46
|
+
this.store = store;
|
|
47
|
+
this.inputSignal = inputSignal;
|
|
48
|
+
this.outputSignal = outputSignal;
|
|
49
|
+
this.queueLength = queueLength;
|
|
50
|
+
this.hops = hops;
|
|
51
|
+
this.error = error;
|
|
52
|
+
}
|
|
53
|
+
get contextValue() {
|
|
54
|
+
return this.store ? this.store.getAll() : /* @__PURE__ */ new Map();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var CNSStimulation = class {
|
|
58
|
+
constructor(cns, instanceNeuronQueue, options, onResponse) {
|
|
59
|
+
this.cns = cns;
|
|
60
|
+
this.options = options;
|
|
61
|
+
this.qHead = 0;
|
|
62
|
+
this.qTail = 0;
|
|
63
|
+
this.qSize = 0;
|
|
64
|
+
this.qCapacity = 4;
|
|
35
65
|
this.activeOperations = 0;
|
|
36
|
-
|
|
37
|
-
// NEW: prevent re-entrant pump; defer extra runs
|
|
66
|
+
// Re-entrancy guard for the pump loop.
|
|
38
67
|
this.pumping = false;
|
|
39
68
|
this.needsPump = false;
|
|
40
|
-
|
|
41
|
-
|
|
69
|
+
this.scheduledCount = 0;
|
|
70
|
+
this.isCompleted = false;
|
|
71
|
+
this.completionRejected = false;
|
|
72
|
+
this.ctxStore = options?.ctx;
|
|
73
|
+
this.instanceNeuronQueue = instanceNeuronQueue;
|
|
74
|
+
this.onResponse = onResponse;
|
|
75
|
+
if (this.options?.maxNeuronHops) {
|
|
76
|
+
this.nueronVisitMap = /* @__PURE__ */ new Map();
|
|
77
|
+
}
|
|
78
|
+
if (this.autoCleanupContextsEnabled) {
|
|
79
|
+
this.activeSccCounts = /* @__PURE__ */ new Map();
|
|
42
80
|
}
|
|
43
|
-
this.items = new Array(this.capacity);
|
|
44
81
|
}
|
|
82
|
+
pushFailedTask(failure) {
|
|
83
|
+
(this.failedTasks ?? (this.failedTasks = [])).push(failure);
|
|
84
|
+
}
|
|
85
|
+
finalizeResolve() {
|
|
86
|
+
this.completionRejected = false;
|
|
87
|
+
this.resolveCompleted?.();
|
|
88
|
+
}
|
|
89
|
+
finalizeReject(error) {
|
|
90
|
+
this.completionRejected = true;
|
|
91
|
+
this.completionError = error;
|
|
92
|
+
this.rejectCompleted?.(error);
|
|
93
|
+
}
|
|
94
|
+
/** Lazily-created neuron context store (see {@link ctxStore}). */
|
|
95
|
+
get ctx() {
|
|
96
|
+
return this.ctxStore ?? (this.ctxStore = new CNSStimulationContextStore());
|
|
97
|
+
}
|
|
98
|
+
// ----- Inlined activation queue / pump -----
|
|
45
99
|
get canStartOperation() {
|
|
46
|
-
const limit = this.concurrency ?? Infinity;
|
|
47
|
-
return this.activeOperations < limit && !this.abortSignal?.aborted;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const oldCapacity = this.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
100
|
+
const limit = this.options?.concurrency ?? Infinity;
|
|
101
|
+
return this.activeOperations < limit && !this.options?.abortSignal?.aborted;
|
|
102
|
+
}
|
|
103
|
+
qResize() {
|
|
104
|
+
const oldCapacity = this.qCapacity;
|
|
105
|
+
const oldItems = this.qItems;
|
|
106
|
+
this.qCapacity = oldCapacity * 2;
|
|
107
|
+
const newItems = new Array(this.qCapacity);
|
|
108
|
+
let oldIndex = this.qHead;
|
|
109
|
+
for (let i = 0; i < this.qSize; i++) {
|
|
110
|
+
newItems[i] = oldItems[oldIndex];
|
|
56
111
|
oldIndex = (oldIndex + 1) % oldCapacity;
|
|
57
112
|
}
|
|
58
|
-
this.
|
|
59
|
-
this.
|
|
60
|
-
this.
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (this.
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
68
|
-
|
|
113
|
+
this.qItems = newItems;
|
|
114
|
+
this.qHead = 0;
|
|
115
|
+
this.qTail = this.qSize;
|
|
116
|
+
}
|
|
117
|
+
qDequeue() {
|
|
118
|
+
if (this.qSize === 0) return void 0;
|
|
119
|
+
const items = this.qItems;
|
|
120
|
+
const task = items[this.qHead];
|
|
121
|
+
items[this.qHead] = void 0;
|
|
122
|
+
this.qHead = (this.qHead + 1) % this.qCapacity;
|
|
123
|
+
this.qSize--;
|
|
124
|
+
return task;
|
|
125
|
+
}
|
|
126
|
+
qEnqueueItem(task) {
|
|
127
|
+
if (!this.qItems) {
|
|
128
|
+
this.qItems = new Array(this.qCapacity);
|
|
129
|
+
} else if (this.qSize === this.qCapacity) {
|
|
130
|
+
this.qResize();
|
|
131
|
+
}
|
|
132
|
+
this.qItems[this.qTail] = task;
|
|
133
|
+
this.qTail = (this.qTail + 1) % this.qCapacity;
|
|
134
|
+
this.qSize++;
|
|
135
|
+
}
|
|
136
|
+
/** Enqueue a task and drive the pump unless one is already running. */
|
|
137
|
+
qEnqueue(task) {
|
|
138
|
+
this.qEnqueueItem(task);
|
|
139
|
+
if (!this.pumping) this.pump();
|
|
140
|
+
else this.needsPump = true;
|
|
69
141
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
142
|
+
qGetQueuedTasks() {
|
|
143
|
+
const result = [];
|
|
144
|
+
if (!this.qItems) return result;
|
|
145
|
+
let index = this.qHead;
|
|
146
|
+
for (let i = 0; i < this.qSize; i++) {
|
|
147
|
+
result.push(this.qItems[index]);
|
|
148
|
+
index = (index + 1) % this.qCapacity;
|
|
73
149
|
}
|
|
74
|
-
|
|
75
|
-
this.tail = (this.tail + 1) % this.capacity;
|
|
76
|
-
this.size++;
|
|
150
|
+
return result;
|
|
77
151
|
}
|
|
78
152
|
pump() {
|
|
79
153
|
if (this.pumping) {
|
|
@@ -81,26 +155,26 @@ var CNSNeuronActivationPump = class {
|
|
|
81
155
|
return;
|
|
82
156
|
}
|
|
83
157
|
this.pumping = true;
|
|
84
|
-
while (this.canStartOperation && this.
|
|
85
|
-
const
|
|
158
|
+
while (this.canStartOperation && this.qSize > 0) {
|
|
159
|
+
const task = this.qDequeue();
|
|
86
160
|
this.activeOperations++;
|
|
87
|
-
this.
|
|
88
|
-
const ret = this.processor(neuronActivationTask);
|
|
161
|
+
const ret = this.executeActivationTask(task);
|
|
89
162
|
if (ret && typeof ret.then === "function") {
|
|
163
|
+
(this.activeTasks ?? (this.activeTasks = /* @__PURE__ */ new Set())).add(task);
|
|
90
164
|
ret.then(
|
|
91
165
|
(cb) => {
|
|
92
166
|
this.activeOperations--;
|
|
93
|
-
this.activeTasks.delete(
|
|
167
|
+
this.activeTasks.delete(task);
|
|
94
168
|
if (typeof cb === "function") cb();
|
|
95
|
-
if (this.
|
|
169
|
+
if (this.qSize > 0 && this.canStartOperation) {
|
|
96
170
|
if (this.pumping) this.needsPump = true;
|
|
97
171
|
else this.pump();
|
|
98
172
|
}
|
|
99
173
|
},
|
|
100
174
|
(err) => {
|
|
101
175
|
this.activeOperations--;
|
|
102
|
-
this.activeTasks.delete(
|
|
103
|
-
if (this.
|
|
176
|
+
this.activeTasks.delete(task);
|
|
177
|
+
if (this.qSize > 0 && this.canStartOperation) {
|
|
104
178
|
if (this.pumping) this.needsPump = true;
|
|
105
179
|
else this.pump();
|
|
106
180
|
}
|
|
@@ -110,7 +184,6 @@ var CNSNeuronActivationPump = class {
|
|
|
110
184
|
continue;
|
|
111
185
|
}
|
|
112
186
|
this.activeOperations--;
|
|
113
|
-
this.activeTasks.delete(neuronActivationTask);
|
|
114
187
|
if (typeof ret === "function") ret();
|
|
115
188
|
}
|
|
116
189
|
this.pumping = false;
|
|
@@ -119,73 +192,20 @@ var CNSNeuronActivationPump = class {
|
|
|
119
192
|
this.pump();
|
|
120
193
|
}
|
|
121
194
|
}
|
|
122
|
-
enqueue(neuronActivationTask) {
|
|
123
|
-
this.enqueueItem(neuronActivationTask);
|
|
124
|
-
if (!this.pumping) this.pump();
|
|
125
|
-
else this.needsPump = true;
|
|
126
|
-
}
|
|
127
|
-
get length() {
|
|
128
|
-
return this.size;
|
|
129
|
-
}
|
|
130
|
-
getActiveOperationsCount() {
|
|
131
|
-
return this.activeOperations;
|
|
132
|
-
}
|
|
133
|
-
getQueuedTasks() {
|
|
134
|
-
const result = [];
|
|
135
|
-
let index = this.head;
|
|
136
|
-
for (let i = 0; i < this.size; i++) {
|
|
137
|
-
result.push(this.items[index]);
|
|
138
|
-
index = (index + 1) % this.capacity;
|
|
139
|
-
}
|
|
140
|
-
return result;
|
|
141
|
-
}
|
|
142
|
-
getActiveTasks() {
|
|
143
|
-
return Array.from(this.activeTasks);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// src/CNSStimulation.ts
|
|
148
|
-
var CNSStimulation = class {
|
|
149
|
-
constructor(cns, instanceNeuronQueue, options) {
|
|
150
|
-
this.cns = cns;
|
|
151
|
-
this.options = options;
|
|
152
|
-
this.scheduledCount = 0;
|
|
153
|
-
this.pendingTasks = /* @__PURE__ */ new Set();
|
|
154
|
-
this.failedTasks = [];
|
|
155
|
-
this.completed = new Promise((resolve, reject) => {
|
|
156
|
-
this.resolveCompleted = resolve;
|
|
157
|
-
this.rejectCompleted = reject;
|
|
158
|
-
});
|
|
159
|
-
this.isCompleted = false;
|
|
160
|
-
/**
|
|
161
|
-
* Track active SCCs: SCC index -> count of active neurons in that SCC
|
|
162
|
-
*/
|
|
163
|
-
this.activeSccCounts = /* @__PURE__ */ new Map();
|
|
164
|
-
this.ctx = options?.ctx ?? new CNSStimulationContextStore();
|
|
165
|
-
this.queue = new CNSNeuronActivationPump(
|
|
166
|
-
(neuronActivationTask) => this.executeActivationTask(neuronActivationTask),
|
|
167
|
-
options?.concurrency,
|
|
168
|
-
options?.abortSignal
|
|
169
|
-
);
|
|
170
|
-
this.instanceNeuronQueue = instanceNeuronQueue;
|
|
171
|
-
if (this.options?.maxNeuronHops) {
|
|
172
|
-
this.nueronVisitMap = /* @__PURE__ */ new Map();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
195
|
tryResolveCompleted() {
|
|
176
196
|
if (this.isCompleted) return;
|
|
177
|
-
const noActive = this.
|
|
178
|
-
const noPending = this.
|
|
197
|
+
const noActive = this.activeOperations === 0;
|
|
198
|
+
const noPending = this.qSize + this.scheduledCount === 0;
|
|
179
199
|
const aborted = !!this.options?.abortSignal?.aborted;
|
|
180
200
|
if (noPending && noActive || aborted && noActive && !noPending) {
|
|
181
201
|
if (aborted) {
|
|
182
|
-
const queuedTasks = this.
|
|
202
|
+
const queuedTasks = this.qGetQueuedTasks();
|
|
183
203
|
for (const task of [...queuedTasks]) {
|
|
184
|
-
const alreadyTracked = this.failedTasks
|
|
204
|
+
const alreadyTracked = this.failedTasks?.some(
|
|
185
205
|
(ft) => ft.task === task
|
|
186
206
|
);
|
|
187
207
|
if (!alreadyTracked) {
|
|
188
|
-
this.
|
|
208
|
+
this.pushFailedTask({
|
|
189
209
|
task,
|
|
190
210
|
error: new Error(
|
|
191
211
|
"Task aborted - not started due to abort signal"
|
|
@@ -195,37 +215,47 @@ var CNSStimulation = class {
|
|
|
195
215
|
}
|
|
196
216
|
}
|
|
197
217
|
this.isCompleted = true;
|
|
198
|
-
this.
|
|
218
|
+
this.finalizeReject(new Error("Stimulation aborted"));
|
|
199
219
|
return;
|
|
200
220
|
}
|
|
201
221
|
this.isCompleted = true;
|
|
202
|
-
|
|
222
|
+
const failedCount = this.failedTasks?.length ?? 0;
|
|
223
|
+
if (failedCount > 0 || this.onResponseError) {
|
|
203
224
|
const error = this.onResponseError || new Error(
|
|
204
|
-
`Stimulation completed with ${
|
|
225
|
+
`Stimulation completed with ${failedCount} failed task(s)`
|
|
205
226
|
);
|
|
206
|
-
this.
|
|
227
|
+
this.finalizeReject(error);
|
|
207
228
|
} else {
|
|
208
|
-
this.
|
|
229
|
+
this.finalizeResolve();
|
|
209
230
|
}
|
|
210
231
|
}
|
|
211
232
|
}
|
|
212
233
|
waitUntilComplete() {
|
|
234
|
+
if (this.completed) return this.completed;
|
|
235
|
+
if (this.isCompleted) {
|
|
236
|
+
this.completed = this.completionRejected ? Promise.reject(this.completionError) : Promise.resolve();
|
|
237
|
+
return this.completed;
|
|
238
|
+
}
|
|
239
|
+
this.completed = new Promise((resolve, reject) => {
|
|
240
|
+
this.resolveCompleted = resolve;
|
|
241
|
+
this.rejectCompleted = reject;
|
|
242
|
+
});
|
|
213
243
|
return this.completed;
|
|
214
244
|
}
|
|
215
245
|
/**
|
|
216
246
|
* Returns all current activation tasks: queued, active, and pending (scheduled but not yet enqueued)
|
|
217
247
|
*/
|
|
218
248
|
getAllActivationTasks() {
|
|
219
|
-
const queuedTasks = this.
|
|
220
|
-
const activeTasks = this.
|
|
221
|
-
const pendingTasks = Array.from(this.pendingTasks);
|
|
249
|
+
const queuedTasks = this.qGetQueuedTasks();
|
|
250
|
+
const activeTasks = this.activeTasks ? Array.from(this.activeTasks) : [];
|
|
251
|
+
const pendingTasks = this.pendingTasks ? Array.from(this.pendingTasks) : [];
|
|
222
252
|
return [...queuedTasks, ...activeTasks, ...pendingTasks];
|
|
223
253
|
}
|
|
224
254
|
/**
|
|
225
255
|
* Returns all tasks that failed or were aborted
|
|
226
256
|
*/
|
|
227
257
|
getFailedTasks() {
|
|
228
|
-
return [...this.failedTasks];
|
|
258
|
+
return this.failedTasks ? [...this.failedTasks] : [];
|
|
229
259
|
}
|
|
230
260
|
/**
|
|
231
261
|
* Get the context store for this stimulation
|
|
@@ -238,7 +268,7 @@ var CNSStimulation = class {
|
|
|
238
268
|
*/
|
|
239
269
|
enqueueTasks(tasks) {
|
|
240
270
|
for (const task of tasks) {
|
|
241
|
-
this.
|
|
271
|
+
this.qEnqueue(task);
|
|
242
272
|
}
|
|
243
273
|
this.tryResolveCompleted();
|
|
244
274
|
}
|
|
@@ -266,20 +296,24 @@ var CNSStimulation = class {
|
|
|
266
296
|
* Increment the active count for the SCC containing this neuron
|
|
267
297
|
*/
|
|
268
298
|
incrementSccCount(neuron2) {
|
|
299
|
+
const counts = this.activeSccCounts;
|
|
300
|
+
if (!counts) return;
|
|
269
301
|
const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
|
|
270
302
|
if (sccIndex === void 0) return;
|
|
271
|
-
const currentCount =
|
|
272
|
-
|
|
303
|
+
const currentCount = counts.get(sccIndex) || 0;
|
|
304
|
+
counts.set(sccIndex, currentCount + 1);
|
|
273
305
|
}
|
|
274
306
|
/**
|
|
275
307
|
* Decrement the active count for the SCC containing this neuron
|
|
276
308
|
*/
|
|
277
309
|
decrementSccCount(neuron2) {
|
|
310
|
+
const counts = this.activeSccCounts;
|
|
311
|
+
if (!counts) return;
|
|
278
312
|
const sccIndex = this.cns.network.getSccIndexByNeuron(neuron2);
|
|
279
313
|
if (sccIndex === void 0) return;
|
|
280
|
-
const currentCount =
|
|
314
|
+
const currentCount = counts.get(sccIndex) || 0;
|
|
281
315
|
const nextCount = Math.max(0, currentCount - 1);
|
|
282
|
-
|
|
316
|
+
counts.set(sccIndex, nextCount);
|
|
283
317
|
if (currentCount === 0) {
|
|
284
318
|
console.warn(
|
|
285
319
|
`[CNSStimulation] Attempting to decrement SCC count below 0 for neuron`
|
|
@@ -290,7 +324,8 @@ var CNSStimulation = class {
|
|
|
290
324
|
* Check if a neuron can be guaranteed not to be visited again
|
|
291
325
|
*/
|
|
292
326
|
canNeuronBeGuaranteedDone(neuron2) {
|
|
293
|
-
if (!this.autoCleanupContextsEnabled
|
|
327
|
+
if (!this.autoCleanupContextsEnabled || !this.activeSccCounts)
|
|
328
|
+
return false;
|
|
294
329
|
return this.cns.network.canNeuronBeGuaranteedDone(
|
|
295
330
|
neuron2,
|
|
296
331
|
this.activeSccCounts
|
|
@@ -298,7 +333,7 @@ var CNSStimulation = class {
|
|
|
298
333
|
}
|
|
299
334
|
cleanupCtxIfNeeded(neuron2) {
|
|
300
335
|
if (this.autoCleanupContextsEnabled && this.canNeuronBeGuaranteedDone(neuron2)) {
|
|
301
|
-
this.
|
|
336
|
+
this.ctxStore?.delete(neuron2);
|
|
302
337
|
}
|
|
303
338
|
}
|
|
304
339
|
createSubscriberQueueItem(subscriber, inputSignal) {
|
|
@@ -325,11 +360,15 @@ var CNSStimulation = class {
|
|
|
325
360
|
const subscribers = this.cns.network.getSubscribers(
|
|
326
361
|
neuronActivationTask.dendriteCollateral
|
|
327
362
|
);
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
363
|
+
let subscriber;
|
|
364
|
+
for (let i = 0; i < subscribers.length; i++) {
|
|
365
|
+
if (subscribers[i].neuron === neuronActivationTask.neuron) {
|
|
366
|
+
subscriber = subscribers[i];
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
331
370
|
if (!subscriber) {
|
|
332
|
-
this.
|
|
371
|
+
this.pushFailedTask({
|
|
333
372
|
task: neuronActivationTask,
|
|
334
373
|
error: new Error(
|
|
335
374
|
`Subscriber not found for activation task`
|
|
@@ -342,40 +381,58 @@ var CNSStimulation = class {
|
|
|
342
381
|
const neuron2 = subscriber.neuron;
|
|
343
382
|
const dendrite = subscriber.dendrite;
|
|
344
383
|
const inputSignal = neuronActivationTask.input;
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
384
|
+
const concurrency = neuron2.concurrency;
|
|
385
|
+
if (concurrency === void 0 || concurrency <= 0) {
|
|
386
|
+
return this.runStarter(
|
|
387
|
+
neuron2,
|
|
388
|
+
dendrite,
|
|
389
|
+
inputSignal,
|
|
390
|
+
neuronActivationTask
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return this.instanceNeuronQueue.run(
|
|
394
|
+
neuron2,
|
|
395
|
+
() => this.runStarter(
|
|
396
|
+
neuron2,
|
|
397
|
+
dendrite,
|
|
398
|
+
inputSignal,
|
|
399
|
+
neuronActivationTask
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
runStarter(neuron2, dendrite, inputSignal, neuronActivationTask) {
|
|
404
|
+
this.markNeuronActive(neuron2);
|
|
405
|
+
let response;
|
|
406
|
+
try {
|
|
407
|
+
response = dendrite.response(
|
|
408
|
+
inputSignal?.payload,
|
|
409
|
+
neuron2.axon,
|
|
410
|
+
new CNSDendriteContext(
|
|
411
|
+
this,
|
|
370
412
|
neuron2,
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
413
|
+
this.options?.abortSignal,
|
|
414
|
+
this.cns
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
} catch (error) {
|
|
418
|
+
this.markNeuronInactive(neuron2);
|
|
419
|
+
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
420
|
+
this.pushFailedTask({
|
|
421
|
+
task: neuronActivationTask,
|
|
422
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
423
|
+
aborted: isAborted
|
|
424
|
+
});
|
|
425
|
+
this.processResponseOrResponses(
|
|
426
|
+
neuron2,
|
|
427
|
+
inputSignal,
|
|
428
|
+
void 0,
|
|
429
|
+
error
|
|
430
|
+
);
|
|
431
|
+
return () => {
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
const maxDuration = neuron2.maxDuration;
|
|
435
|
+
if (response instanceof Promise || maxDuration) {
|
|
379
436
|
const asPromise = response instanceof Promise ? response : Promise.resolve(response);
|
|
380
437
|
const timedPromise = maxDuration && maxDuration > 0 ? new Promise((resolve, reject) => {
|
|
381
438
|
const t = setTimeout(() => {
|
|
@@ -395,48 +452,45 @@ var CNSStimulation = class {
|
|
|
395
452
|
}
|
|
396
453
|
);
|
|
397
454
|
}) : asPromise;
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
(
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
(
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
455
|
+
return timedPromise.then(
|
|
456
|
+
(signal) => {
|
|
457
|
+
return () => {
|
|
458
|
+
this.markNeuronInactive(neuron2);
|
|
459
|
+
return this.processResponseOrResponses(
|
|
460
|
+
neuron2,
|
|
461
|
+
inputSignal,
|
|
462
|
+
signal
|
|
463
|
+
);
|
|
464
|
+
};
|
|
465
|
+
},
|
|
466
|
+
(error) => {
|
|
467
|
+
return () => {
|
|
468
|
+
this.markNeuronInactive(neuron2);
|
|
469
|
+
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
470
|
+
this.pushFailedTask({
|
|
471
|
+
task: neuronActivationTask,
|
|
472
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
473
|
+
aborted: isAborted
|
|
474
|
+
});
|
|
475
|
+
return this.processResponseOrResponses(
|
|
476
|
+
neuron2,
|
|
477
|
+
inputSignal,
|
|
478
|
+
void 0,
|
|
479
|
+
error
|
|
480
|
+
);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
} else {
|
|
485
|
+
return () => {
|
|
486
|
+
this.markNeuronInactive(neuron2);
|
|
487
|
+
return this.processResponseOrResponses(
|
|
488
|
+
neuron2,
|
|
489
|
+
inputSignal,
|
|
490
|
+
response
|
|
427
491
|
);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
this.markNeuronInactive(neuron2);
|
|
431
|
-
return this.processResponseOrResponses(
|
|
432
|
-
neuron2,
|
|
433
|
-
inputSignal,
|
|
434
|
-
response
|
|
435
|
-
);
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
return this.instanceNeuronQueue.run(neuron2, starter);
|
|
492
|
+
};
|
|
493
|
+
}
|
|
440
494
|
}
|
|
441
495
|
processResponseOrResponses(emitter, inputSignal, outputSignalOrSignals, error) {
|
|
442
496
|
if (Array.isArray(outputSignalOrSignals)) {
|
|
@@ -454,36 +508,62 @@ var CNSStimulation = class {
|
|
|
454
508
|
processResponse(emitter, inputSignal, outputSignal, error) {
|
|
455
509
|
const collateral2 = outputSignal?.collateral;
|
|
456
510
|
const subscribers = collateral2 ? this.cns.network.getSubscribers(collateral2) : [];
|
|
511
|
+
const onResponse = this.onResponse;
|
|
512
|
+
if (!onResponse) {
|
|
513
|
+
if (collateral2 && !error) {
|
|
514
|
+
if (emitter) this.cleanupCtxIfNeeded(emitter);
|
|
515
|
+
const n = subscribers.length;
|
|
516
|
+
if (n > 0) {
|
|
517
|
+
const tasks = new Array(n);
|
|
518
|
+
for (let i = 0; i < n; i++) {
|
|
519
|
+
tasks[i] = this.createSubscriberQueueItem(
|
|
520
|
+
subscribers[i],
|
|
521
|
+
outputSignal
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
this.scheduledCount += n;
|
|
525
|
+
for (let i = 0; i < n; i++) {
|
|
526
|
+
this.scheduledCount--;
|
|
527
|
+
this.qEnqueue(tasks[i]);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
this.tryResolveCompleted();
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
457
534
|
const subscriberActivationTasks = [];
|
|
458
535
|
if (collateral2 && !error) {
|
|
459
536
|
if (emitter) this.cleanupCtxIfNeeded(emitter);
|
|
537
|
+
const pending = this.pendingTasks ?? (this.pendingTasks = /* @__PURE__ */ new Set());
|
|
460
538
|
for (let i = 0; i < subscribers.length; i++) {
|
|
461
539
|
const task = this.createSubscriberQueueItem(
|
|
462
540
|
subscribers[i],
|
|
463
541
|
outputSignal
|
|
464
542
|
);
|
|
465
543
|
subscriberActivationTasks.push(task);
|
|
466
|
-
|
|
544
|
+
pending.add(task);
|
|
467
545
|
}
|
|
468
546
|
}
|
|
469
547
|
this.scheduledCount += subscriberActivationTasks.length;
|
|
470
548
|
let maybePromise;
|
|
471
549
|
try {
|
|
472
|
-
maybePromise =
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
550
|
+
maybePromise = onResponse(
|
|
551
|
+
new CNSStimulationResponseImpl(
|
|
552
|
+
this,
|
|
553
|
+
this.ctxStore,
|
|
554
|
+
inputSignal,
|
|
555
|
+
outputSignal,
|
|
556
|
+
this.qSize + this.scheduledCount,
|
|
557
|
+
this.options?.maxNeuronHops && emitter ? this.nueronVisitMap?.get(emitter) ?? 0 : void 0,
|
|
558
|
+
error
|
|
559
|
+
)
|
|
560
|
+
);
|
|
481
561
|
} catch (e) {
|
|
482
562
|
this.onResponseError = e instanceof Error ? e : new Error(String(e));
|
|
483
563
|
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
484
564
|
this.scheduledCount--;
|
|
485
|
-
this.pendingTasks
|
|
486
|
-
this.
|
|
565
|
+
this.pendingTasks?.delete(subscriberActivationTasks[i]);
|
|
566
|
+
this.qEnqueue(subscriberActivationTasks[i]);
|
|
487
567
|
}
|
|
488
568
|
this.tryResolveCompleted();
|
|
489
569
|
return;
|
|
@@ -493,8 +573,8 @@ var CNSStimulation = class {
|
|
|
493
573
|
() => {
|
|
494
574
|
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
495
575
|
this.scheduledCount--;
|
|
496
|
-
this.pendingTasks
|
|
497
|
-
this.
|
|
576
|
+
this.pendingTasks?.delete(subscriberActivationTasks[i]);
|
|
577
|
+
this.qEnqueue(subscriberActivationTasks[i]);
|
|
498
578
|
}
|
|
499
579
|
this.tryResolveCompleted();
|
|
500
580
|
},
|
|
@@ -502,8 +582,8 @@ var CNSStimulation = class {
|
|
|
502
582
|
this.onResponseError = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
503
583
|
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
504
584
|
this.scheduledCount--;
|
|
505
|
-
this.pendingTasks
|
|
506
|
-
this.
|
|
585
|
+
this.pendingTasks?.delete(subscriberActivationTasks[i]);
|
|
586
|
+
this.qEnqueue(subscriberActivationTasks[i]);
|
|
507
587
|
}
|
|
508
588
|
this.tryResolveCompleted();
|
|
509
589
|
}
|
|
@@ -512,8 +592,8 @@ var CNSStimulation = class {
|
|
|
512
592
|
}
|
|
513
593
|
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
514
594
|
this.scheduledCount--;
|
|
515
|
-
this.pendingTasks
|
|
516
|
-
this.
|
|
595
|
+
this.pendingTasks?.delete(subscriberActivationTasks[i]);
|
|
596
|
+
this.qEnqueue(subscriberActivationTasks[i]);
|
|
517
597
|
}
|
|
518
598
|
this.tryResolveCompleted();
|
|
519
599
|
}
|
|
@@ -877,8 +957,7 @@ var CNS = class {
|
|
|
877
957
|
}
|
|
878
958
|
wrapOnResponse(local) {
|
|
879
959
|
if (this.globalResponseListeners.length === 0 && !local) {
|
|
880
|
-
return
|
|
881
|
-
};
|
|
960
|
+
return void 0;
|
|
882
961
|
}
|
|
883
962
|
return (r) => {
|
|
884
963
|
let anyPromise = false;
|
|
@@ -922,10 +1001,8 @@ var CNS = class {
|
|
|
922
1001
|
const stimulation = new CNSStimulation(
|
|
923
1002
|
this,
|
|
924
1003
|
this.instanceNeuronQueue,
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
onResponse: wrapped
|
|
928
|
-
}
|
|
1004
|
+
options,
|
|
1005
|
+
wrapped
|
|
929
1006
|
);
|
|
930
1007
|
stimulation.responseToSignal(signalOrSignals);
|
|
931
1008
|
return stimulation;
|
|
@@ -938,10 +1015,8 @@ var CNS = class {
|
|
|
938
1015
|
const stimulation = new CNSStimulation(
|
|
939
1016
|
this,
|
|
940
1017
|
this.instanceNeuronQueue,
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
onResponse: wrapped
|
|
944
|
-
}
|
|
1018
|
+
options,
|
|
1019
|
+
wrapped
|
|
945
1020
|
);
|
|
946
1021
|
stimulation.enqueueTasks(tasks);
|
|
947
1022
|
return stimulation;
|
|
@@ -998,6 +1073,20 @@ var CNSPersistOptionsRegistry = class {
|
|
|
998
1073
|
removeStimulation(stimulationId) {
|
|
999
1074
|
this.stimulations.delete(stimulationId);
|
|
1000
1075
|
}
|
|
1076
|
+
register(name, neuron2, collateralNames) {
|
|
1077
|
+
this.addNeuron(neuron2, { name, neuron: neuron2 });
|
|
1078
|
+
for (const [key, col] of Object.entries(neuron2.axon)) {
|
|
1079
|
+
this.addCollateral(col, {
|
|
1080
|
+
name: collateralNames?.[key] ?? key,
|
|
1081
|
+
collateral: col
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
return this;
|
|
1085
|
+
}
|
|
1086
|
+
registerCollateral(name, collateral2) {
|
|
1087
|
+
this.addCollateral(collateral2, { name, collateral: collateral2 });
|
|
1088
|
+
return this;
|
|
1089
|
+
}
|
|
1001
1090
|
};
|
|
1002
1091
|
|
|
1003
1092
|
// src/CNSCollateral.ts
|
|
@@ -1200,11 +1289,14 @@ var modality = (afferentPaths) => {
|
|
|
1200
1289
|
};
|
|
1201
1290
|
var createPersistRegistry = (namedNeurons) => {
|
|
1202
1291
|
const registry = new CNSPersistOptionsRegistry();
|
|
1203
|
-
for (const [name,
|
|
1292
|
+
for (const [name, entry] of Object.entries(namedNeurons)) {
|
|
1293
|
+
const isEntry = "neuron" in entry && !("axon" in entry);
|
|
1294
|
+
const neuron2 = isEntry ? entry.neuron : entry;
|
|
1295
|
+
const colNames = isEntry ? entry.collaterals ?? {} : {};
|
|
1204
1296
|
registry.addNeuron(neuron2, { name, neuron: neuron2 });
|
|
1205
1297
|
for (const [key, col] of Object.entries(neuron2.axon)) {
|
|
1206
1298
|
registry.addCollateral(col, {
|
|
1207
|
-
name: key,
|
|
1299
|
+
name: colNames[key] ?? key,
|
|
1208
1300
|
collateral: col
|
|
1209
1301
|
});
|
|
1210
1302
|
}
|