effect-machine 0.12.0 → 0.14.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.
Files changed (53) hide show
  1. package/README.md +133 -324
  2. package/dist/actor.d.ts +46 -28
  3. package/dist/actor.js +276 -315
  4. package/dist/cluster/entity-machine.d.ts +1 -1
  5. package/dist/cluster/entity-machine.js +20 -9
  6. package/dist/cluster/to-entity.d.ts +3 -3
  7. package/dist/errors.d.ts +24 -20
  8. package/dist/errors.js +10 -6
  9. package/dist/index.d.ts +5 -4
  10. package/dist/index.js +3 -2
  11. package/dist/internal/runtime.d.ts +82 -7
  12. package/dist/internal/runtime.js +162 -58
  13. package/dist/internal/transition.d.ts +12 -11
  14. package/dist/internal/transition.js +12 -14
  15. package/dist/machine.d.ts +148 -140
  16. package/dist/machine.js +141 -155
  17. package/dist/schema.d.ts +14 -0
  18. package/dist/schema.js +10 -1
  19. package/dist/slot.d.ts +112 -86
  20. package/dist/slot.js +92 -59
  21. package/dist/supervision.d.ts +97 -0
  22. package/dist/supervision.js +42 -0
  23. package/dist/testing.d.ts +21 -12
  24. package/dist/testing.js +23 -26
  25. package/package.json +7 -7
  26. package/v3/dist/actor.d.ts +53 -30
  27. package/v3/dist/actor.js +286 -311
  28. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  29. package/v3/dist/cluster/entity-machine.js +5 -5
  30. package/v3/dist/cluster/to-entity.d.ts +1 -1
  31. package/v3/dist/errors.d.ts +14 -10
  32. package/v3/dist/errors.js +11 -7
  33. package/v3/dist/index.d.ts +6 -5
  34. package/v3/dist/index.js +3 -2
  35. package/v3/dist/inspection.d.ts +3 -22
  36. package/v3/dist/inspection.js +1 -15
  37. package/v3/dist/internal/brands.d.ts +4 -8
  38. package/v3/dist/internal/inspection.js +1 -1
  39. package/v3/dist/internal/runtime.d.ts +87 -10
  40. package/v3/dist/internal/runtime.js +177 -61
  41. package/v3/dist/internal/transition.d.ts +13 -12
  42. package/v3/dist/internal/transition.js +14 -16
  43. package/v3/dist/internal/utils.js +5 -1
  44. package/v3/dist/machine.d.ts +158 -143
  45. package/v3/dist/machine.js +148 -155
  46. package/v3/dist/schema.d.ts +25 -11
  47. package/v3/dist/schema.js +18 -5
  48. package/v3/dist/slot.d.ts +112 -86
  49. package/v3/dist/slot.js +92 -59
  50. package/v3/dist/supervision.d.ts +97 -0
  51. package/v3/dist/supervision.js +42 -0
  52. package/v3/dist/testing.d.ts +21 -12
  53. package/v3/dist/testing.js +23 -24
@@ -68,7 +68,7 @@ declare const EntityMachine: {
68
68
  readonly _tag: string;
69
69
  }, E extends {
70
70
  readonly _tag: string;
71
- }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
71
+ }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
72
72
  };
73
73
  //#endregion
74
74
  export { EntityMachine, EntityMachineOptions };
@@ -1,7 +1,7 @@
1
1
  import { stubSystem } from "../internal/utils.js";
2
- import { BuiltMachine, replay } from "../machine.js";
3
- import { ActorSystem } from "../actor.js";
2
+ import { replay } from "../machine.js";
4
3
  import { createRuntime } from "../internal/runtime.js";
4
+ import { ActorSystem } from "../actor.js";
5
5
  import { PersistenceAdapter } from "./persistence.js";
6
6
  import { Effect, Option, Ref } from "effect";
7
7
  import { Entity } from "@effect/cluster";
