@almadar/runtime 3.1.0 → 3.1.2

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.
@@ -164,6 +164,19 @@ interface ProcessEventOptions {
164
164
  declare function processEvent(options: ProcessEventOptions): TransitionResult;
165
165
  declare class StateMachineManager {
166
166
  private traits;
167
+ /**
168
+ * State map keyed by `${traitName}::${entityId | __singleton__}`.
169
+ *
170
+ * Each entity instance of an orbital gets its own copy of every
171
+ * trait's state machine. This is what enables N parallel subagents
172
+ * (one OrbitalProcess row per dispatched orbital) to all run their
173
+ * own Build/Validate/Fix cycle without colliding on shared trait
174
+ * state — the original cause of GAP-AGB-2.
175
+ *
176
+ * Initial state is created lazily on first event for each scope, so
177
+ * adding a trait does not pre-allocate state for every potential
178
+ * entity (and there's no need to know entity ids up front).
179
+ */
167
180
  private states;
168
181
  private config;
169
182
  private observer?;
@@ -184,18 +197,35 @@ declare class StateMachineManager {
184
197
  * Remove a trait from the manager.
185
198
  */
186
199
  removeTrait(traitName: string): void;
200
+ /**
201
+ * Get-or-init the state row for a (trait, entityId) pair.
202
+ * Returns undefined if the trait isn't registered.
203
+ */
204
+ private getOrInitState;
187
205
  /**
188
206
  * Get current state for a trait.
207
+ *
208
+ * For single-entity orbitals, omit `entityId` — returns the singleton
209
+ * scope. For multi-entity orbitals (e.g. agent OrbitalSubagent), pass
210
+ * the entity row id to look up that specific instance's state.
189
211
  */
190
- getState(traitName: string): TraitState | undefined;
212
+ getState(traitName: string, entityId?: string): TraitState | undefined;
191
213
  /**
192
- * Get all current states.
214
+ * Get a flat traitName→state map. For multi-entity orbitals this
215
+ * returns one entry per trait collapsed onto the singleton scope (or
216
+ * the first observed scope if singleton is empty). Use
217
+ * `getAllStatesByScope()` to get the full per-entity view.
193
218
  */
194
219
  getAllStates(): Map<string, TraitState>;
220
+ /**
221
+ * Get every per-entity state row, grouped by trait. Useful for
222
+ * inspecting parallel subagent state.
223
+ */
224
+ getAllStatesByScope(): Map<string, Map<string, TraitState>>;
195
225
  /**
196
226
  * Check if a trait can handle an event from its current state.
197
227
  */
198
- canHandleEvent(traitName: string, eventKey: string): boolean;
228
+ canHandleEvent(traitName: string, eventKey: string, entityId?: string): boolean;
199
229
  /**
200
230
  * Send an event to all traits.
201
231
  *
@@ -214,31 +244,28 @@ declare class StateMachineManager {
214
244
  */
215
245
  enqueueEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow): void;
216
246
  /**
217
- * Drain a single trait's event queue, processing events sequentially.
218
- *
219
- * This is the core actor loop: each event is fully processed (including
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
247
+ * Drain a single (trait, entity) pair's event queue, processing
248
+ * events sequentially. Pass `entityId` to drain a specific entity
249
+ * instance; omit it to drain the singleton scope.
226
250
  */
227
- drainQueue(traitName: string, executeEffects: (traitName: string, result: TransitionResult, payload?: EventPayload) => Promise<void>): Promise<void>;
251
+ drainQueue(traitName: string, executeEffects: (traitName: string, result: TransitionResult, payload?: EventPayload) => Promise<void>, entityId?: string): Promise<void>;
228
252
  /**
229
253
  * Check whether a trait's queue is currently being drained.
230
254
  */
231
- isProcessing(traitName: string): boolean;
255
+ isProcessing(traitName: string, entityId?: string): boolean;
232
256
  /**
233
257
  * Get the number of pending events in a trait's queue.
234
258
  */
235
- getQueueLength(traitName: string): number;
259
+ getQueueLength(traitName: string, entityId?: string): number;
236
260
  /**
237
261
  * Reset a trait to its initial state.
262
+ *
263
+ * If `entityId` is provided, resets only that entity's scope.
264
+ * Otherwise resets every entity scope known for the trait.
238
265
  */
239
- resetTrait(traitName: string): void;
266
+ resetTrait(traitName: string, entityId?: string): void;
240
267
  /**
241
- * Reset all traits to initial states.
268
+ * Reset all traits to initial states (every entity scope).
242
269
  */
243
270
  resetAll(): void;
244
271
  }
@@ -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-QXgOGiS8.js';
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-DrZB9ksb.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-HIM4HJAN.js';
1
+ import { EventBus, createUnifiedLoader, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-KCXJNXQZ.js';
2
2
  import './chunk-PZ5AY32C.js';
3
3
  import { Router } from 'express';
4
4
  import * as fs from 'fs';
@@ -943,7 +943,10 @@ var OrbitalServerRuntime = class {
943
943
  }
944
944
  }
945
945
  }
946
- const forwardedEntityId = event.payload?.entityId ?? event.payload?.orbitalName;
946
+ const raw = event.payload;
947
+ const mapped = mappedPayload;
948
+ const pickId = (field) => mapped?.[field] ?? raw?.[field];
949
+ const forwardedEntityId = pickId("entityId") ?? pickId("orbitalName");
947
950
  await this.processOrbitalEvent(orbitalName, {
948
951
  event: listener.triggers,
949
952
  payload: mappedPayload,