@almadar/runtime 3.1.1 → 3.1.3
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/{OrbitalServerRuntime-QXgOGiS8.d.ts → OrbitalServerRuntime-DWJYcIJG.d.ts} +49 -17
- package/dist/OrbitalServerRuntime.d.ts +1 -1
- package/dist/OrbitalServerRuntime.js +1 -1
- package/dist/{chunk-GU35X5AW.js → chunk-QQIRPNHH.js} +196 -59
- package/dist/chunk-QQIRPNHH.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-GU35X5AW.js.map +0 -1
|
@@ -96,6 +96,11 @@ declare function findInitialState(trait: TraitDefinition): string;
|
|
|
96
96
|
declare function createInitialTraitState(trait: TraitDefinition): TraitState;
|
|
97
97
|
/**
|
|
98
98
|
* Find a matching transition from the current state for the given event.
|
|
99
|
+
*
|
|
100
|
+
* **Guard-unaware**: returns the first transition matching `from` /
|
|
101
|
+
* `event` regardless of any attached guard. Use `findMatchingTransitions`
|
|
102
|
+
* when multiple sibling transitions share the same `from`/`event` and
|
|
103
|
+
* disambiguate by guard.
|
|
99
104
|
*/
|
|
100
105
|
declare function findTransition(trait: TraitDefinition, currentState: string, eventKey: string): TraitDefinition['transitions'][0] | undefined;
|
|
101
106
|
/**
|
|
@@ -164,6 +169,19 @@ interface ProcessEventOptions {
|
|
|
164
169
|
declare function processEvent(options: ProcessEventOptions): TransitionResult;
|
|
165
170
|
declare class StateMachineManager {
|
|
166
171
|
private traits;
|
|
172
|
+
/**
|
|
173
|
+
* State map keyed by `${traitName}::${entityId | __singleton__}`.
|
|
174
|
+
*
|
|
175
|
+
* Each entity instance of an orbital gets its own copy of every
|
|
176
|
+
* trait's state machine. This is what enables N parallel subagents
|
|
177
|
+
* (one OrbitalProcess row per dispatched orbital) to all run their
|
|
178
|
+
* own Build/Validate/Fix cycle without colliding on shared trait
|
|
179
|
+
* state — the original cause of GAP-AGB-2.
|
|
180
|
+
*
|
|
181
|
+
* Initial state is created lazily on first event for each scope, so
|
|
182
|
+
* adding a trait does not pre-allocate state for every potential
|
|
183
|
+
* entity (and there's no need to know entity ids up front).
|
|
184
|
+
*/
|
|
167
185
|
private states;
|
|
168
186
|
private config;
|
|
169
187
|
private observer?;
|
|
@@ -184,18 +202,35 @@ declare class StateMachineManager {
|
|
|
184
202
|
* Remove a trait from the manager.
|
|
185
203
|
*/
|
|
186
204
|
removeTrait(traitName: string): void;
|
|
205
|
+
/**
|
|
206
|
+
* Get-or-init the state row for a (trait, entityId) pair.
|
|
207
|
+
* Returns undefined if the trait isn't registered.
|
|
208
|
+
*/
|
|
209
|
+
private getOrInitState;
|
|
187
210
|
/**
|
|
188
211
|
* Get current state for a trait.
|
|
212
|
+
*
|
|
213
|
+
* For single-entity orbitals, omit `entityId` — returns the singleton
|
|
214
|
+
* scope. For multi-entity orbitals (e.g. agent OrbitalSubagent), pass
|
|
215
|
+
* the entity row id to look up that specific instance's state.
|
|
189
216
|
*/
|
|
190
|
-
getState(traitName: string): TraitState | undefined;
|
|
217
|
+
getState(traitName: string, entityId?: string): TraitState | undefined;
|
|
191
218
|
/**
|
|
192
|
-
* Get
|
|
219
|
+
* Get a flat traitName→state map. For multi-entity orbitals this
|
|
220
|
+
* returns one entry per trait collapsed onto the singleton scope (or
|
|
221
|
+
* the first observed scope if singleton is empty). Use
|
|
222
|
+
* `getAllStatesByScope()` to get the full per-entity view.
|
|
193
223
|
*/
|
|
194
224
|
getAllStates(): Map<string, TraitState>;
|
|
225
|
+
/**
|
|
226
|
+
* Get every per-entity state row, grouped by trait. Useful for
|
|
227
|
+
* inspecting parallel subagent state.
|
|
228
|
+
*/
|
|
229
|
+
getAllStatesByScope(): Map<string, Map<string, TraitState>>;
|
|
195
230
|
/**
|
|
196
231
|
* Check if a trait can handle an event from its current state.
|
|
197
232
|
*/
|
|
198
|
-
canHandleEvent(traitName: string, eventKey: string): boolean;
|
|
233
|
+
canHandleEvent(traitName: string, eventKey: string, entityId?: string): boolean;
|
|
199
234
|
/**
|
|
200
235
|
* Send an event to all traits.
|
|
201
236
|
*
|
|
@@ -214,31 +249,28 @@ declare class StateMachineManager {
|
|
|
214
249
|
*/
|
|
215
250
|
enqueueEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow): void;
|
|
216
251
|
/**
|
|
217
|
-
* Drain a single trait's event queue, processing
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* awaiting all effects) before the next event is dequeued. If the queue
|
|
221
|
-
* is already being drained for this trait, this call is a no-op (the
|
|
222
|
-
* running drain will pick up newly enqueued events).
|
|
223
|
-
*
|
|
224
|
-
* @param traitName - Which trait's queue to drain
|
|
225
|
-
* @param executeEffects - Async callback to run effects for a successful transition
|
|
252
|
+
* Drain a single (trait, entity) pair's event queue, processing
|
|
253
|
+
* events sequentially. Pass `entityId` to drain a specific entity
|
|
254
|
+
* instance; omit it to drain the singleton scope.
|
|
226
255
|
*/
|
|
227
|
-
drainQueue(traitName: string, executeEffects: (traitName: string, result: TransitionResult, payload?: EventPayload) => Promise<void
|
|
256
|
+
drainQueue(traitName: string, executeEffects: (traitName: string, result: TransitionResult, payload?: EventPayload) => Promise<void>, entityId?: string): Promise<void>;
|
|
228
257
|
/**
|
|
229
258
|
* Check whether a trait's queue is currently being drained.
|
|
230
259
|
*/
|
|
231
|
-
isProcessing(traitName: string): boolean;
|
|
260
|
+
isProcessing(traitName: string, entityId?: string): boolean;
|
|
232
261
|
/**
|
|
233
262
|
* Get the number of pending events in a trait's queue.
|
|
234
263
|
*/
|
|
235
|
-
getQueueLength(traitName: string): number;
|
|
264
|
+
getQueueLength(traitName: string, entityId?: string): number;
|
|
236
265
|
/**
|
|
237
266
|
* Reset a trait to its initial state.
|
|
267
|
+
*
|
|
268
|
+
* If `entityId` is provided, resets only that entity's scope.
|
|
269
|
+
* Otherwise resets every entity scope known for the trait.
|
|
238
270
|
*/
|
|
239
|
-
resetTrait(traitName: string): void;
|
|
271
|
+
resetTrait(traitName: string, entityId?: string): void;
|
|
240
272
|
/**
|
|
241
|
-
* Reset all traits to initial states.
|
|
273
|
+
* Reset all traits to initial states (every entity scope).
|
|
242
274
|
*/
|
|
243
275
|
resetAll(): void;
|
|
244
276
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'express';
|
|
2
|
-
export { v as EffectResult, L as LoaderConfig, w as LocalPersistenceAdapter, O as OrbitalEventRequest, c as OrbitalEventResponse, x as OrbitalServerRuntime, d as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, i as RuntimeOrbital, j as RuntimeOrbitalSchema, k as RuntimeTrait, y as RuntimeTraitTick, z as createOrbitalServerRuntime } from './OrbitalServerRuntime-
|
|
2
|
+
export { v as EffectResult, L as LoaderConfig, w as LocalPersistenceAdapter, O as OrbitalEventRequest, c as OrbitalEventResponse, x as OrbitalServerRuntime, d as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, i as RuntimeOrbital, j as RuntimeOrbitalSchema, k as RuntimeTrait, y as RuntimeTraitTick, z as createOrbitalServerRuntime } from './OrbitalServerRuntime-DWJYcIJG.js';
|
|
3
3
|
import './types-CM6txTNy.js';
|
|
4
4
|
import '@almadar/core';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventBus, createUnifiedLoader, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-
|
|
1
|
+
import { EventBus, createUnifiedLoader, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-QQIRPNHH.js';
|
|
2
2
|
import './chunk-PZ5AY32C.js';
|
|
3
3
|
import { Router } from 'express';
|
|
4
4
|
import * as fs from 'fs';
|
|
@@ -304,17 +304,20 @@ function createInitialTraitState(trait) {
|
|
|
304
304
|
context: {}
|
|
305
305
|
};
|
|
306
306
|
}
|
|
307
|
-
function
|
|
307
|
+
function findMatchingTransitions(trait, currentState, eventKey) {
|
|
308
308
|
if (!trait.transitions || trait.transitions.length === 0) {
|
|
309
|
-
return
|
|
309
|
+
return [];
|
|
310
310
|
}
|
|
311
|
-
return trait.transitions.
|
|
311
|
+
return trait.transitions.filter((t) => {
|
|
312
312
|
if (Array.isArray(t.from)) {
|
|
313
313
|
return t.from.includes(currentState) && t.event === eventKey;
|
|
314
314
|
}
|
|
315
315
|
return t.from === currentState && t.event === eventKey;
|
|
316
316
|
});
|
|
317
317
|
}
|
|
318
|
+
function findTransition(trait, currentState, eventKey) {
|
|
319
|
+
return findMatchingTransitions(trait, currentState, eventKey)[0];
|
|
320
|
+
}
|
|
318
321
|
function normalizeEventKey(eventKey) {
|
|
319
322
|
if (!eventKey) return "";
|
|
320
323
|
return eventKey.startsWith("UI:") ? eventKey.slice(3) : eventKey;
|
|
@@ -331,8 +334,8 @@ function processEvent(options) {
|
|
|
331
334
|
contextExtensions
|
|
332
335
|
} = options;
|
|
333
336
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
334
|
-
const
|
|
335
|
-
if (
|
|
337
|
+
const candidates = findMatchingTransitions(trait, traitState.currentState, normalizedEvent);
|
|
338
|
+
if (candidates.length === 0) {
|
|
336
339
|
smLog.debug("noTransition", { trait: trait.name, event: normalizedEvent, currentState: traitState.currentState });
|
|
337
340
|
return {
|
|
338
341
|
executed: false,
|
|
@@ -341,8 +344,22 @@ function processEvent(options) {
|
|
|
341
344
|
effects: []
|
|
342
345
|
};
|
|
343
346
|
}
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
let lastFailedGuardTransition;
|
|
348
|
+
for (const transition of candidates) {
|
|
349
|
+
smLog.debug("processEvent", { trait: trait.name, event: normalizedEvent, currentState: traitState.currentState, to: transition.to });
|
|
350
|
+
if (!transition.guard) {
|
|
351
|
+
return {
|
|
352
|
+
executed: true,
|
|
353
|
+
newState: transition.to,
|
|
354
|
+
previousState: traitState.currentState,
|
|
355
|
+
effects: transition.effects || [],
|
|
356
|
+
transition: {
|
|
357
|
+
from: traitState.currentState,
|
|
358
|
+
to: transition.to,
|
|
359
|
+
event: normalizedEvent
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
}
|
|
346
363
|
const ctx = createContextFromBindings({
|
|
347
364
|
entity: entityData,
|
|
348
365
|
payload,
|
|
@@ -354,20 +371,21 @@ function processEvent(options) {
|
|
|
354
371
|
ctx
|
|
355
372
|
);
|
|
356
373
|
smLog.debug("guard:evaluate", { trait: trait.name, event: normalizedEvent, guardResult: guardPasses });
|
|
357
|
-
if (
|
|
374
|
+
if (guardPasses) {
|
|
358
375
|
return {
|
|
359
|
-
executed:
|
|
360
|
-
newState:
|
|
376
|
+
executed: true,
|
|
377
|
+
newState: transition.to,
|
|
361
378
|
previousState: traitState.currentState,
|
|
362
|
-
effects: [],
|
|
379
|
+
effects: transition.effects || [],
|
|
363
380
|
transition: {
|
|
364
381
|
from: traitState.currentState,
|
|
365
382
|
to: transition.to,
|
|
366
383
|
event: normalizedEvent
|
|
367
384
|
},
|
|
368
|
-
guardResult:
|
|
385
|
+
guardResult: true
|
|
369
386
|
};
|
|
370
387
|
}
|
|
388
|
+
lastFailedGuardTransition = transition;
|
|
371
389
|
} catch (error) {
|
|
372
390
|
if (guardMode === "strict") {
|
|
373
391
|
console.error(
|
|
@@ -388,27 +406,62 @@ function processEvent(options) {
|
|
|
388
406
|
};
|
|
389
407
|
}
|
|
390
408
|
console.error("[StateMachineCore] Guard evaluation error:", error);
|
|
409
|
+
return {
|
|
410
|
+
executed: true,
|
|
411
|
+
newState: transition.to,
|
|
412
|
+
previousState: traitState.currentState,
|
|
413
|
+
effects: transition.effects || [],
|
|
414
|
+
transition: {
|
|
415
|
+
from: traitState.currentState,
|
|
416
|
+
to: transition.to,
|
|
417
|
+
event: normalizedEvent
|
|
418
|
+
},
|
|
419
|
+
guardResult: true
|
|
420
|
+
};
|
|
391
421
|
}
|
|
392
422
|
}
|
|
393
423
|
return {
|
|
394
|
-
executed:
|
|
395
|
-
newState:
|
|
424
|
+
executed: false,
|
|
425
|
+
newState: traitState.currentState,
|
|
396
426
|
previousState: traitState.currentState,
|
|
397
|
-
effects:
|
|
398
|
-
transition: {
|
|
427
|
+
effects: [],
|
|
428
|
+
transition: lastFailedGuardTransition ? {
|
|
399
429
|
from: traitState.currentState,
|
|
400
|
-
to:
|
|
430
|
+
to: lastFailedGuardTransition.to,
|
|
401
431
|
event: normalizedEvent
|
|
402
|
-
},
|
|
403
|
-
guardResult:
|
|
432
|
+
} : void 0,
|
|
433
|
+
guardResult: false
|
|
404
434
|
};
|
|
405
435
|
}
|
|
436
|
+
var SINGLETON_SCOPE = "__singleton__";
|
|
437
|
+
function scopeOf(entityData) {
|
|
438
|
+
const id = entityData && entityData["id"];
|
|
439
|
+
return id ?? SINGLETON_SCOPE;
|
|
440
|
+
}
|
|
441
|
+
function compositeKey(traitName, scope) {
|
|
442
|
+
return `${traitName}::${scope}`;
|
|
443
|
+
}
|
|
406
444
|
var StateMachineManager = class {
|
|
407
445
|
traits = /* @__PURE__ */ new Map();
|
|
446
|
+
/**
|
|
447
|
+
* State map keyed by `${traitName}::${entityId | __singleton__}`.
|
|
448
|
+
*
|
|
449
|
+
* Each entity instance of an orbital gets its own copy of every
|
|
450
|
+
* trait's state machine. This is what enables N parallel subagents
|
|
451
|
+
* (one OrbitalProcess row per dispatched orbital) to all run their
|
|
452
|
+
* own Build/Validate/Fix cycle without colliding on shared trait
|
|
453
|
+
* state — the original cause of GAP-AGB-2.
|
|
454
|
+
*
|
|
455
|
+
* Initial state is created lazily on first event for each scope, so
|
|
456
|
+
* adding a trait does not pre-allocate state for every potential
|
|
457
|
+
* entity (and there's no need to know entity ids up front).
|
|
458
|
+
*/
|
|
408
459
|
states = /* @__PURE__ */ new Map();
|
|
409
460
|
config;
|
|
410
461
|
observer;
|
|
411
|
-
// Actor-model
|
|
462
|
+
// Actor-model queues, also keyed by `${traitName}::${entityId}` so
|
|
463
|
+
// each entity gets its own actor loop and concurrent subagents do
|
|
464
|
+
// not serialize through a shared queue.
|
|
412
465
|
queues = /* @__PURE__ */ new Map();
|
|
413
466
|
processing = /* @__PURE__ */ new Set();
|
|
414
467
|
constructor(traits = [], config = {}, observer) {
|
|
@@ -431,33 +484,101 @@ var StateMachineManager = class {
|
|
|
431
484
|
*/
|
|
432
485
|
addTrait(trait) {
|
|
433
486
|
this.traits.set(trait.name, trait);
|
|
434
|
-
this.states.set(trait.name, createInitialTraitState(trait));
|
|
435
487
|
}
|
|
436
488
|
/**
|
|
437
489
|
* Remove a trait from the manager.
|
|
438
490
|
*/
|
|
439
491
|
removeTrait(traitName) {
|
|
440
492
|
this.traits.delete(traitName);
|
|
441
|
-
|
|
493
|
+
const prefix = `${traitName}::`;
|
|
494
|
+
for (const key of [...this.states.keys()]) {
|
|
495
|
+
if (key.startsWith(prefix)) this.states.delete(key);
|
|
496
|
+
}
|
|
497
|
+
for (const key of [...this.queues.keys()]) {
|
|
498
|
+
if (key.startsWith(prefix)) this.queues.delete(key);
|
|
499
|
+
}
|
|
500
|
+
for (const key of [...this.processing]) {
|
|
501
|
+
if (key.startsWith(prefix)) this.processing.delete(key);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Get-or-init the state row for a (trait, entityId) pair.
|
|
506
|
+
* Returns undefined if the trait isn't registered.
|
|
507
|
+
*/
|
|
508
|
+
getOrInitState(traitName, scope) {
|
|
509
|
+
const trait = this.traits.get(traitName);
|
|
510
|
+
if (!trait) return void 0;
|
|
511
|
+
const key = compositeKey(traitName, scope);
|
|
512
|
+
let state = this.states.get(key);
|
|
513
|
+
if (!state) {
|
|
514
|
+
state = createInitialTraitState(trait);
|
|
515
|
+
this.states.set(key, state);
|
|
516
|
+
}
|
|
517
|
+
return state;
|
|
442
518
|
}
|
|
443
519
|
/**
|
|
444
520
|
* Get current state for a trait.
|
|
521
|
+
*
|
|
522
|
+
* For single-entity orbitals, omit `entityId` — returns the singleton
|
|
523
|
+
* scope. For multi-entity orbitals (e.g. agent OrbitalSubagent), pass
|
|
524
|
+
* the entity row id to look up that specific instance's state.
|
|
445
525
|
*/
|
|
446
|
-
getState(traitName) {
|
|
447
|
-
|
|
526
|
+
getState(traitName, entityId) {
|
|
527
|
+
const scope = entityId ?? SINGLETON_SCOPE;
|
|
528
|
+
const key = compositeKey(traitName, scope);
|
|
529
|
+
const existing = this.states.get(key);
|
|
530
|
+
if (existing) return existing;
|
|
531
|
+
return this.getOrInitState(traitName, scope);
|
|
448
532
|
}
|
|
449
533
|
/**
|
|
450
|
-
* Get
|
|
534
|
+
* Get a flat traitName→state map. For multi-entity orbitals this
|
|
535
|
+
* returns one entry per trait collapsed onto the singleton scope (or
|
|
536
|
+
* the first observed scope if singleton is empty). Use
|
|
537
|
+
* `getAllStatesByScope()` to get the full per-entity view.
|
|
451
538
|
*/
|
|
452
539
|
getAllStates() {
|
|
453
|
-
|
|
540
|
+
const out = /* @__PURE__ */ new Map();
|
|
541
|
+
for (const traitName of this.traits.keys()) {
|
|
542
|
+
const singleton = this.states.get(compositeKey(traitName, SINGLETON_SCOPE));
|
|
543
|
+
if (singleton) {
|
|
544
|
+
out.set(traitName, singleton);
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
for (const [key, state] of this.states) {
|
|
548
|
+
if (key.startsWith(`${traitName}::`)) {
|
|
549
|
+
out.set(traitName, state);
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return out;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Get every per-entity state row, grouped by trait. Useful for
|
|
558
|
+
* inspecting parallel subagent state.
|
|
559
|
+
*/
|
|
560
|
+
getAllStatesByScope() {
|
|
561
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
562
|
+
for (const [key, state] of this.states) {
|
|
563
|
+
const sep = key.indexOf("::");
|
|
564
|
+
if (sep < 0) continue;
|
|
565
|
+
const traitName = key.slice(0, sep);
|
|
566
|
+
const scope = key.slice(sep + 2);
|
|
567
|
+
let bucket = grouped.get(traitName);
|
|
568
|
+
if (!bucket) {
|
|
569
|
+
bucket = /* @__PURE__ */ new Map();
|
|
570
|
+
grouped.set(traitName, bucket);
|
|
571
|
+
}
|
|
572
|
+
bucket.set(scope, state);
|
|
573
|
+
}
|
|
574
|
+
return grouped;
|
|
454
575
|
}
|
|
455
576
|
/**
|
|
456
577
|
* Check if a trait can handle an event from its current state.
|
|
457
578
|
*/
|
|
458
|
-
canHandleEvent(traitName, eventKey) {
|
|
579
|
+
canHandleEvent(traitName, eventKey, entityId) {
|
|
459
580
|
const trait = this.traits.get(traitName);
|
|
460
|
-
const state = this.
|
|
581
|
+
const state = this.getOrInitState(traitName, entityId ?? SINGLETON_SCOPE);
|
|
461
582
|
if (!trait || !state) return false;
|
|
462
583
|
return !!findTransition(trait, state.currentState, normalizeEventKey(eventKey));
|
|
463
584
|
}
|
|
@@ -468,9 +589,11 @@ var StateMachineManager = class {
|
|
|
468
589
|
*/
|
|
469
590
|
sendEvent(eventKey, payload, entityData) {
|
|
470
591
|
const results = [];
|
|
592
|
+
const scope = scopeOf(entityData);
|
|
471
593
|
for (const [traitName, trait] of this.traits) {
|
|
472
|
-
const traitState = this.
|
|
594
|
+
const traitState = this.getOrInitState(traitName, scope);
|
|
473
595
|
if (!traitState) continue;
|
|
596
|
+
const key = compositeKey(traitName, scope);
|
|
474
597
|
const result = processEvent({
|
|
475
598
|
traitState,
|
|
476
599
|
trait,
|
|
@@ -482,7 +605,7 @@ var StateMachineManager = class {
|
|
|
482
605
|
contextExtensions: this.config.contextExtensions
|
|
483
606
|
});
|
|
484
607
|
if (result.executed) {
|
|
485
|
-
this.states.set(
|
|
608
|
+
this.states.set(key, {
|
|
486
609
|
...traitState,
|
|
487
610
|
currentState: result.newState,
|
|
488
611
|
previousState: result.previousState,
|
|
@@ -516,31 +639,29 @@ var StateMachineManager = class {
|
|
|
516
639
|
* at a time per trait, effects fully awaited before the next event).
|
|
517
640
|
*/
|
|
518
641
|
enqueueEvent(eventKey, payload, entityData) {
|
|
642
|
+
const scope = scopeOf(entityData);
|
|
519
643
|
for (const [traitName] of this.traits) {
|
|
520
|
-
const
|
|
644
|
+
const key = compositeKey(traitName, scope);
|
|
645
|
+
const queue = this.queues.get(key) ?? [];
|
|
521
646
|
queue.push({ eventKey, payload, entityData });
|
|
522
|
-
this.queues.set(
|
|
647
|
+
this.queues.set(key, queue);
|
|
523
648
|
}
|
|
524
649
|
}
|
|
525
650
|
/**
|
|
526
|
-
* Drain a single trait's event queue, processing
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
* awaiting all effects) before the next event is dequeued. If the queue
|
|
530
|
-
* is already being drained for this trait, this call is a no-op (the
|
|
531
|
-
* running drain will pick up newly enqueued events).
|
|
532
|
-
*
|
|
533
|
-
* @param traitName - Which trait's queue to drain
|
|
534
|
-
* @param executeEffects - Async callback to run effects for a successful transition
|
|
651
|
+
* Drain a single (trait, entity) pair's event queue, processing
|
|
652
|
+
* events sequentially. Pass `entityId` to drain a specific entity
|
|
653
|
+
* instance; omit it to drain the singleton scope.
|
|
535
654
|
*/
|
|
536
|
-
async drainQueue(traitName, executeEffects) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
655
|
+
async drainQueue(traitName, executeEffects, entityId) {
|
|
656
|
+
const scope = entityId ?? SINGLETON_SCOPE;
|
|
657
|
+
const key = compositeKey(traitName, scope);
|
|
658
|
+
if (this.processing.has(key)) return;
|
|
659
|
+
this.processing.add(key);
|
|
660
|
+
const queue = this.queues.get(key) ?? [];
|
|
540
661
|
while (queue.length > 0) {
|
|
541
662
|
const entry = queue.shift();
|
|
542
663
|
const trait = this.traits.get(traitName);
|
|
543
|
-
const traitState = this.
|
|
664
|
+
const traitState = this.getOrInitState(traitName, scope);
|
|
544
665
|
if (!trait || !traitState) continue;
|
|
545
666
|
const result = processEvent({
|
|
546
667
|
traitState,
|
|
@@ -553,7 +674,7 @@ var StateMachineManager = class {
|
|
|
553
674
|
contextExtensions: this.config.contextExtensions
|
|
554
675
|
});
|
|
555
676
|
if (result.executed) {
|
|
556
|
-
this.states.set(
|
|
677
|
+
this.states.set(key, {
|
|
557
678
|
...traitState,
|
|
558
679
|
currentState: result.newState,
|
|
559
680
|
previousState: result.previousState,
|
|
@@ -573,35 +694,51 @@ var StateMachineManager = class {
|
|
|
573
694
|
await executeEffects(traitName, result, entry.payload);
|
|
574
695
|
}
|
|
575
696
|
}
|
|
576
|
-
this.processing.delete(
|
|
697
|
+
this.processing.delete(key);
|
|
577
698
|
}
|
|
578
699
|
/**
|
|
579
700
|
* Check whether a trait's queue is currently being drained.
|
|
580
701
|
*/
|
|
581
|
-
isProcessing(traitName) {
|
|
582
|
-
return this.processing.has(traitName);
|
|
702
|
+
isProcessing(traitName, entityId) {
|
|
703
|
+
return this.processing.has(compositeKey(traitName, entityId ?? SINGLETON_SCOPE));
|
|
583
704
|
}
|
|
584
705
|
/**
|
|
585
706
|
* Get the number of pending events in a trait's queue.
|
|
586
707
|
*/
|
|
587
|
-
getQueueLength(traitName) {
|
|
588
|
-
return this.queues.get(traitName)?.length ?? 0;
|
|
708
|
+
getQueueLength(traitName, entityId) {
|
|
709
|
+
return this.queues.get(compositeKey(traitName, entityId ?? SINGLETON_SCOPE))?.length ?? 0;
|
|
589
710
|
}
|
|
590
711
|
/**
|
|
591
712
|
* Reset a trait to its initial state.
|
|
713
|
+
*
|
|
714
|
+
* If `entityId` is provided, resets only that entity's scope.
|
|
715
|
+
* Otherwise resets every entity scope known for the trait.
|
|
592
716
|
*/
|
|
593
|
-
resetTrait(traitName) {
|
|
717
|
+
resetTrait(traitName, entityId) {
|
|
594
718
|
const trait = this.traits.get(traitName);
|
|
595
|
-
if (trait)
|
|
596
|
-
|
|
719
|
+
if (!trait) return;
|
|
720
|
+
if (entityId) {
|
|
721
|
+
this.states.set(compositeKey(traitName, entityId), createInitialTraitState(trait));
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const prefix = `${traitName}::`;
|
|
725
|
+
for (const key of [...this.states.keys()]) {
|
|
726
|
+
if (key.startsWith(prefix)) {
|
|
727
|
+
this.states.set(key, createInitialTraitState(trait));
|
|
728
|
+
}
|
|
597
729
|
}
|
|
598
730
|
}
|
|
599
731
|
/**
|
|
600
|
-
* Reset all traits to initial states.
|
|
732
|
+
* Reset all traits to initial states (every entity scope).
|
|
601
733
|
*/
|
|
602
734
|
resetAll() {
|
|
603
735
|
for (const [traitName, trait] of this.traits) {
|
|
604
|
-
|
|
736
|
+
const prefix = `${traitName}::`;
|
|
737
|
+
for (const key of [...this.states.keys()]) {
|
|
738
|
+
if (key.startsWith(prefix)) {
|
|
739
|
+
this.states.set(key, createInitialTraitState(trait));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
605
742
|
}
|
|
606
743
|
}
|
|
607
744
|
};
|
|
@@ -2397,5 +2534,5 @@ function parseNamespacedEvent(eventName) {
|
|
|
2397
2534
|
}
|
|
2398
2535
|
|
|
2399
2536
|
export { EffectExecutor, EventBus, HANDLER_MANIFEST, StateMachineManager, containsBindings, createContextFromBindings, createInitialTraitState, createTestExecutor, createUnifiedLoader, extractBindings, findInitialState, findTransition, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isNamespacedEvent, normalizeEventKey, parseNamespacedEvent, preprocessSchema, processEvent };
|
|
2400
|
-
//# sourceMappingURL=chunk-
|
|
2401
|
-
//# sourceMappingURL=chunk-
|
|
2537
|
+
//# sourceMappingURL=chunk-QQIRPNHH.js.map
|
|
2538
|
+
//# sourceMappingURL=chunk-QQIRPNHH.js.map
|