@@ -47,7 +47,8 @@ const EntityMachine = { layer: (entity, machine, options) => {
47
47
  const versionRef = yield* Ref.make(persistCtx.initialVersion);
48
48
  const runtime = yield* createRuntime(machineWithState, system, {
49
49
  actorId: entityId,
50
- hooks: options?.hooks
50
+ hooks: options?.hooks,
51
+ childIdPrefix: `${entityId}/`
51
52
  });
52
53
  if (persistCtx.adapter !== void 0) {
53
54
  const { adapter: pAdapter, key } = persistCtx;
@@ -110,8 +111,7 @@ const hydratePersistence = (persistence, entityDef, entityId, machine, initializ
110
111
  const snapshotVersion = Option.isSome(maybeSnapshot) ? maybeSnapshot.value.version : 0;
111
112
  const events = yield* adapter.loadEvents(key, snapshotVersion);
112
113
  if (events.length > 0) {
113
- const eventValues = events.map((e) => e.event);
114
- const hydratedState = yield* replay(new BuiltMachine(machine), eventValues, { from: baseState });
114
+ const hydratedState = yield* replay(machine, events.map((e) => e.event), { from: baseState });
115
115
  const lastEvent = events[events.length - 1];
116
116
  return {
117
117
  adapter,
@@ -59,6 +59,6 @@ declare const toEntity: <S extends {
59
59
  readonly _tag: string;
60
60
  }, E extends {
61
61
  readonly _tag: string;
62
- }, R>(machine: Machine<S, E, R, any, any, any, any>, options: ToEntityOptions) => any;
62
+ }, R>(machine: Machine<S, E, R, any, any, any>, options: ToEntityOptions) => any;
63
63
  //#endregion
64
64
  export { EntityRpcs, ToEntityOptions, toEntity };
@@ -8,13 +8,6 @@ declare const DuplicateActorError_base: Schema.TaggedErrorClass<DuplicateActorEr
8
8
  }>;
9
9
  /** Attempted to spawn/restore actor with ID already in use */
10
10
  declare class DuplicateActorError extends DuplicateActorError_base {}
11
- declare const UnprovidedSlotsError_base: Schema.TaggedErrorClass<UnprovidedSlotsError, "UnprovidedSlotsError", {
12
- readonly _tag: Schema.tag<"UnprovidedSlotsError">;
13
- } & {
14
- slots: Schema.Array$<typeof Schema.String>;
15
- }>;
16
- /** Machine has unprovided effect slots */
17
- declare class UnprovidedSlotsError extends UnprovidedSlotsError_base {}
18
11
  declare const MissingSchemaError_base: Schema.TaggedErrorClass<MissingSchemaError, "MissingSchemaError", {
19
12
  readonly _tag: Schema.tag<"MissingSchemaError">;
20
13
  } & {
@@ -24,6 +17,8 @@ declare const MissingSchemaError_base: Schema.TaggedErrorClass<MissingSchemaErro
24
17
  declare class MissingSchemaError extends MissingSchemaError_base {}
25
18
  declare const InvalidSchemaError_base: Schema.TaggedErrorClass<InvalidSchemaError, "InvalidSchemaError", {
26
19
  readonly _tag: Schema.tag<"InvalidSchemaError">;
20
+ } & {
21
+ message: typeof Schema.String;
27
22
  }>;
28
23
  /** State/Event schema has no variants */
29
24
  declare class InvalidSchemaError extends InvalidSchemaError_base {}
@@ -38,7 +33,7 @@ declare const SlotProvisionError_base: Schema.TaggedErrorClass<SlotProvisionErro
38
33
  readonly _tag: Schema.tag<"SlotProvisionError">;
39
34
  } & {
40
35
  slotName: typeof Schema.String;
41
- slotType: Schema.Literal<["guard", "effect"]>;
36
+ slotType: Schema.Literal<["slot"]>;
42
37
  }>;
43
38
  /** Slot handler not found at runtime (internal error) */
44
39
  declare class SlotProvisionError extends SlotProvisionError_base {}
@@ -48,7 +43,7 @@ declare const ProvisionValidationError_base: Schema.TaggedErrorClass<ProvisionVa
48
43
  missing: Schema.Array$<typeof Schema.String>;
49
44
  extra: Schema.Array$<typeof Schema.String>;
50
45
  }>;
51
- /** Machine.build() validation failed - missing or extra handlers */
46
+ /** Slot provision validation failed missing or extra handlers */
52
47
  declare class ProvisionValidationError extends ProvisionValidationError_base {}
53
48
  declare const AssertionError_base: Schema.TaggedErrorClass<AssertionError, "AssertionError", {
54
49
  readonly _tag: Schema.tag<"AssertionError">;
@@ -79,6 +74,15 @@ declare const PersistenceError_base: Schema.TaggedErrorClass<PersistenceError, "
79
74
  }>;
80
75
  /** Persistence adapter operation failed */
81
76
  declare class PersistenceError extends PersistenceError_base {}
77
+ declare const SlotCodecError_base: Schema.TaggedErrorClass<SlotCodecError, "SlotCodecError", {
78
+ readonly _tag: Schema.tag<"SlotCodecError">;
79
+ } & {
80
+ slotName: typeof Schema.String;
81
+ phase: Schema.Literal<["input", "output"]>;
82
+ message: typeof Schema.String;
83
+ }>;
84
+ /** Slot input/output schema validation failed */
85
+ declare class SlotCodecError extends SlotCodecError_base {}
82
86
  declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflictError, "VersionConflictError", {
83
87
  readonly _tag: Schema.tag<"VersionConflictError">;
84
88
  } & {
@@ -88,4 +92,4 @@ declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflict
88
92
  /** Optimistic locking failure — stored version doesn't match expected */
89
93
  declare class VersionConflictError extends VersionConflictError_base {}
90
94
  //#endregion
91
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError, VersionConflictError };
95
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
package/v3/dist/errors.js CHANGED
@@ -3,7 +3,7 @@ import { Schema } from "effect";
3
3
  /**
4
4
  * Typed error classes for effect-machine.
5
5
  *
6
- * All errors extend Schema.TaggedError for:
6
+ * All errors extend Schema.TaggedErrorClass for:
7
7
  * - Type-safe catching via Effect.catchTag
8
8
  * - Serialization support
9
9
  * - Composable error handling
@@ -12,20 +12,18 @@ import { Schema } from "effect";
12
12
  */
13
13
  /** Attempted to spawn/restore actor with ID already in use */
14
14
  var DuplicateActorError = class extends Schema.TaggedError()("DuplicateActorError", { actorId: Schema.String }) {};
15
- /** Machine has unprovided effect slots */
16
- var UnprovidedSlotsError = class extends Schema.TaggedError()("UnprovidedSlotsError", { slots: Schema.Array(Schema.String) }) {};
17
15
  /** Operation requires schemas attached to machine */
18
16
  var MissingSchemaError = class extends Schema.TaggedError()("MissingSchemaError", { operation: Schema.String }) {};
19
17
  /** State/Event schema has no variants */
20
- var InvalidSchemaError = class extends Schema.TaggedError()("InvalidSchemaError", {}) {};
18
+ var InvalidSchemaError = class extends Schema.TaggedError()("InvalidSchemaError", { message: Schema.String }) {};
21
19
  /** $match called with missing handler for tag */
22
20
  var MissingMatchHandlerError = class extends Schema.TaggedError()("MissingMatchHandlerError", { tag: Schema.String }) {};
23
21
  /** Slot handler not found at runtime (internal error) */
24
22
  var SlotProvisionError = class extends Schema.TaggedError()("SlotProvisionError", {
25
23
  slotName: Schema.String,
26
- slotType: Schema.Literal("guard", "effect")
24
+ slotType: Schema.Literal("slot")
27
25
  }) {};
28
- /** Machine.build() validation failed - missing or extra handlers */
26
+ /** Slot provision validation failed missing or extra handlers */
29
27
  var ProvisionValidationError = class extends Schema.TaggedError()("ProvisionValidationError", {
30
28
  missing: Schema.Array(Schema.String),
31
29
  extra: Schema.Array(Schema.String)
@@ -41,10 +39,16 @@ var NoReplyError = class extends Schema.TaggedError()("NoReplyError", {
41
39
  }) {};
42
40
  /** Persistence adapter operation failed */
43
41
  var PersistenceError = class extends Schema.TaggedError()("PersistenceError", { message: Schema.String }) {};
42
+ /** Slot input/output schema validation failed */
43
+ var SlotCodecError = class extends Schema.TaggedError()("SlotCodecError", {
44
+ slotName: Schema.String,
45
+ phase: Schema.Literal("input", "output"),
46
+ message: Schema.String
47
+ }) {};
44
48
  /** Optimistic locking failure — stored version doesn't match expected */
45
49
  var VersionConflictError = class extends Schema.TaggedError()("VersionConflictError", {
46
50
  expected: Schema.Number,
47
51
  actual: Schema.Number
48
52
  }) {};
49
53
  //#endregion
50
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError, VersionConflictError };
54
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
@@ -1,10 +1,11 @@
1
- import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
2
- import { ReplyResult } from "./internal/utils.js";
1
+ import { DeferReplyResult, ReplyResult } from "./internal/utils.js";
3
2
  import { Event, MachineEventSchema, MachineStateSchema, ReplyFields, State } from "./schema.js";
4
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
3
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
4
+ import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema } from "./slot.js";
5
+ import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
5
6
  import { ProcessEventResult } from "./internal/transition.js";
6
- import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
7
+ import { BackgroundEffect, HandlerContext, Machine, MachineRef, MakeConfig, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
7
8
  import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
8
9
  import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
9
10
  import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
10
- export { type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type BuiltMachine, DuplicateActorError, type EffectEvent, type EffectSlots, type EffectsDef, type EffectsSchema, type ErrorEvent, Event, type EventReceivedEvent, type GuardHandlers, type GuardSlot, type GuardSlots, type GuardsDef, type GuardsSchema, type HandlerContext, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, type ProcessEventResult, type ProvideHandlers, ProvisionValidationError, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
11
+ export { ActorExit, type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, type DeferReplyResult, DuplicateActorError, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, type ProcessEventResult, type ProvideSlots, ProvisionValidationError, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type SlotCall, type SlotCalls, SlotCodecError, type SlotFnDef, type SlotHandler, type SlotInvocation, SlotProvisionError, type SlotRequest, type SlotResult, type SlotsDef, type SlotsSchema, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
package/v3/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
1
2
  import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
2
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
3
3
  import { Slot } from "./slot.js";
4
4
  import { machine_exports } from "./machine.js";
5
+ import { ActorExit, Supervision } from "./supervision.js";
5
6
  import { ActorSystem, Default } from "./actor.js";
6
7
  import { Event, State } from "./schema.js";
7
8
  import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
8
- export { ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, Slot, SlotProvisionError, State, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
9
+ export { ActorExit, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotCodecError, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
@@ -4,7 +4,7 @@ import { Context, Effect, Schema } from "effect";
4
4
  /**
5
5
  * Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.
6
6
  */
7
- type ResolveType<T> = T extends Schema.Schema<infer A, infer _I, infer _R> ? A : T;
7
+ type ResolveType<T> = T extends Schema.Schema<infer A> ? A : T;
8
8
  /**
9
9
  * Event emitted when an actor is spawned
10
10
  */
@@ -45,9 +45,6 @@ interface EffectEvent<S> {
45
45
  readonly state: S;
46
46
  readonly timestamp: number;
47
47
  }
48
- /**
49
- * Event emitted when a task lifecycle phase occurs
50
- */
51
48
  interface TaskEvent<S> {
52
49
  readonly type: "@machine.task";
53
50
  readonly actorId: string;
@@ -93,13 +90,10 @@ type AnyInspectionEvent = InspectionEvent<{
93
90
  }, {
94
91
  readonly _tag: string;
95
92
  }>;
96
- /**
97
- * Inspector handler — sync callback or Effect-returning callback.
98
- */
99
- type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
100
93
  /**
101
94
  * Inspector interface for observing machine behavior
102
95
  */
96
+ type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
103
97
  interface Inspector<S, E> {
104
98
  readonly onInspect: InspectorHandler<S, E>;
105
99
  }
@@ -109,7 +103,7 @@ interface Inspector<S, E> {
109
103
  */
110
104
  declare const Inspector: Context.Tag<Inspector<any, any>, Inspector<any, any>>;
111
105
  /**
112
- * Create an inspector from a sync callback function.
106
+ * Create an inspector from a callback function.
113
107
  *
114
108
  * Type params accept either raw tagged types or Schema constructors:
115
109
  * - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
@@ -121,30 +115,17 @@ declare const makeInspector: <S = {
121
115
  }, E = {
122
116
  readonly _tag: string;
123
117
  }>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
124
- /**
125
- * Create an inspector from an Effect-returning callback function.
126
- */
127
118
  declare const makeInspectorEffect: <S = {
128
119
  readonly _tag: string;
129
120
  }, E = {
130
121
  readonly _tag: string;
131
122
  }>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void, never, never>) => Inspector<ResolveType<S>, ResolveType<E>>;
132
- /**
133
- * Combine multiple inspectors into one. All run concurrently per event.
134
- * Individual inspector failures are swallowed.
135
- */
136
123
  declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
137
- /**
138
- * Options for the tracing inspector.
139
- */
140
124
  interface TracingInspectorOptions<S, E> {
141
125
  readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
142
126
  readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
143
127
  readonly eventName?: (event: InspectionEvent<S, E>) => string;
144
128
  }
145
- /**
146
- * Inspector that emits OpenTelemetry spans and events for each inspection event.
147
- */
148
129
  declare const tracingInspector: <S extends {
149
130
  readonly _tag: string;
150
131
  }, E extends {
@@ -6,7 +6,7 @@ import { Context, Effect, Option } from "effect";
6
6
  */
7
7
  const Inspector = Context.GenericTag("@effect/machine/Inspector");
8
8
  /**
9
- * Create an inspector from a sync callback function.
9
+ * Create an inspector from a callback function.
10
10
  *
11
11
  * Type params accept either raw tagged types or Schema constructors:
12
12
  * - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
@@ -14,22 +14,11 @@ const Inspector = Context.GenericTag("@effect/machine/Inspector");
14
14
  * - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
15
15
  */
16
16
  const makeInspector = (onInspect) => ({ onInspect });
17
- /**
18
- * Create an inspector from an Effect-returning callback function.
19
- */
20
17
  const makeInspectorEffect = (onInspect) => ({ onInspect });
21
- /**
22
- * Run an inspector handler, handling both sync and Effect returns.
23
- * @internal
24
- */
25
18
  const inspectionEffect = (inspector, event) => {
26
19
  const result = inspector.onInspect(event);
27
20
  return Effect.isEffect(result) ? result : Effect.void;
28
21
  };
29
- /**
30
- * Combine multiple inspectors into one. All run concurrently per event.
31
- * Individual inspector failures are swallowed.
32
- */
33
22
  const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
34
23
  concurrency: "unbounded",
35
24
  discard: true
@@ -99,9 +88,6 @@ const inspectionAttributes = (event) => {
99
88
  };
100
89
  }
101
90
  };
102
- /**
103
- * Inspector that emits OpenTelemetry spans and events for each inspection event.
104
- */
105
91
  const tracingInspector = (options) => ({ onInspect: (event) => {
106
92
  const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
107
93
  const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
@@ -1,10 +1,8 @@
1
1
  import { Brand } from "effect";
2
2
 
3
3
  //#region src/internal/brands.d.ts
4
- declare const StateTypeId: unique symbol;
5
- declare const EventTypeId: unique symbol;
6
- type StateTypeId = typeof StateTypeId;
7
- type EventTypeId = typeof EventTypeId;
4
+ type StateTypeId = "effect-machine/StateTypeId";
5
+ type EventTypeId = "effect-machine/EventTypeId";
8
6
  interface StateBrand extends Brand.Brand<StateTypeId> {}
9
7
  interface EventBrand extends Brand.Brand<EventTypeId> {}
10
8
  type BrandedState = {
@@ -13,8 +11,7 @@ type BrandedState = {
13
11
  type BrandedEvent = {
14
12
  readonly _tag: string;
15
13
  } & EventBrand;
16
- declare const SchemaIdTypeId: unique symbol;
17
- type SchemaIdTypeId = typeof SchemaIdTypeId;
14
+ type SchemaIdTypeId = "effect-machine/SchemaIdTypeId";
18
15
  /**
19
16
  * Brand that captures the schema definition type D.
20
17
  * Two schemas with identical definition shapes will have compatible brands.
@@ -33,8 +30,7 @@ type FullEventBrand<D extends Record<string, unknown>> = EventBrand & SchemaIdBr
33
30
  * Brand that carries the reply type for an event variant.
34
31
  * Present only on events defined with Event.reply().
35
32
  */
36
- declare const ReplyTypeId: unique symbol;
37
- type ReplyTypeId = typeof ReplyTypeId;
33
+ type ReplyTypeId = "effect-machine/ReplyTypeId";
38
34
  interface ReplyTypeBrand<R> extends Brand.Brand<ReplyTypeId> {
39
35
  readonly _ReplyType: R;
40
36
  }
@@ -14,7 +14,7 @@ const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function
14
14
  return;
15
15
  }
16
16
  });
17
- if (result !== void 0 && Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
17
+ if (Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
18
18
  });
19
19
  //#endregion
20
20
  export { emitWithTimestamp };
@@ -1,9 +1,10 @@
1
- import { EffectsDef, GuardsDef, MachineContext } from "../slot.js";
2
1
  import { NoReplyError } from "../errors.js";
3
- import { ProcessEventHooks } from "./transition.js";
2
+ import { MachineContext, SlotsDef } from "../slot.js";
3
+ import { ActorExit } from "../supervision.js";
4
+ import { ProcessEventHooks, ProcessEventResult } from "./transition.js";
4
5
  import { Machine, MachineRef } from "../machine.js";
5
6
  import { ActorSystem } from "../actor.js";
6
- import { Deferred, Effect, Queue, Scope } from "effect";
7
+ import { Deferred, Effect, Queue, Ref, Scope, SubscriptionRef } from "effect";
7
8
 
8
9
  //#region src/internal/runtime.d.ts
9
10
  /** @internal */
@@ -13,46 +14,122 @@ type RuntimeQueuedEvent<E> = {
13
14
  } | {
14
15
  readonly _tag: "sendWait";
15
16
  readonly event: E;
16
- readonly done: Deferred.Deferred<void>;
17
+ readonly done: Deferred.Deferred<void, unknown>;
18
+ } | {
19
+ readonly _tag: "call";
20
+ readonly event: E;
21
+ readonly reply: Deferred.Deferred<ProcessEventResult<{
22
+ readonly _tag: string;
23
+ }>, unknown>;
17
24
  } | {
18
25
  readonly _tag: "ask";
19
26
  readonly event: E;
20
27
  readonly reply: Deferred.Deferred<unknown, NoReplyError>;
28
+ } | {
29
+ readonly _tag: "drain";
30
+ readonly done: Deferred.Deferred<void, never>;
21
31
  };
32
+ /**
33
+ * Resources owned by the actor cell (stable across generations).
34
+ * When provided, createRuntime uses these instead of allocating its own.
35
+ * @internal
36
+ */
37
+ interface RuntimeCellResources<S, E> {
38
+ readonly stateRef: SubscriptionRef.SubscriptionRef<S>;
39
+ readonly eventQueue: Queue.Queue<RuntimeQueuedEvent<E>>;
40
+ readonly stoppedRef: Ref.Ref<boolean>;
41
+ }
22
42
  /** @internal */
23
43
  interface RuntimeHandle<S, E> {
24
44
  /** Enqueue a fire-and-forget event */
25
45
  readonly send: (event: E) => Effect.Effect<void>;
26
- /** Enqueue event and wait for processing to complete (for RPC Send) */
27
- readonly sendWait: (event: E) => Effect.Effect<void>;
46
+ /** Enqueue event and wait for processing to complete (for RPC Send). Fails on defect. */
47
+ readonly sendWait: (event: E) => Effect.Effect<void, unknown>;
28
48
  /** Enqueue an ask event, returns the reply value */
29
49
  readonly ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
30
50
  /** Get current state */
31
51
  readonly getState: Effect.Effect<S>;
52
+ /** SubscriptionRef for state observation (WatchState streaming) */
53
+ readonly stateRef: SubscriptionRef.SubscriptionRef<S>;
32
54
  /** Whether the runtime has stopped (final state reached) */
33
55
  readonly isStopped: Effect.Effect<boolean>;
34
56
  /** Stop the runtime (interrupt event loop, clean up) */
35
57
  readonly stop: Effect.Effect<void>;
58
+ /** @internal — raw event queue for direct enqueue (actor.ts uses this for pendingReplies tracking) */
59
+ readonly _queue: Queue.Queue<RuntimeQueuedEvent<E>>;
60
+ /** @internal — stopped ref for direct access */
61
+ readonly _stoppedRef: Ref.Ref<boolean>;
62
+ /**
63
+ * Exit deferred — set exactly once with the exit reason when the runtime stops.
64
+ * Final state → ActorExit.Final, explicit stop → ActorExit.Stopped, defect → ActorExit.Defect.
65
+ */
66
+ readonly exitDeferred: Deferred.Deferred<ActorExit<S>, never>;
67
+ /**
68
+ * Actor scope — owns background fibers for this generation.
69
+ * Closing this scope interrupts all background fibers.
70
+ */
71
+ readonly actorScope: Scope.CloseableScope;
72
+ }
73
+ /** @internal */
74
+ interface RuntimeLifecycleHooks<S, E> {
75
+ /** Before processEventCore — actor emits @machine.event inspection */
76
+ readonly onEvent?: (state: S, event: E) => Effect.Effect<void>;
77
+ /** After SubscriptionRef.set on transition — actor notifies listeners, annotates spans */
78
+ readonly onStateChange?: (result: ProcessEventResult<S>, event: E) => Effect.Effect<void>;
79
+ /** After reply settlement when transition occurred — actor publishes to transitionsPubSub */
80
+ readonly onProcessed?: (result: ProcessEventResult<S>, event: E) => Effect.Effect<void>;
81
+ /** When final state detected in event loop — actor emits @machine.stop */
82
+ readonly onFinal?: (state: S) => Effect.Effect<void>;
83
+ /** Before stop resource cleanup — actor emits @machine.stop, settles pending replies */
84
+ readonly onShutdown?: () => Effect.Effect<void>;
85
+ /** Before initial spawn effects — actor emits @machine.effect inspection */
86
+ readonly onInitialSpawnEffects?: (state: S) => Effect.Effect<void>;
36
87
  }
37
88
  /** @internal */
38
89
  interface RuntimeConfig<S, E> {
39
90
  readonly actorId: string;
40
91
  readonly hooks?: ProcessEventHooks<S, E>;
92
+ /**
93
+ * Cell-owned resources. When provided, the runtime uses the cell's stateRef,
94
+ * eventQueue, and stoppedRef instead of creating its own.
95
+ * Used by actor.ts for supervision (cell owns stable resources across generations).
96
+ */
97
+ readonly cellResources?: RuntimeCellResources<S, E>;
41
98
  /**
42
99
  * Custom queue factory. Default: `Queue.unbounded()`.
43
100
  * Use `Queue.sliding(n)` or `Queue.dropping(n)` for bounded queues.
101
+ * Ignored when cellResources is provided.
44
102
  */
45
103
  readonly queueFactory?: Effect.Effect<Queue.Queue<RuntimeQueuedEvent<E>>>;
104
+ /** Lifecycle callbacks for actor-specific concerns */
105
+ readonly lifecycle?: RuntimeLifecycleHooks<S, E>;
106
+ /** Wrap each processQueued invocation — actor uses for span annotations */
107
+ readonly wrapProcess?: (state: S, event: E, inner: Effect.Effect<ProcessQueuedResult<S>>) => Effect.Effect<ProcessQueuedResult<S>>;
108
+ /** Called after self.spawn succeeds — actor tracks children */
109
+ readonly onChildSpawned?: (childId: string, child: unknown) => Effect.Effect<void>;
110
+ /** Skip registering stop as scope finalizer — actor manages its own lifecycle */
111
+ readonly skipFinalizer?: boolean;
112
+ /** Prefix for child actor IDs in self.spawn. Entity-machine uses `${actorId}/`. Default: no prefix. */
113
+ readonly childIdPrefix?: string;
114
+ }
115
+ /** @internal */
116
+ interface ProcessQueuedResult<S> {
117
+ readonly shouldStop: boolean;
118
+ readonly stateChanged: boolean;
119
+ readonly result: ProcessEventResult<S>;
46
120
  }
47
121
  /**
48
122
  * Create a runtime for a machine. Returns a handle for sending events
49
123
  * and querying state. The runtime owns:
50
- * - Single event queue (all events serialized)
51
124
  * - Event loop fiber
52
125
  * - Postpone buffer
53
- * - Background effects
126
+ * - Background effects (under actorScope)
54
127
  * - State scope (spawn effects)
55
128
  * - Final state detection
129
+ * - Exit reason via exitDeferred
130
+ *
131
+ * Resources (stateRef, eventQueue, stoppedRef) are either cell-provided
132
+ * or allocated fresh by the runtime.
56
133
  *
57
134
  * @internal
58
135
  */
@@ -60,6 +137,6 @@ declare const createRuntime: <S extends {
60
137
  readonly _tag: string;
61
138
  }, E extends {
62
139
  readonly _tag: string;
63
- }, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, any, any, GD, EFD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<RuntimeHandle<S, E>, never, Scope.Scope | Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
140
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<RuntimeHandle<S, E>, never, Scope.Scope | Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
64
141
  //#endregion
65
- export { RuntimeConfig, RuntimeHandle, RuntimeQueuedEvent, createRuntime };
142
+ export { ProcessQueuedResult, RuntimeCellResources, RuntimeConfig, RuntimeHandle, RuntimeLifecycleHooks, RuntimeQueuedEvent, createRuntime };