@cnstra/core 1.6.0 → 1.8.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/README.md +47 -24
- package/dist/CNS.d.ts +12 -83
- package/dist/CNS.d.ts.map +1 -1
- package/dist/CNSNetwork.d.ts +87 -0
- package/dist/CNSNetwork.d.ts.map +1 -0
- package/dist/CNSNeuronActivationPump.d.ts +27 -0
- package/dist/CNSNeuronActivationPump.d.ts.map +1 -0
- package/dist/CNSStimulation.d.ts +27 -6
- package/dist/CNSStimulation.d.ts.map +1 -1
- package/dist/index.cjs +324 -304
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +324 -304
- package/dist/index.js.map +1 -1
- package/dist/interfaces/ICNS.d.ts +12 -24
- package/dist/interfaces/ICNS.d.ts.map +1 -1
- package/dist/interfaces/ICNSStimulationContextStore.d.ts +3 -2
- package/dist/interfaces/ICNSStimulationContextStore.d.ts.map +1 -1
- package/dist/types/TCNSDendrite.d.ts +2 -2
- package/dist/types/TCNSDendrite.d.ts.map +1 -1
- package/dist/types/TCNSNeuronActivationTask.d.ts +8 -0
- package/dist/types/TCNSNeuronActivationTask.d.ts.map +1 -0
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts +7 -0
- package/dist/types/TCNSNeuronActivationTaskFailure.d.ts.map +1 -0
- package/dist/types/TCNSSignal.d.ts.map +1 -1
- package/dist/types/TCNSStimulationOptions.d.ts +6 -5
- package/dist/types/TCNSStimulationOptions.d.ts.map +1 -1
- package/dist/types/TCNSStimulationResponse.d.ts +11 -4
- package/dist/types/TCNSStimulationResponse.d.ts.map +1 -1
- package/dist/types/TCNSStimulationSerializedContextValue.d.ts +4 -0
- package/dist/types/TCNSStimulationSerializedContextValue.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/CNSFunctionalQueue.d.ts +0 -26
- package/dist/CNSFunctionalQueue.d.ts.map +0 -1
- package/dist/types/TCNSSerializedSignal.d.ts +0 -10
- package/dist/types/TCNSSerializedSignal.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -24,8 +24,8 @@ var CNSStimulationContextStore = class {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
// src/
|
|
28
|
-
var
|
|
27
|
+
// src/CNSNeuronActivationPump.ts
|
|
28
|
+
var CNSNeuronActivationPump = class {
|
|
29
29
|
constructor(processor, concurrency, abortSignal, initialCapacity) {
|
|
30
30
|
this.processor = processor;
|
|
31
31
|
this.concurrency = concurrency;
|
|
@@ -36,6 +36,7 @@ var CNSFunctionalQueue = class {
|
|
|
36
36
|
this.size = 0;
|
|
37
37
|
this.capacity = 16;
|
|
38
38
|
this.activeOperations = 0;
|
|
39
|
+
this.activeTasks = /* @__PURE__ */ new Set();
|
|
39
40
|
// NEW: prevent re-entrant pump; defer extra runs
|
|
40
41
|
this.pumping = false;
|
|
41
42
|
this.needsPump = false;
|
|
@@ -63,17 +64,17 @@ var CNSFunctionalQueue = class {
|
|
|
63
64
|
}
|
|
64
65
|
dequeue() {
|
|
65
66
|
if (this.size === 0) return void 0;
|
|
66
|
-
const
|
|
67
|
+
const neuronActivationTask = this.items[this.head];
|
|
67
68
|
this.items[this.head] = void 0;
|
|
68
69
|
this.head = (this.head + 1) % this.capacity;
|
|
69
70
|
this.size--;
|
|
70
|
-
return
|
|
71
|
+
return neuronActivationTask;
|
|
71
72
|
}
|
|
72
|
-
enqueueItem(
|
|
73
|
+
enqueueItem(neuronActivationTask) {
|
|
73
74
|
if (this.size === this.capacity) {
|
|
74
75
|
this.resize();
|
|
75
76
|
}
|
|
76
|
-
this.items[this.tail] =
|
|
77
|
+
this.items[this.tail] = neuronActivationTask;
|
|
77
78
|
this.tail = (this.tail + 1) % this.capacity;
|
|
78
79
|
this.size++;
|
|
79
80
|
}
|
|
@@ -84,13 +85,15 @@ var CNSFunctionalQueue = class {
|
|
|
84
85
|
}
|
|
85
86
|
this.pumping = true;
|
|
86
87
|
while (this.canStartOperation && this.size > 0) {
|
|
87
|
-
const
|
|
88
|
+
const neuronActivationTask = this.dequeue();
|
|
88
89
|
this.activeOperations++;
|
|
89
|
-
|
|
90
|
+
this.activeTasks.add(neuronActivationTask);
|
|
91
|
+
const ret = this.processor(neuronActivationTask);
|
|
90
92
|
if (ret && typeof ret.then === "function") {
|
|
91
93
|
ret.then(
|
|
92
94
|
(cb) => {
|
|
93
95
|
this.activeOperations--;
|
|
96
|
+
this.activeTasks.delete(neuronActivationTask);
|
|
94
97
|
if (typeof cb === "function") cb();
|
|
95
98
|
if (this.size > 0 && this.canStartOperation) {
|
|
96
99
|
if (this.pumping) this.needsPump = true;
|
|
@@ -99,6 +102,7 @@ var CNSFunctionalQueue = class {
|
|
|
99
102
|
},
|
|
100
103
|
(err) => {
|
|
101
104
|
this.activeOperations--;
|
|
105
|
+
this.activeTasks.delete(neuronActivationTask);
|
|
102
106
|
if (this.size > 0 && this.canStartOperation) {
|
|
103
107
|
if (this.pumping) this.needsPump = true;
|
|
104
108
|
else this.pump();
|
|
@@ -109,6 +113,7 @@ var CNSFunctionalQueue = class {
|
|
|
109
113
|
continue;
|
|
110
114
|
}
|
|
111
115
|
this.activeOperations--;
|
|
116
|
+
this.activeTasks.delete(neuronActivationTask);
|
|
112
117
|
if (typeof ret === "function") ret();
|
|
113
118
|
}
|
|
114
119
|
this.pumping = false;
|
|
@@ -117,8 +122,8 @@ var CNSFunctionalQueue = class {
|
|
|
117
122
|
this.pump();
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
|
-
enqueue(
|
|
121
|
-
this.enqueueItem(
|
|
125
|
+
enqueue(neuronActivationTask) {
|
|
126
|
+
this.enqueueItem(neuronActivationTask);
|
|
122
127
|
if (!this.pumping) this.pump();
|
|
123
128
|
else this.needsPump = true;
|
|
124
129
|
}
|
|
@@ -128,6 +133,18 @@ var CNSFunctionalQueue = class {
|
|
|
128
133
|
getActiveOperationsCount() {
|
|
129
134
|
return this.activeOperations;
|
|
130
135
|
}
|
|
136
|
+
getQueuedTasks() {
|
|
137
|
+
const result = [];
|
|
138
|
+
let index = this.head;
|
|
139
|
+
for (let i = 0; i < this.size; i++) {
|
|
140
|
+
result.push(this.items[index]);
|
|
141
|
+
index = (index + 1) % this.capacity;
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
getActiveTasks() {
|
|
146
|
+
return Array.from(this.activeTasks);
|
|
147
|
+
}
|
|
131
148
|
};
|
|
132
149
|
|
|
133
150
|
// src/CNSStimulation.ts
|
|
@@ -136,6 +153,8 @@ var CNSStimulation = class {
|
|
|
136
153
|
this.cns = cns;
|
|
137
154
|
this.options = options;
|
|
138
155
|
this.scheduledCount = 0;
|
|
156
|
+
this.pendingTasks = /* @__PURE__ */ new Set();
|
|
157
|
+
this.failedTasks = [];
|
|
139
158
|
this.completed = new Promise((resolve, reject) => {
|
|
140
159
|
this.resolveCompleted = resolve;
|
|
141
160
|
this.rejectCompleted = reject;
|
|
@@ -145,10 +164,12 @@ var CNSStimulation = class {
|
|
|
145
164
|
* Track active SCCs: SCC index -> count of active neurons in that SCC
|
|
146
165
|
*/
|
|
147
166
|
this.activeSccCounts = /* @__PURE__ */ new Map();
|
|
148
|
-
this.ctx =
|
|
167
|
+
this.ctx = new CNSStimulationContextStore(
|
|
168
|
+
new Map(Object.entries(options?.contextValues ?? {}))
|
|
169
|
+
);
|
|
149
170
|
this.id = options?.stimulationId || Math.random().toString(36).slice(2);
|
|
150
|
-
this.queue = new
|
|
151
|
-
(
|
|
171
|
+
this.queue = new CNSNeuronActivationPump(
|
|
172
|
+
(neuronActivationTask) => this.executeActivationTask(neuronActivationTask),
|
|
152
173
|
options?.concurrency,
|
|
153
174
|
options?.abortSignal
|
|
154
175
|
);
|
|
@@ -156,25 +177,81 @@ var CNSStimulation = class {
|
|
|
156
177
|
if (this.options?.maxNeuronHops) {
|
|
157
178
|
this.nueronVisitMap = /* @__PURE__ */ new Map();
|
|
158
179
|
}
|
|
159
|
-
if (this.options?.abortSignal) {
|
|
160
|
-
this.options.abortSignal.addEventListener("abort", () => {
|
|
161
|
-
this.tryResolveCompleted();
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
180
|
}
|
|
165
181
|
tryResolveCompleted() {
|
|
166
182
|
if (this.isCompleted) return;
|
|
167
183
|
const noActive = this.queue.getActiveOperationsCount() === 0;
|
|
168
184
|
const noPending = this.queue.length + this.scheduledCount === 0;
|
|
169
185
|
const aborted = !!this.options?.abortSignal?.aborted;
|
|
170
|
-
if (noPending && noActive || aborted && noActive) {
|
|
186
|
+
if (noPending && noActive || aborted && noActive && !noPending) {
|
|
187
|
+
if (aborted) {
|
|
188
|
+
const queuedTasks = this.queue.getQueuedTasks();
|
|
189
|
+
for (const task of [...queuedTasks]) {
|
|
190
|
+
const alreadyTracked = this.failedTasks.some(
|
|
191
|
+
(ft) => ft.task.neuronId === task.neuronId && ft.task.dendriteCollateralName === task.dendriteCollateralName && ft.task.stimulationId === task.stimulationId
|
|
192
|
+
);
|
|
193
|
+
if (!alreadyTracked) {
|
|
194
|
+
this.failedTasks.push({
|
|
195
|
+
task,
|
|
196
|
+
error: new Error(
|
|
197
|
+
"Task aborted - not started due to abort signal"
|
|
198
|
+
),
|
|
199
|
+
aborted: true
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
this.isCompleted = true;
|
|
204
|
+
this.rejectCompleted(new Error("Stimulation aborted"));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
171
207
|
this.isCompleted = true;
|
|
172
|
-
this.
|
|
208
|
+
if (this.failedTasks.length > 0 || this.onResponseError) {
|
|
209
|
+
const error = this.onResponseError || new Error(
|
|
210
|
+
`Stimulation completed with ${this.failedTasks.length} failed task(s)`
|
|
211
|
+
);
|
|
212
|
+
this.rejectCompleted(error);
|
|
213
|
+
} else {
|
|
214
|
+
this.resolveCompleted();
|
|
215
|
+
}
|
|
173
216
|
}
|
|
174
217
|
}
|
|
175
218
|
waitUntilComplete() {
|
|
176
219
|
return this.completed;
|
|
177
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Returns all current activation tasks: queued, active, and pending (scheduled but not yet enqueued)
|
|
223
|
+
*/
|
|
224
|
+
getAllActivationTasks() {
|
|
225
|
+
const queuedTasks = this.queue.getQueuedTasks();
|
|
226
|
+
const activeTasks = this.queue.getActiveTasks();
|
|
227
|
+
const pendingTasks = Array.from(this.pendingTasks);
|
|
228
|
+
return [...queuedTasks, ...activeTasks, ...pendingTasks];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Returns all tasks that failed or were aborted
|
|
232
|
+
*/
|
|
233
|
+
getFailedTasks() {
|
|
234
|
+
return [...this.failedTasks];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the context store for this stimulation
|
|
238
|
+
*/
|
|
239
|
+
getContext() {
|
|
240
|
+
return this.ctx;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Enqueue activation tasks directly into the stimulation queue
|
|
244
|
+
*/
|
|
245
|
+
enqueueTasks(tasks) {
|
|
246
|
+
for (const task of tasks) {
|
|
247
|
+
const taskWithId = {
|
|
248
|
+
...task,
|
|
249
|
+
stimulationId: this.id
|
|
250
|
+
};
|
|
251
|
+
this.queue.enqueue(taskWithId);
|
|
252
|
+
}
|
|
253
|
+
this.tryResolveCompleted();
|
|
254
|
+
}
|
|
178
255
|
get concurrencyEnabled() {
|
|
179
256
|
return this.options?.concurrency !== void 0 && this.options?.concurrency > 0;
|
|
180
257
|
}
|
|
@@ -199,7 +276,7 @@ var CNSStimulation = class {
|
|
|
199
276
|
* Increment the active count for the SCC containing this neuron
|
|
200
277
|
*/
|
|
201
278
|
incrementSccCount(neuronId) {
|
|
202
|
-
const sccIndex = this.cns.getSccIndexByNeuronName(neuronId);
|
|
279
|
+
const sccIndex = this.cns.network.getSccIndexByNeuronName(neuronId);
|
|
203
280
|
if (sccIndex === void 0) return;
|
|
204
281
|
const currentCount = this.activeSccCounts.get(sccIndex) || 0;
|
|
205
282
|
this.activeSccCounts.set(sccIndex, currentCount + 1);
|
|
@@ -208,7 +285,7 @@ var CNSStimulation = class {
|
|
|
208
285
|
* Decrement the active count for the SCC containing this neuron
|
|
209
286
|
*/
|
|
210
287
|
decrementSccCount(neuronId) {
|
|
211
|
-
const sccIndex = this.cns.getSccIndexByNeuronName(neuronId);
|
|
288
|
+
const sccIndex = this.cns.network.getSccIndexByNeuronName(neuronId);
|
|
212
289
|
if (sccIndex === void 0) return;
|
|
213
290
|
const currentCount = this.activeSccCounts.get(sccIndex) || 0;
|
|
214
291
|
const nextCount = Math.max(0, currentCount - 1);
|
|
@@ -224,7 +301,7 @@ var CNSStimulation = class {
|
|
|
224
301
|
*/
|
|
225
302
|
canNeuronBeGuaranteedDone(neuronId) {
|
|
226
303
|
if (!this.autoCleanupContextsEnabled) return false;
|
|
227
|
-
return this.cns.canNeuronBeGuaranteedDone(
|
|
304
|
+
return this.cns.network.canNeuronBeGuaranteedDone(
|
|
228
305
|
neuronId,
|
|
229
306
|
this.activeSccCounts
|
|
230
307
|
);
|
|
@@ -247,45 +324,70 @@ var CNSStimulation = class {
|
|
|
247
324
|
);
|
|
248
325
|
}
|
|
249
326
|
}
|
|
250
|
-
const
|
|
327
|
+
const neuronActivationTask = {
|
|
328
|
+
stimulationId: this.id,
|
|
251
329
|
neuronId: subscriber.neuron.name,
|
|
252
330
|
dendriteCollateralName: subscriber.dendrite.collateral.name,
|
|
253
|
-
input: inputSignal
|
|
254
|
-
collateralName: inputSignal.collateralName,
|
|
255
|
-
payload: inputSignal.payload
|
|
256
|
-
} : void 0
|
|
331
|
+
input: inputSignal
|
|
257
332
|
};
|
|
258
|
-
return
|
|
333
|
+
return neuronActivationTask;
|
|
259
334
|
}
|
|
260
|
-
|
|
261
|
-
const subscribers = this.cns.getSubscribers(
|
|
262
|
-
|
|
335
|
+
executeActivationTask(neuronActivationTask) {
|
|
336
|
+
const subscribers = this.cns.network.getSubscribers(
|
|
337
|
+
neuronActivationTask.dendriteCollateralName
|
|
263
338
|
);
|
|
264
339
|
const subscriber = subscribers.find(
|
|
265
|
-
(s) => s.neuron.name ===
|
|
340
|
+
(s) => s.neuron.name === neuronActivationTask.neuronId
|
|
266
341
|
);
|
|
267
|
-
if (!subscriber)
|
|
268
|
-
|
|
342
|
+
if (!subscriber) {
|
|
343
|
+
this.failedTasks.push({
|
|
344
|
+
task: neuronActivationTask,
|
|
345
|
+
error: new Error(
|
|
346
|
+
`Subscriber not found for neuron "${neuronActivationTask.neuronId}" and collateral "${neuronActivationTask.dendriteCollateralName}"`
|
|
347
|
+
),
|
|
348
|
+
aborted: false
|
|
349
|
+
});
|
|
350
|
+
return () => {
|
|
351
|
+
};
|
|
352
|
+
}
|
|
269
353
|
const neuron2 = subscriber.neuron;
|
|
270
354
|
const dendrite = subscriber.dendrite;
|
|
271
|
-
const inputSignal =
|
|
272
|
-
collateralName:
|
|
273
|
-
payload:
|
|
355
|
+
const inputSignal = neuronActivationTask.input ? {
|
|
356
|
+
collateralName: neuronActivationTask.input.collateralName,
|
|
357
|
+
payload: neuronActivationTask.input.payload
|
|
274
358
|
} : void 0;
|
|
275
359
|
const starter = () => {
|
|
276
360
|
this.markNeuronActive(neuron2.name);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
361
|
+
let response;
|
|
362
|
+
try {
|
|
363
|
+
response = dendrite.response(
|
|
364
|
+
inputSignal?.payload,
|
|
365
|
+
neuron2.axon,
|
|
366
|
+
{
|
|
367
|
+
get: () => this.ctx.get(neuron2.name),
|
|
368
|
+
set: (value) => this.ctx.set(neuron2.name, value),
|
|
369
|
+
delete: () => this.ctx.delete(neuron2.name),
|
|
370
|
+
abortSignal: this.options?.abortSignal,
|
|
371
|
+
cns: this.cns,
|
|
372
|
+
stimulationId: this.id
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
this.markNeuronInactive(neuron2.name);
|
|
377
|
+
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
378
|
+
this.failedTasks.push({
|
|
379
|
+
task: neuronActivationTask,
|
|
380
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
381
|
+
aborted: isAborted
|
|
382
|
+
});
|
|
383
|
+
this.processResponseOrResponses(
|
|
384
|
+
inputSignal,
|
|
385
|
+
void 0,
|
|
386
|
+
error
|
|
387
|
+
);
|
|
388
|
+
return () => {
|
|
389
|
+
};
|
|
390
|
+
}
|
|
289
391
|
const maxDuration = neuron2.maxDuration;
|
|
290
392
|
const asPromise = response instanceof Promise ? response : Promise.resolve(response);
|
|
291
393
|
const timedPromise = maxDuration && maxDuration > 0 ? new Promise((resolve, reject) => {
|
|
@@ -322,6 +424,12 @@ var CNSStimulation = class {
|
|
|
322
424
|
(error) => {
|
|
323
425
|
return () => {
|
|
324
426
|
this.markNeuronInactive(neuron2.name);
|
|
427
|
+
const isAborted = this.options?.abortSignal?.aborted ?? false;
|
|
428
|
+
this.failedTasks.push({
|
|
429
|
+
task: neuronActivationTask,
|
|
430
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
431
|
+
aborted: isAborted
|
|
432
|
+
});
|
|
325
433
|
return this.processResponseOrResponses(
|
|
326
434
|
inputSignal,
|
|
327
435
|
void 0,
|
|
@@ -357,60 +465,78 @@ var CNSStimulation = class {
|
|
|
357
465
|
}
|
|
358
466
|
processResponse(inputSignal, outputSignal, error) {
|
|
359
467
|
const collateralName = outputSignal?.collateralName;
|
|
360
|
-
const ownerNeuron = collateralName ? this.cns.getParentNeuronByCollateralName(collateralName) : void 0;
|
|
361
|
-
const subscribers = collateralName ? this.cns.getSubscribers(collateralName) : [];
|
|
362
|
-
const
|
|
468
|
+
const ownerNeuron = collateralName ? this.cns.network.getParentNeuronByCollateralName(collateralName) : void 0;
|
|
469
|
+
const subscribers = collateralName ? this.cns.network.getSubscribers(collateralName) : [];
|
|
470
|
+
const subscriberActivationTasks = [];
|
|
363
471
|
if (collateralName && !error) {
|
|
364
472
|
if (ownerNeuron) {
|
|
365
473
|
this.cleanupCtxIfNeeded(ownerNeuron);
|
|
366
474
|
}
|
|
367
475
|
for (let i = 0; i < subscribers.length; i++) {
|
|
368
|
-
|
|
369
|
-
|
|
476
|
+
const task = this.createSubscriberQueueItem(
|
|
477
|
+
subscribers[i],
|
|
478
|
+
outputSignal
|
|
370
479
|
);
|
|
480
|
+
subscriberActivationTasks.push(task);
|
|
481
|
+
this.pendingTasks.add(task);
|
|
371
482
|
}
|
|
372
483
|
}
|
|
373
|
-
this.scheduledCount +=
|
|
484
|
+
this.scheduledCount += subscriberActivationTasks.length;
|
|
374
485
|
let maybePromise;
|
|
375
486
|
try {
|
|
376
487
|
maybePromise = this.options?.onResponse?.({
|
|
377
488
|
inputSignal,
|
|
378
489
|
outputSignal,
|
|
379
|
-
|
|
490
|
+
contextValue: this.ctx.getAll(),
|
|
380
491
|
queueLength: this.queue.length + this.scheduledCount,
|
|
492
|
+
stimulation: this,
|
|
381
493
|
stimulationId: this.id,
|
|
382
494
|
hops: this.options?.maxNeuronHops && ownerNeuron ? this.nueronVisitMap?.get(ownerNeuron.name) ?? 0 : void 0,
|
|
383
495
|
error
|
|
384
496
|
});
|
|
385
497
|
} catch (e) {
|
|
386
|
-
this.
|
|
498
|
+
this.onResponseError = e instanceof Error ? e : new Error(String(e));
|
|
499
|
+
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
500
|
+
this.scheduledCount--;
|
|
501
|
+
this.pendingTasks.delete(subscriberActivationTasks[i]);
|
|
502
|
+
this.queue.enqueue(subscriberActivationTasks[i]);
|
|
503
|
+
}
|
|
504
|
+
this.tryResolveCompleted();
|
|
387
505
|
return;
|
|
388
506
|
}
|
|
389
507
|
if (maybePromise && typeof maybePromise.then === "function") {
|
|
390
508
|
maybePromise.then(
|
|
391
509
|
() => {
|
|
392
|
-
for (let i = 0; i <
|
|
510
|
+
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
393
511
|
this.scheduledCount--;
|
|
394
|
-
this.
|
|
512
|
+
this.pendingTasks.delete(subscriberActivationTasks[i]);
|
|
513
|
+
this.queue.enqueue(subscriberActivationTasks[i]);
|
|
395
514
|
}
|
|
396
515
|
this.tryResolveCompleted();
|
|
397
516
|
},
|
|
398
517
|
(error2) => {
|
|
399
|
-
this.
|
|
518
|
+
this.onResponseError = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
519
|
+
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
520
|
+
this.scheduledCount--;
|
|
521
|
+
this.pendingTasks.delete(subscriberActivationTasks[i]);
|
|
522
|
+
this.queue.enqueue(subscriberActivationTasks[i]);
|
|
523
|
+
}
|
|
524
|
+
this.tryResolveCompleted();
|
|
400
525
|
}
|
|
401
526
|
);
|
|
402
527
|
return;
|
|
403
528
|
}
|
|
404
|
-
for (let i = 0; i <
|
|
529
|
+
for (let i = 0; i < subscriberActivationTasks.length; i++) {
|
|
405
530
|
this.scheduledCount--;
|
|
406
|
-
this.
|
|
531
|
+
this.pendingTasks.delete(subscriberActivationTasks[i]);
|
|
532
|
+
this.queue.enqueue(subscriberActivationTasks[i]);
|
|
407
533
|
}
|
|
408
534
|
this.tryResolveCompleted();
|
|
409
535
|
}
|
|
410
536
|
responseToSignal(signalOrSignals) {
|
|
411
537
|
if (Array.isArray(signalOrSignals)) {
|
|
412
538
|
for (const signal of signalOrSignals) {
|
|
413
|
-
const ownerNeuron2 = this.cns.getParentNeuronByCollateralName(
|
|
539
|
+
const ownerNeuron2 = this.cns.network.getParentNeuronByCollateralName(
|
|
414
540
|
signal.collateralName
|
|
415
541
|
);
|
|
416
542
|
if (ownerNeuron2) {
|
|
@@ -420,7 +546,7 @@ var CNSStimulation = class {
|
|
|
420
546
|
this.processResponseOrResponses(void 0, signalOrSignals);
|
|
421
547
|
return;
|
|
422
548
|
}
|
|
423
|
-
const ownerNeuron = this.cns.getParentNeuronByCollateralName(
|
|
549
|
+
const ownerNeuron = this.cns.network.getParentNeuronByCollateralName(
|
|
424
550
|
signalOrSignals.collateralName
|
|
425
551
|
);
|
|
426
552
|
if (ownerNeuron) {
|
|
@@ -431,88 +557,6 @@ var CNSStimulation = class {
|
|
|
431
557
|
}
|
|
432
558
|
};
|
|
433
559
|
|
|
434
|
-
// src/CNSTaskQueue.ts
|
|
435
|
-
var CNSTaskQueue = class {
|
|
436
|
-
constructor(concurrency) {
|
|
437
|
-
this.concurrency = concurrency;
|
|
438
|
-
this.pumping = false;
|
|
439
|
-
this.needsPump = false;
|
|
440
|
-
this.activeOperations = 0;
|
|
441
|
-
this.items = [];
|
|
442
|
-
}
|
|
443
|
-
get canStartOperation() {
|
|
444
|
-
const limit = this.concurrency ?? Infinity;
|
|
445
|
-
return this.activeOperations < limit;
|
|
446
|
-
}
|
|
447
|
-
enqueue(task) {
|
|
448
|
-
return new Promise((resolve, reject) => {
|
|
449
|
-
this.items.push({ task, resolve, reject });
|
|
450
|
-
if (!this.pumping) this.pump();
|
|
451
|
-
else this.needsPump = true;
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
pump() {
|
|
455
|
-
if (this.pumping) {
|
|
456
|
-
this.needsPump = true;
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
this.pumping = true;
|
|
460
|
-
while (this.canStartOperation && this.items.length > 0) {
|
|
461
|
-
const { task, resolve, reject } = this.items.shift();
|
|
462
|
-
this.activeOperations++;
|
|
463
|
-
try {
|
|
464
|
-
const ret = task();
|
|
465
|
-
if (ret && typeof ret.then === "function") {
|
|
466
|
-
ret.then(
|
|
467
|
-
(cb) => {
|
|
468
|
-
try {
|
|
469
|
-
if (typeof cb === "function") cb();
|
|
470
|
-
resolve();
|
|
471
|
-
} finally {
|
|
472
|
-
this.activeOperations--;
|
|
473
|
-
if (this.items.length > 0 && this.canStartOperation) {
|
|
474
|
-
if (this.pumping) this.needsPump = true;
|
|
475
|
-
else this.pump();
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
},
|
|
479
|
-
(err) => {
|
|
480
|
-
try {
|
|
481
|
-
reject(err);
|
|
482
|
-
} finally {
|
|
483
|
-
this.activeOperations--;
|
|
484
|
-
if (this.items.length > 0 && this.canStartOperation) {
|
|
485
|
-
if (this.pumping) this.needsPump = true;
|
|
486
|
-
else this.pump();
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
);
|
|
491
|
-
break;
|
|
492
|
-
} else {
|
|
493
|
-
try {
|
|
494
|
-
if (typeof ret === "function") ret();
|
|
495
|
-
resolve();
|
|
496
|
-
} finally {
|
|
497
|
-
this.activeOperations--;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
} catch (e) {
|
|
501
|
-
try {
|
|
502
|
-
reject(e);
|
|
503
|
-
} finally {
|
|
504
|
-
this.activeOperations--;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
this.pumping = false;
|
|
509
|
-
if (this.needsPump) {
|
|
510
|
-
this.needsPump = false;
|
|
511
|
-
this.pump();
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
};
|
|
515
|
-
|
|
516
560
|
// src/CNSInstanceNeuronQueue.ts
|
|
517
561
|
var CNSInstanceNeuronQueue = class {
|
|
518
562
|
constructor() {
|
|
@@ -568,20 +612,10 @@ var CNSInstanceNeuronQueue = class {
|
|
|
568
612
|
}
|
|
569
613
|
};
|
|
570
614
|
|
|
571
|
-
// src/
|
|
572
|
-
var
|
|
573
|
-
constructor(neurons
|
|
615
|
+
// src/CNSNetwork.ts
|
|
616
|
+
var CNSNetwork = class {
|
|
617
|
+
constructor(neurons) {
|
|
574
618
|
this.neurons = neurons;
|
|
575
|
-
this.options = options;
|
|
576
|
-
/**
|
|
577
|
-
* Fast lookup: collateralName -> list of (neuron, dendrite) subscribers.
|
|
578
|
-
* Built once at construction time.
|
|
579
|
-
*/
|
|
580
|
-
this.subIndex = /* @__PURE__ */ new Map();
|
|
581
|
-
this.neuronIndex = /* @__PURE__ */ new Map();
|
|
582
|
-
this.dendriteIndex = /* @__PURE__ */ new Map();
|
|
583
|
-
this.collateralIndex = /* @__PURE__ */ new Map();
|
|
584
|
-
this.parentNeuronByCollateralName = /* @__PURE__ */ new Map();
|
|
585
619
|
/**
|
|
586
620
|
* Strongly Connected Components of the neuron graph.
|
|
587
621
|
* Each component is a set of neuron IDs that can reach each other.
|
|
@@ -600,24 +634,17 @@ var CNS = class {
|
|
|
600
634
|
*/
|
|
601
635
|
this.sccAncestors = /* @__PURE__ */ new Map();
|
|
602
636
|
/**
|
|
603
|
-
*
|
|
604
|
-
|
|
605
|
-
this.neuronGates = /* @__PURE__ */ new Map();
|
|
606
|
-
/**
|
|
607
|
-
* Global task queue used by stimulation to schedule per-neuron gated work.
|
|
608
|
-
* Does not replace per-stimulation concurrency; only coordinates global per-neuron limits.
|
|
609
|
-
*/
|
|
610
|
-
this.globalTaskQueue = new CNSTaskQueue();
|
|
611
|
-
this.instanceNeuronQueue = new CNSInstanceNeuronQueue();
|
|
612
|
-
/**
|
|
613
|
-
* Global response listeners applied to every stimulation.
|
|
637
|
+
* Fast lookup: collateralName -> list of (neuron, dendrite) subscribers.
|
|
638
|
+
* Built once at construction time.
|
|
614
639
|
*/
|
|
615
|
-
this.
|
|
640
|
+
this.subIndex = /* @__PURE__ */ new Map();
|
|
641
|
+
this.neuronIndex = /* @__PURE__ */ new Map();
|
|
642
|
+
this.dendriteIndex = /* @__PURE__ */ new Map();
|
|
643
|
+
this.collateralIndex = /* @__PURE__ */ new Map();
|
|
644
|
+
this.parentNeuronByCollateralName = /* @__PURE__ */ new Map();
|
|
616
645
|
this.validateUniqueIdentifiers();
|
|
617
646
|
this.buildIndexes();
|
|
618
|
-
|
|
619
|
-
this.buildSCC();
|
|
620
|
-
}
|
|
647
|
+
this.buildSCC();
|
|
621
648
|
}
|
|
622
649
|
/**
|
|
623
650
|
* Validate uniqueness constraints:
|
|
@@ -647,126 +674,6 @@ var CNS = class {
|
|
|
647
674
|
);
|
|
648
675
|
}
|
|
649
676
|
}
|
|
650
|
-
addResponseListener(listener) {
|
|
651
|
-
this.globalResponseListeners.push(listener);
|
|
652
|
-
let active = true;
|
|
653
|
-
return () => {
|
|
654
|
-
if (!active) return;
|
|
655
|
-
active = false;
|
|
656
|
-
const idx = this.globalResponseListeners.indexOf(listener);
|
|
657
|
-
if (idx >= 0) this.globalResponseListeners.splice(idx, 1);
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
wrapOnResponse(local) {
|
|
661
|
-
if (this.globalResponseListeners.length === 0 && !local) {
|
|
662
|
-
return () => {
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
return (r) => {
|
|
666
|
-
let anyPromise = false;
|
|
667
|
-
const promises = [];
|
|
668
|
-
if (local) {
|
|
669
|
-
const res = local(r);
|
|
670
|
-
if (res && typeof res.then === "function") {
|
|
671
|
-
anyPromise = true;
|
|
672
|
-
promises.push(res);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
for (let i = 0; i < this.globalResponseListeners.length; i++) {
|
|
676
|
-
const res = this.globalResponseListeners[i](r);
|
|
677
|
-
if (res && typeof res.then === "function") {
|
|
678
|
-
anyPromise = true;
|
|
679
|
-
promises.push(res);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
if (anyPromise) {
|
|
683
|
-
return Promise.allSettled(promises).then((results) => {
|
|
684
|
-
const rejected = results.find(
|
|
685
|
-
(r2) => r2.status === "rejected"
|
|
686
|
-
);
|
|
687
|
-
if (rejected) throw rejected.reason;
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
runWithNeuronConcurrency(neuron2, fn) {
|
|
693
|
-
const limit = neuron2.concurrency;
|
|
694
|
-
if (limit === void 0 || limit <= 0) {
|
|
695
|
-
return this.globalTaskQueue.enqueue(fn);
|
|
696
|
-
}
|
|
697
|
-
let gate = this.neuronGates.get(neuron2.name);
|
|
698
|
-
if (!gate) {
|
|
699
|
-
gate = { limit, active: 0, waiters: [] };
|
|
700
|
-
this.neuronGates.set(neuron2.name, gate);
|
|
701
|
-
} else {
|
|
702
|
-
gate.limit = limit;
|
|
703
|
-
}
|
|
704
|
-
const wrap = (cb) => {
|
|
705
|
-
return () => {
|
|
706
|
-
try {
|
|
707
|
-
cb();
|
|
708
|
-
} finally {
|
|
709
|
-
gate.active = Math.max(0, gate.active - 1);
|
|
710
|
-
if (gate.waiters.length > 0) {
|
|
711
|
-
const next = gate.waiters.shift();
|
|
712
|
-
next();
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
};
|
|
716
|
-
};
|
|
717
|
-
if (gate.active < gate.limit) {
|
|
718
|
-
gate.active++;
|
|
719
|
-
return this.globalTaskQueue.enqueue(() => {
|
|
720
|
-
const ret = fn();
|
|
721
|
-
if (ret && typeof ret.then === "function") {
|
|
722
|
-
return ret.then((cb) => wrap(cb));
|
|
723
|
-
}
|
|
724
|
-
return wrap(ret);
|
|
725
|
-
});
|
|
726
|
-
}
|
|
727
|
-
return new Promise((resolve) => {
|
|
728
|
-
const starter = () => {
|
|
729
|
-
gate.active++;
|
|
730
|
-
this.globalTaskQueue.enqueue(() => {
|
|
731
|
-
const ret = fn();
|
|
732
|
-
if (ret && typeof ret.then === "function") {
|
|
733
|
-
return ret.then(
|
|
734
|
-
(cb) => wrap(cb)
|
|
735
|
-
);
|
|
736
|
-
}
|
|
737
|
-
return wrap(ret);
|
|
738
|
-
}).then(resolve);
|
|
739
|
-
};
|
|
740
|
-
gate.waiters.push(starter);
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
buildIndexes() {
|
|
744
|
-
this.subIndex.clear();
|
|
745
|
-
this.parentNeuronByCollateralName.clear();
|
|
746
|
-
for (const neuron2 of this.neurons) {
|
|
747
|
-
this.neuronIndex.set(neuron2.name, neuron2);
|
|
748
|
-
for (const dendrite of neuron2.dendrites) {
|
|
749
|
-
const key = dendrite.collateral.name;
|
|
750
|
-
const arr = this.subIndex.get(key) ?? [];
|
|
751
|
-
arr.push({ neuron: neuron2, dendrite });
|
|
752
|
-
this.subIndex.set(
|
|
753
|
-
key,
|
|
754
|
-
arr
|
|
755
|
-
);
|
|
756
|
-
this.dendriteIndex.set(key, dendrite);
|
|
757
|
-
}
|
|
758
|
-
Object.values(neuron2.axon).forEach((collateral2) => {
|
|
759
|
-
this.parentNeuronByCollateralName.set(
|
|
760
|
-
collateral2.name,
|
|
761
|
-
neuron2
|
|
762
|
-
);
|
|
763
|
-
this.collateralIndex.set(
|
|
764
|
-
collateral2.name,
|
|
765
|
-
collateral2
|
|
766
|
-
);
|
|
767
|
-
});
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
677
|
/**
|
|
771
678
|
* Build the neuron graph where neurons are connected if one can stimulate the other.
|
|
772
679
|
*/
|
|
@@ -811,7 +718,7 @@ var CNS = class {
|
|
|
811
718
|
stack.push(neuronId);
|
|
812
719
|
onStack.add(neuronId);
|
|
813
720
|
const neighbors = graph.get(neuronId) || /* @__PURE__ */ new Set();
|
|
814
|
-
for (const neighbor of neighbors) {
|
|
721
|
+
for (const neighbor of Array.from(neighbors)) {
|
|
815
722
|
if (!index.has(neighbor)) {
|
|
816
723
|
strongConnect(neighbor);
|
|
817
724
|
lowlink.set(
|
|
@@ -843,7 +750,7 @@ var CNS = class {
|
|
|
843
750
|
}
|
|
844
751
|
this.stronglyConnectedComponents = components;
|
|
845
752
|
for (let i = 0; i < components.length; i++) {
|
|
846
|
-
for (const neuronId of components[i]) {
|
|
753
|
+
for (const neuronId of Array.from(components[i])) {
|
|
847
754
|
this.neuronToSCC.set(neuronId, i);
|
|
848
755
|
}
|
|
849
756
|
}
|
|
@@ -860,9 +767,9 @@ var CNS = class {
|
|
|
860
767
|
}
|
|
861
768
|
for (let i = 0; i < this.stronglyConnectedComponents.length; i++) {
|
|
862
769
|
const scc = this.stronglyConnectedComponents[i];
|
|
863
|
-
for (const neuronId of scc) {
|
|
770
|
+
for (const neuronId of Array.from(scc)) {
|
|
864
771
|
const neighbors = neuronGraph.get(neuronId) || /* @__PURE__ */ new Set();
|
|
865
|
-
for (const neighborId of neighbors) {
|
|
772
|
+
for (const neighborId of Array.from(neighbors)) {
|
|
866
773
|
const neighborSccIndex = this.neuronToSCC.get(neighborId);
|
|
867
774
|
if (neighborSccIndex !== void 0 && neighborSccIndex !== i) {
|
|
868
775
|
this.sccDag.get(neighborSccIndex).add(i);
|
|
@@ -892,11 +799,11 @@ var CNS = class {
|
|
|
892
799
|
while (queue.length > 0) {
|
|
893
800
|
const current = queue.shift();
|
|
894
801
|
const outgoingEdges = this.getOutgoingEdges(current);
|
|
895
|
-
for (const neighbor of outgoingEdges) {
|
|
802
|
+
for (const neighbor of Array.from(outgoingEdges)) {
|
|
896
803
|
const neighborAncestors = this.sccAncestors.get(neighbor);
|
|
897
804
|
neighborAncestors.add(current);
|
|
898
805
|
const currentAncestors = this.sccAncestors.get(current);
|
|
899
|
-
for (const ancestor of currentAncestors) {
|
|
806
|
+
for (const ancestor of Array.from(currentAncestors)) {
|
|
900
807
|
neighborAncestors.add(ancestor);
|
|
901
808
|
}
|
|
902
809
|
const newInDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
@@ -912,7 +819,7 @@ var CNS = class {
|
|
|
912
819
|
*/
|
|
913
820
|
getOutgoingEdges(sccIndex) {
|
|
914
821
|
const outgoing = /* @__PURE__ */ new Set();
|
|
915
|
-
for (const [targetScc, incomingEdges] of this.sccDag) {
|
|
822
|
+
for (const [targetScc, incomingEdges] of Array.from(this.sccDag)) {
|
|
916
823
|
if (incomingEdges.has(sccIndex)) {
|
|
917
824
|
outgoing.add(targetScc);
|
|
918
825
|
}
|
|
@@ -947,13 +854,40 @@ var CNS = class {
|
|
|
947
854
|
}
|
|
948
855
|
const ancestors = this.sccAncestors.get(sccIndex);
|
|
949
856
|
if (!ancestors) return true;
|
|
950
|
-
for (const ancestorSccIndex of ancestors) {
|
|
857
|
+
for (const ancestorSccIndex of Array.from(ancestors)) {
|
|
951
858
|
if (activeSccCounts.get(ancestorSccIndex) && activeSccCounts.get(ancestorSccIndex) > 0) {
|
|
952
859
|
return false;
|
|
953
860
|
}
|
|
954
861
|
}
|
|
955
862
|
return true;
|
|
956
863
|
}
|
|
864
|
+
buildIndexes() {
|
|
865
|
+
this.subIndex.clear();
|
|
866
|
+
this.parentNeuronByCollateralName.clear();
|
|
867
|
+
for (const neuron2 of this.neurons) {
|
|
868
|
+
this.neuronIndex.set(neuron2.name, neuron2);
|
|
869
|
+
for (const dendrite of neuron2.dendrites) {
|
|
870
|
+
const key = dendrite.collateral.name;
|
|
871
|
+
const arr = this.subIndex.get(key) ?? [];
|
|
872
|
+
arr.push({ neuron: neuron2, dendrite });
|
|
873
|
+
this.subIndex.set(
|
|
874
|
+
key,
|
|
875
|
+
arr
|
|
876
|
+
);
|
|
877
|
+
this.dendriteIndex.set(key, dendrite);
|
|
878
|
+
}
|
|
879
|
+
Object.values(neuron2.axon).forEach((collateral2) => {
|
|
880
|
+
this.parentNeuronByCollateralName.set(
|
|
881
|
+
collateral2.name,
|
|
882
|
+
neuron2
|
|
883
|
+
);
|
|
884
|
+
this.collateralIndex.set(
|
|
885
|
+
collateral2.name,
|
|
886
|
+
collateral2
|
|
887
|
+
);
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
957
891
|
getParentNeuronByCollateralName(collateralName) {
|
|
958
892
|
return this.parentNeuronByCollateralName.get(collateralName);
|
|
959
893
|
}
|
|
@@ -977,6 +911,80 @@ var CNS = class {
|
|
|
977
911
|
getSubscribers(collateralName) {
|
|
978
912
|
return this.subIndex.get(collateralName) ?? [];
|
|
979
913
|
}
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// src/CNS.ts
|
|
917
|
+
var CNS = class {
|
|
918
|
+
constructor(neurons, options) {
|
|
919
|
+
this.neurons = neurons;
|
|
920
|
+
this.options = options;
|
|
921
|
+
/**
|
|
922
|
+
* Global per-neuron concurrency gates shared across all stimulations.
|
|
923
|
+
*/
|
|
924
|
+
this.neuronGates = /* @__PURE__ */ new Map();
|
|
925
|
+
/**
|
|
926
|
+
* Global task queue used by stimulation to schedule per-neuron gated work.
|
|
927
|
+
* Does not replace per-stimulation concurrency; only coordinates global per-neuron limits.
|
|
928
|
+
*/
|
|
929
|
+
this.instanceNeuronQueue = new CNSInstanceNeuronQueue();
|
|
930
|
+
/**
|
|
931
|
+
* Global response listeners applied to every stimulation.
|
|
932
|
+
*/
|
|
933
|
+
this.globalResponseListeners = [];
|
|
934
|
+
this.network = new CNSNetwork(this.neurons);
|
|
935
|
+
}
|
|
936
|
+
addResponseListener(listener) {
|
|
937
|
+
this.globalResponseListeners.push(listener);
|
|
938
|
+
let active = true;
|
|
939
|
+
return () => {
|
|
940
|
+
if (!active) return;
|
|
941
|
+
active = false;
|
|
942
|
+
const idx = this.globalResponseListeners.indexOf(listener);
|
|
943
|
+
if (idx >= 0) this.globalResponseListeners.splice(idx, 1);
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
wrapOnResponse(local) {
|
|
947
|
+
if (this.globalResponseListeners.length === 0 && !local) {
|
|
948
|
+
return () => {
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
return (r) => {
|
|
952
|
+
let anyPromise = false;
|
|
953
|
+
const promises = [];
|
|
954
|
+
if (local) {
|
|
955
|
+
try {
|
|
956
|
+
const res = local(r);
|
|
957
|
+
if (res && typeof res.then === "function") {
|
|
958
|
+
anyPromise = true;
|
|
959
|
+
promises.push(res);
|
|
960
|
+
}
|
|
961
|
+
} catch (error) {
|
|
962
|
+
anyPromise = true;
|
|
963
|
+
promises.push(Promise.reject(error));
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
for (let i = 0; i < this.globalResponseListeners.length; i++) {
|
|
967
|
+
try {
|
|
968
|
+
const res = this.globalResponseListeners[i](r);
|
|
969
|
+
if (res && typeof res.then === "function") {
|
|
970
|
+
anyPromise = true;
|
|
971
|
+
promises.push(res);
|
|
972
|
+
}
|
|
973
|
+
} catch (error) {
|
|
974
|
+
anyPromise = true;
|
|
975
|
+
promises.push(Promise.reject(error));
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (anyPromise) {
|
|
979
|
+
return Promise.allSettled(promises).then((results) => {
|
|
980
|
+
const rejected = results.find(
|
|
981
|
+
(r2) => r2.status === "rejected"
|
|
982
|
+
);
|
|
983
|
+
if (rejected) throw rejected.reason;
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
}
|
|
980
988
|
stimulate(signalOrSignals, options) {
|
|
981
989
|
const wrapped = this.wrapOnResponse(options?.onResponse);
|
|
982
990
|
const stimulation = new CNSStimulation(this, this.instanceNeuronQueue, {
|
|
@@ -984,7 +992,19 @@ var CNS = class {
|
|
|
984
992
|
onResponse: wrapped
|
|
985
993
|
});
|
|
986
994
|
stimulation.responseToSignal(signalOrSignals);
|
|
987
|
-
return stimulation
|
|
995
|
+
return stimulation;
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Start a stimulation with activation tasks directly
|
|
999
|
+
*/
|
|
1000
|
+
activate(tasks, options) {
|
|
1001
|
+
const wrapped = this.wrapOnResponse(options?.onResponse);
|
|
1002
|
+
const stimulation = new CNSStimulation(this, this.instanceNeuronQueue, {
|
|
1003
|
+
...options,
|
|
1004
|
+
onResponse: wrapped
|
|
1005
|
+
});
|
|
1006
|
+
stimulation.enqueueTasks(tasks);
|
|
1007
|
+
return stimulation;
|
|
988
1008
|
}
|
|
989
1009
|
};
|
|
990
1010
|
|