@typeonce/effect-machine 0.9.0 → 0.10.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 (92) hide show
  1. package/README.md +128 -28
  2. package/dist/Machine.d.ts +334 -238
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +45 -76
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts +6 -2
  7. package/dist/internal/machine/atom.d.ts.map +1 -1
  8. package/dist/internal/machine/atom.js +5 -0
  9. package/dist/internal/machine/atom.js.map +1 -1
  10. package/dist/internal/machine/cluster.d.ts.map +1 -1
  11. package/dist/internal/machine/cluster.js +2 -1
  12. package/dist/internal/machine/cluster.js.map +1 -1
  13. package/dist/internal/machine/command.js +2 -2
  14. package/dist/internal/machine/command.js.map +1 -1
  15. package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
  16. package/dist/internal/machine/commandRuntime.js +6 -3
  17. package/dist/internal/machine/commandRuntime.js.map +1 -1
  18. package/dist/internal/machine/configuration.d.ts +8 -1
  19. package/dist/internal/machine/configuration.d.ts.map +1 -1
  20. package/dist/internal/machine/configuration.js +9 -4
  21. package/dist/internal/machine/configuration.js.map +1 -1
  22. package/dist/internal/machine/errors.d.ts +1 -1
  23. package/dist/internal/machine/errors.d.ts.map +1 -1
  24. package/dist/internal/machine/executionPlan.d.ts +3 -3
  25. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  26. package/dist/internal/machine/executionPlan.js +50 -25
  27. package/dist/internal/machine/executionPlan.js.map +1 -1
  28. package/dist/internal/machine/invocation.d.ts.map +1 -1
  29. package/dist/internal/machine/invocation.js +3 -2
  30. package/dist/internal/machine/invocation.js.map +1 -1
  31. package/dist/internal/machine/machine.d.ts +14 -19
  32. package/dist/internal/machine/machine.d.ts.map +1 -1
  33. package/dist/internal/machine/machine.js +12 -10
  34. package/dist/internal/machine/machine.js.map +1 -1
  35. package/dist/internal/machine/planner.d.ts +2 -1
  36. package/dist/internal/machine/planner.d.ts.map +1 -1
  37. package/dist/internal/machine/planner.js +61 -24
  38. package/dist/internal/machine/planner.js.map +1 -1
  39. package/dist/internal/machine/process.d.ts.map +1 -1
  40. package/dist/internal/machine/process.js +8 -8
  41. package/dist/internal/machine/process.js.map +1 -1
  42. package/dist/internal/machine/protocol.d.ts +7 -13
  43. package/dist/internal/machine/protocol.d.ts.map +1 -1
  44. package/dist/internal/machine/protocol.js +128 -50
  45. package/dist/internal/machine/protocol.js.map +1 -1
  46. package/dist/internal/machine/runtime.d.ts +8 -2
  47. package/dist/internal/machine/runtime.d.ts.map +1 -1
  48. package/dist/internal/machine/runtime.js +86 -8
  49. package/dist/internal/machine/runtime.js.map +1 -1
  50. package/dist/internal/machine/topology.d.ts +7 -0
  51. package/dist/internal/machine/topology.d.ts.map +1 -1
  52. package/dist/internal/machine/topology.js +6 -0
  53. package/dist/internal/machine/topology.js.map +1 -1
  54. package/dist/internal/testing/machine/finiteModel.js +1 -1
  55. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  56. package/dist/internal/testing/machine/runtime.d.ts.map +1 -1
  57. package/dist/internal/testing/machine/runtime.js +2 -1
  58. package/dist/internal/testing/machine/runtime.js.map +1 -1
  59. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  60. package/dist/internal/testing/machine/verification.js +5 -3
  61. package/dist/internal/testing/machine/verification.js.map +1 -1
  62. package/dist/testing/MachineTest.d.ts +7 -7
  63. package/dist/testing/MachineTest.js +7 -7
  64. package/dist/unstable/cluster/ClusterMachine.d.ts +1 -1
  65. package/dist/unstable/cluster/ClusterMachine.js +1 -1
  66. package/dist/unstable/reactivity/AtomMachine.d.ts +25 -8
  67. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  68. package/dist/unstable/reactivity/AtomMachine.js +18 -3
  69. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  70. package/docs/agent-guide.md +143 -48
  71. package/package.json +1 -1
  72. package/src/Machine.ts +559 -307
  73. package/src/internal/machine/atom.ts +35 -10
  74. package/src/internal/machine/cluster.ts +2 -1
  75. package/src/internal/machine/command.ts +2 -2
  76. package/src/internal/machine/commandRuntime.ts +9 -4
  77. package/src/internal/machine/configuration.ts +23 -5
  78. package/src/internal/machine/errors.ts +1 -1
  79. package/src/internal/machine/executionPlan.ts +74 -29
  80. package/src/internal/machine/invocation.ts +3 -2
  81. package/src/internal/machine/machine.ts +68 -49
  82. package/src/internal/machine/planner.ts +68 -24
  83. package/src/internal/machine/process.ts +18 -8
  84. package/src/internal/machine/protocol.ts +207 -68
  85. package/src/internal/machine/runtime.ts +135 -9
  86. package/src/internal/machine/topology.ts +15 -0
  87. package/src/internal/testing/machine/finiteModel.ts +1 -1
  88. package/src/internal/testing/machine/runtime.ts +2 -1
  89. package/src/internal/testing/machine/verification.ts +5 -3
  90. package/src/testing/MachineTest.ts +7 -7
  91. package/src/unstable/cluster/ClusterMachine.ts +1 -1
  92. package/src/unstable/reactivity/AtomMachine.ts +42 -10
@@ -72,9 +72,9 @@ type MachineStartError<InitialE, E, InitialR, R, RuntimeError = never> =
72
72
  | Machine.StoppedError
73
73
  | RuntimeError
74
74
 
75
- const runMachineAtomEffect = <State, Event, Error, Output, StartError, Requirements>(
75
+ const runMachineAtomEffect = <State, Event, Error, Output, Emitted, StartError, Requirements>(
76
76
  get: Atom.AtomContext,
77
- start: Effect.Effect<Machine.MachineRef<State, Event, Error, Output>, StartError, Requirements>
77
+ start: Effect.Effect<Machine.MachineRef<State, Event, Error, Output, Emitted>, StartError, Requirements>
78
78
  ): Effect.Effect<never, StartError, Requirements> =>
79
79
  Effect.scoped(
80
80
  Effect.acquireRelease(start, (ref) => ref.stop).pipe(
@@ -96,7 +96,8 @@ const startMachineAtomEffect = <
96
96
  FinalStates extends Machine.Machine.StateIdentifier<States> = never,
97
97
  Output = never,
98
98
  OutputStates extends Machine.Machine.StateIdentifier<States> = never,
99
- InputEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = Events
99
+ InputEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = Events,
100
+ ParentEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = readonly []
100
101
  >(
101
102
  get: Atom.AtomContext,
102
103
  machine:
@@ -113,7 +114,8 @@ const startMachineAtomEffect = <
113
114
  Output,
114
115
  Emits,
115
116
  OutputStates,
116
- InputEvents
117
+ InputEvents,
118
+ ParentEvents
117
119
  >
118
120
  & EnsureExecutable<States, UnhandledStates, OutputStates>,
119
121
  args: [...Machine.Machine.InputArgs<Input>]
@@ -122,11 +124,12 @@ const startMachineAtomEffect = <
122
124
  Machine.Machine.Snapshot<States>,
123
125
  Machine.Machine.EventInputOf<InputEvents>,
124
126
  MachineRuntimeError<E, R>,
125
- Output
127
+ Output,
128
+ Machine.Machine.EmittedEventOf<Emits>
126
129
  >,
127
130
  MachineStartError<InitialE, E, InitialR, R>,
128
131
  MachineRequirements<InitialR, R, Machine.Machine.EventOf<Events>, Machine.Machine.EmitOf<Emits>>
129
- > => runMachineAtomEffect(get, internalMachine.start(machine, ...args))
132
+ > => runMachineAtomEffect(get, internalMachine.start(machine as any, ...args) as any)
130
133
 
131
134
  const resumeMachineAtomEffect = (
132
135
  get: Atom.AtomContext,
@@ -137,6 +140,24 @@ const resumeMachineAtomEffect = (
137
140
  type RefState<Ref> = Ref extends Machine.MachineRef<infer State, any, any, any> ? State : never
138
141
  type RefError<Ref> = Ref extends Machine.MachineRef<any, any, infer Error, any> ? Error : never
139
142
  type RefOutput<Ref> = Ref extends Machine.MachineRef<any, any, any, infer Output> ? Output : never
143
+ type RefEmitted<Ref> = Ref extends Machine.MachineRef<any, any, any, any, infer Emitted> ? Emitted : never
144
+
145
+ export const emissions = <State, Event, Error, Output, StartError, Emitted>(
146
+ self: MachineAtom<State, Event, Error, Output, StartError, Emitted>
147
+ ): Stream.Stream<Emitted, StartError, AtomRegistry.AtomRegistry> =>
148
+ Atom.toStreamResult(self.ref).pipe(Stream.flatMap((ref) => ref.emissions))
149
+
150
+ export const childEmissions = <Child extends Machine.ChildMachine.Any, StartError>(
151
+ self: ChildMachineAtom<Child, StartError>
152
+ ): Stream.Stream<RefEmitted<Machine.ChildMachine.Ref<Child>>, StartError, AtomRegistry.AtomRegistry> =>
153
+ Atom.toStreamResult(self.ref).pipe(
154
+ Stream.flatMap(
155
+ Option.match({
156
+ onNone: () => Stream.empty,
157
+ onSome: (ref) => ref.emissions
158
+ })
159
+ )
160
+ )
140
161
 
141
162
  const makeRuntimeResultAtom = <State, Error, Output, StartError>(
142
163
  snapshot: Atom.Atom<AsyncResult.AsyncResult<Machine.RuntimeSnapshot<State, Error, Output>, StartError>>
@@ -588,7 +609,8 @@ type ResumedMachineAtomOf<M extends Machine.Machine.Any, RuntimeError> = Machine
588
609
  Machine.Machine.EventInput<Machine.Machine.InputEvent<M>>,
589
610
  MachineRuntimeError<Machine.Machine.Error<M>, Machine.Machine.Services<M>>,
590
611
  Machine.Machine.Output<M>,
591
- Machine.MachineSchemaDecodeError | RuntimeError
612
+ Machine.MachineSchemaDecodeError | RuntimeError,
613
+ Machine.Machine.EmittedEvent<M>
592
614
  >
593
615
 
594
616
  export const make: {
@@ -605,7 +627,8 @@ export const make: {
605
627
  FinalStates extends Machine.Machine.StateIdentifier<States> = never,
606
628
  Output = never,
607
629
  OutputStates extends Machine.Machine.StateIdentifier<States> = never,
608
- InputEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = Events
630
+ InputEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = Events,
631
+ ParentEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = readonly []
609
632
  >(
610
633
  machine:
611
634
  & Machine.Machine<
@@ -621,7 +644,8 @@ export const make: {
621
644
  Output,
622
645
  Emits,
623
646
  OutputStates,
624
- InputEvents
647
+ InputEvents,
648
+ ParentEvents
625
649
  >
626
650
  & EnsureNoExternalRequirements<
627
651
  MachineRequirements<
@@ -638,7 +662,8 @@ export const make: {
638
662
  Machine.Machine.EventInputOf<InputEvents>,
639
663
  MachineRuntimeError<E, R>,
640
664
  Output,
641
- MachineStartError<InitialE, E, InitialR, R>
665
+ MachineStartError<InitialE, E, InitialR, R>,
666
+ Machine.Machine.EmittedEventOf<Emits>
642
667
  >
643
668
  } = ((machine: Machine.Machine.Any, ...args: ReadonlyArray<unknown>) => {
644
669
  const ref = Atom.make((get) => startMachineAtomEffect(get, machine as any, args as []))
@@ -14,6 +14,7 @@ import { Rpc } from "effect/unstable/rpc"
14
14
  import type * as Machine from "../../Machine.js"
15
15
  import type { Checkpoint, ClusterMachine, LoadResult } from "../../unstable/cluster/ClusterMachine.js"
16
16
  import * as internalMachine from "./machine.js"
17
+ import * as Protocol from "./protocol.js"
17
18
  import type { EnsureExecutable } from "./readiness.js"
18
19
 
19
20
  type EntityAddress = EntityAddress.EntityAddress
@@ -248,7 +249,7 @@ export const make = <
248
249
  OutputStates,
249
250
  InputEvents
250
251
  >
251
- const eventSchema = Schema.Union(machine.events as MachineEvents<M>)
252
+ const eventSchema = Schema.Union(Protocol.inputEventSchemas(machine) as MachineEvents<M>)
252
253
  const rpc = Rpc.make("send", {
253
254
  payload: eventSchema,
254
255
  success: SendResult
@@ -47,8 +47,8 @@ export const makeCollector = <Event>(machine: Machine.Any): Collected<Event> =>
47
47
  emit: (event) => {
48
48
  emittedEvents.push(decodeEmitSync(machine, event))
49
49
  },
50
- sendTo: (child: unknown, event: unknown) => {
51
- commands.push({ _tag: "SendTo", child: child as any, event })
50
+ sendTo: (target: unknown, event: unknown) => {
51
+ commands.push({ _tag: "SendTo", target: target as any, event })
52
52
  },
53
53
  stop: (child: unknown) => {
54
54
  commands.push({ _tag: "Stop", child: child as any })
@@ -10,6 +10,9 @@ import type { RuntimeCommand } from "./command.js"
10
10
  import { decodeEmit, decodeEvent } from "./protocol.js"
11
11
  import type { ProcessScope } from "./runtime.js"
12
12
 
13
+ const isActorRef = (target: unknown): target is { readonly send: (event: unknown) => Effect.Effect<void, unknown> } =>
14
+ typeof target === "object" && target !== null && "send" in target && typeof target.send === "function"
15
+
13
16
  export const makeLiveRuntime = <Events, Emits>(
14
17
  machine: Machine.Any,
15
18
  scope: ProcessScope<Events>
@@ -18,9 +21,9 @@ export const makeLiveRuntime = <Events, Emits>(
18
21
  decodeEvent(machine, event).pipe(
19
22
  Effect.flatMap((event) => scope.self.send(event as Events))
20
23
  ),
21
- sendParent: (event) =>
24
+ emit: (event) =>
22
25
  decodeEmit(machine, event).pipe(
23
- Effect.flatMap((event) => scope.sendParent(event))
26
+ Effect.flatMap((event) => scope.emit(event))
24
27
  )
25
28
  })
26
29
 
@@ -30,7 +33,9 @@ export const runCommands = <Event>(
30
33
  ) =>
31
34
  Effect.forEach(commands, (command) =>
32
35
  command._tag === "SendTo"
33
- ? scope.sendTo(command.child as never, command.event)
36
+ ? isActorRef(command.target)
37
+ ? command.target.send(command.event)
38
+ : scope.sendTo(command.target as never, command.event)
34
39
  : scope.stopChild(command.child as never), { discard: true })
35
40
 
36
41
  export const runEmittedEvents = <Events, Emits>(
@@ -38,6 +43,6 @@ export const runEmittedEvents = <Events, Emits>(
38
43
  runtime: Runtime<Events, Emits>
39
44
  ) =>
40
45
  Effect.all(
41
- Array.from(events, (event) => runtime.sendParent(event)),
46
+ Array.from(events, (event) => runtime.emit(event)),
42
47
  { discard: true }
43
48
  )
@@ -8,7 +8,7 @@ import * as Cause from "effect/Cause"
8
8
  import * as Effect from "effect/Effect"
9
9
  import * as Option from "effect/Option"
10
10
  import { hasProperty } from "effect/Predicate"
11
- import type { Machine } from "../../Machine.js"
11
+ import type { ActorRef, Machine } from "../../Machine.js"
12
12
  import { MachineSchemaDecodeError } from "./errors.js"
13
13
  import {
14
14
  decodeBoundary,
@@ -252,8 +252,26 @@ export interface ActiveConfiguration {
252
252
  readonly values: ReadonlyMap<string, unknown>
253
253
  readonly outputs: ReadonlyMap<string, unknown>
254
254
  readonly history: ReadonlyMap<string, HistoryRecord>
255
+ readonly actorScope?: PlanningActorScope
255
256
  }
256
257
 
258
+ export interface PlanningActorScope {
259
+ readonly self: ActorRef<any>
260
+ readonly parent: ActorRef<any> | undefined
261
+ }
262
+
263
+ export const withActorScope = (
264
+ configuration: ActiveConfiguration,
265
+ actorScope: PlanningActorScope
266
+ ): ActiveConfiguration => ({
267
+ ...configuration,
268
+ actorScope: { self: actorScope.self, parent: actorScope.parent }
269
+ })
270
+
271
+ export const getActorScope = (
272
+ configuration: ActiveConfiguration
273
+ ): PlanningActorScope | undefined => configuration.actorScope
274
+
257
275
  export interface FinalCompletion {
258
276
  readonly path: string
259
277
  readonly output: unknown
@@ -1178,8 +1196,8 @@ export const resolveFinalOutputEffect: <
1178
1196
  const node = getNode(machine, path)
1179
1197
  const output = getStateConfigByPath(machine, path)?.output?.({
1180
1198
  state: configuration.values.get(path),
1181
- parent: getParentValue(machine, configuration, path),
1182
- parents: getParentValues(machine, configuration, path),
1199
+ containingState: getParentValue(machine, configuration, path),
1200
+ ancestors: getParentValues(machine, configuration, path),
1183
1201
  event,
1184
1202
  outputs
1185
1203
  } as any)
@@ -1331,8 +1349,8 @@ const resolveFinalOutputSync = <const Events extends ReadonlyArray<Machine.Tagge
1331
1349
  const node = getNode(machine, path)
1332
1350
  const output = getStateConfigByPath(machine, path)?.output?.({
1333
1351
  state: configuration.values.get(path),
1334
- parent: getParentValue(machine, configuration, path),
1335
- parents: getParentValues(machine, configuration, path),
1352
+ containingState: getParentValue(machine, configuration, path),
1353
+ ancestors: getParentValues(machine, configuration, path),
1336
1354
  event,
1337
1355
  outputs
1338
1356
  } as any)
@@ -25,7 +25,7 @@ export class MachineSchemaEncodeError extends Data.TaggedError("MachineSchemaEnc
25
25
  */
26
26
  export class MachineSchemaDecodeError extends Data.TaggedError("MachineSchemaDecodeError")<{
27
27
  readonly machineId: string | undefined
28
- readonly boundary: "input" | "event" | "emit" | "state" | "output" | "history" | "configuration"
28
+ readonly boundary: "input" | "event" | "emission" | "state" | "output" | "history" | "configuration"
29
29
  readonly state?: string
30
30
  readonly event?: string
31
31
  readonly cause: Schema.SchemaError | Cause.Cause<unknown>
@@ -4,7 +4,8 @@
4
4
  * @since 0.4.0
5
5
  */
6
6
 
7
- import type { Machine } from "../../Machine.js"
7
+ import * as Effect from "effect/Effect"
8
+ import type { ActorRef, Machine } from "../../Machine.js"
8
9
  import { getTargetBuilder, type RuntimeCommand } from "./command.js"
9
10
  import {
10
11
  type ActiveConfiguration,
@@ -17,10 +18,12 @@ import {
17
18
  isDescendantOf,
18
19
  normalizeConfigurationSync,
19
20
  normalizeTargetConfigurationSync,
21
+ type PlanningActorScope,
20
22
  snapshotFromConfiguration,
21
- validateInitialConfiguration
23
+ validateInitialConfiguration,
24
+ withActorScope
22
25
  } from "./configuration.js"
23
- import { InfiniteTransitionError } from "./errors.js"
26
+ import { InfiniteTransitionError, StoppedError } from "./errors.js"
24
27
  import * as InvocationEvent from "./invocationEvent.js"
25
28
  import {
26
29
  broadenTransitionBoundary,
@@ -43,7 +46,7 @@ import {
43
46
  validateDeclaredTransitionTarget
44
47
  } from "./planner.js"
45
48
  import { decodeEmitSync, decodeEventSync, decodeInputSync, decodeStateValueSync } from "./protocol.js"
46
- import { isSnapshot, isTarget, TargetSnapshotTypeId } from "./topology.js"
49
+ import { isNoTarget, isSnapshot, isTarget, TargetSnapshotTypeId } from "./topology.js"
47
50
 
48
51
  interface IndexedExecutionDescriptor {
49
52
  readonly flat: boolean
@@ -64,6 +67,29 @@ interface IndexedExecutionDescriptor {
64
67
  >
65
68
  }
66
69
 
70
+ const planningActorScopes = new WeakMap<Machine.Any, PlanningActorScope>()
71
+
72
+ const getPlanningActorScope = (machine: Machine.Any): PlanningActorScope => {
73
+ const cached = planningActorScopes.get(machine)
74
+ if (cached !== undefined) return cached
75
+ const self: ActorRef<unknown> = {
76
+ id: machine.id ?? "Machine",
77
+ sessionId: "Machine.plan",
78
+ send: () => Effect.fail(new StoppedError())
79
+ }
80
+ const scope = { self, parent: undefined }
81
+ planningActorScopes.set(machine, scope)
82
+ return scope
83
+ }
84
+
85
+ const getActorContext = (
86
+ machine: Machine.Any,
87
+ actorScope: PlanningActorScope | undefined
88
+ ): PlanningActorScope =>
89
+ actorScope === undefined
90
+ ? getPlanningActorScope(machine)
91
+ : { self: actorScope.self, parent: actorScope.parent }
92
+
67
93
  const indexedStateConfigKeys: ReadonlySet<PropertyKey> = new Set([
68
94
  "initial",
69
95
  "invoke",
@@ -336,18 +362,20 @@ const makeIndexedTransitionContext = (
336
362
  descriptor: IndexedExecutionDescriptor,
337
363
  configuration: OwnedIndexedState,
338
364
  sourceIndex: number,
339
- event: any
365
+ event: any,
366
+ actorScope?: PlanningActorScope
340
367
  ): any => {
341
368
  const source = descriptor.nodes[sourceIndex]!
342
369
  const parentIndex = descriptor.parentIndices[sourceIndex]!
343
- const parents: Record<string, unknown> = {}
370
+ const ancestors: Record<string, unknown> = {}
344
371
  for (const ancestorIndex of descriptor.ancestorIndices[sourceIndex]!) {
345
- parents[descriptor.nodes[ancestorIndex]!.path] = configuration.values[ancestorIndex]
372
+ ancestors[descriptor.nodes[ancestorIndex]!.path] = configuration.values[ancestorIndex]
346
373
  }
347
374
  return {
375
+ ...getActorContext(machine, actorScope),
348
376
  state: configuration.values[sourceIndex],
349
- parent: parentIndex < 0 ? undefined : configuration.values[parentIndex],
350
- parents,
377
+ containingState: parentIndex < 0 ? undefined : configuration.values[parentIndex],
378
+ ancestors,
351
379
  event,
352
380
  snapshot: snapshotFromIndexedState(descriptor, configuration),
353
381
  target: getTargetBuilder(machine, source.path)
@@ -399,7 +427,7 @@ const collectIndexedTransition = (
399
427
  let commands: Array<RuntimeCommand> | undefined
400
428
  let raisedEvents: Array<any> | undefined
401
429
  let emittedEvents: Array<unknown> | undefined
402
- const state = transition(context, {
430
+ const result = transition(context, {
403
431
  raise: (event: unknown) => {
404
432
  ;(raisedEvents ??= []).push(decodeEventSync(machine, event))
405
433
  },
@@ -407,14 +435,14 @@ const collectIndexedTransition = (
407
435
  ;(emittedEvents ??= []).push(decodeEmitSync(machine, event))
408
436
  },
409
437
  sendTo: (child: unknown, event: unknown) => {
410
- ;(commands ??= []).push({ _tag: "SendTo", child: child as any, event })
438
+ ;(commands ??= []).push({ _tag: "SendTo", target: child as any, event })
411
439
  },
412
440
  stop: (child: unknown) => {
413
441
  ;(commands ??= []).push({ _tag: "Stop", child: child as any })
414
442
  }
415
443
  })
416
444
  return {
417
- state,
445
+ state: isNoTarget(result) ? undefined : result,
418
446
  commands: commands ?? emptyExecutionValues,
419
447
  raisedEvents: raisedEvents ?? emptyExecutionValues,
420
448
  emittedEvents: emittedEvents ?? emptyExecutionValues
@@ -425,7 +453,8 @@ const selectIndexedEventTransitions = (
425
453
  machine: Machine.Any,
426
454
  descriptor: IndexedExecutionDescriptor,
427
455
  configuration: OwnedIndexedState,
428
- event: any
456
+ event: any,
457
+ actorScope?: PlanningActorScope
429
458
  ): ReadonlyArray<IndexedSelectedTransition> => {
430
459
  const selected: Array<IndexedSelectedTransition> = []
431
460
  for (const leafIndex of configuration.activeLeaves) {
@@ -446,7 +475,8 @@ const selectIndexedEventTransitions = (
446
475
  descriptor,
447
476
  configuration,
448
477
  sourceIndex,
449
- event
478
+ event,
479
+ actorScope
450
480
  )
451
481
  })
452
482
  }
@@ -629,7 +659,8 @@ const planIndexedFlatState = (
629
659
  descriptor: IndexedExecutionDescriptor,
630
660
  configuration: OwnedIndexedState,
631
661
  decoded: { readonly _tag: PropertyKey },
632
- retainMicrosteps: boolean
662
+ retainMicrosteps: boolean,
663
+ actorScope?: PlanningActorScope
633
664
  ): ExecutionMacrostep<OwnedIndexedState> => {
634
665
  let current = configuration
635
666
  let event: any = decoded
@@ -681,9 +712,10 @@ const planIndexedFlatState = (
681
712
  machine,
682
713
  transition.transition,
683
714
  {
715
+ ...getActorContext(machine, actorScope),
684
716
  state: current.values[sourceIndex],
685
- parent: undefined,
686
- parents: {},
717
+ containingState: undefined,
718
+ ancestors: {},
687
719
  event,
688
720
  snapshot: snapshotFromIndexedState(descriptor, current),
689
721
  target: getTargetBuilder(machine, sourcePath)
@@ -774,7 +806,8 @@ const planIndexedState = (
774
806
  descriptor: IndexedExecutionDescriptor,
775
807
  configuration: OwnedIndexedState,
776
808
  input: unknown,
777
- retainMicrosteps: boolean
809
+ retainMicrosteps: boolean,
810
+ actorScope?: PlanningActorScope
778
811
  ): ExecutionMacrostep<OwnedIndexedState> => {
779
812
  if (InvocationEvent.isInvocationEvent(input)) {
780
813
  // Invocation lifecycle transitions retain the generic planner as their
@@ -783,7 +816,9 @@ const planIndexedState = (
783
816
  // the representation boundary.
784
817
  const planned = planConfiguration(
785
818
  machine as any,
786
- activeConfigurationFromIndexedState(descriptor, configuration),
819
+ actorScope === undefined
820
+ ? activeConfigurationFromIndexedState(descriptor, configuration)
821
+ : withActorScope(activeConfigurationFromIndexedState(descriptor, configuration), actorScope),
787
822
  input
788
823
  )
789
824
  return {
@@ -806,7 +841,7 @@ const planIndexedState = (
806
841
  }
807
842
  const decoded = decodeEventSync(machine, input)
808
843
  if (descriptor.flat) {
809
- return planIndexedFlatState(machine, descriptor, configuration, decoded, retainMicrosteps)
844
+ return planIndexedFlatState(machine, descriptor, configuration, decoded, retainMicrosteps, actorScope)
810
845
  }
811
846
  if (descriptor.finalIndices.some((index) => configuration.active[index] === 1)) {
812
847
  const active = activeConfigurationFromIndexedState(descriptor, configuration)
@@ -827,7 +862,7 @@ const planIndexedState = (
827
862
  }
828
863
  }
829
864
 
830
- const selections = selectIndexedEventTransitions(machine, descriptor, configuration, decoded)
865
+ const selections = selectIndexedEventTransitions(machine, descriptor, configuration, decoded, actorScope)
831
866
  if (selections.length === 0) {
832
867
  return {
833
868
  next: configuration,
@@ -895,7 +930,7 @@ const planIndexedState = (
895
930
  }
896
931
  raisedIndex += 1
897
932
  currentEvent = raised
898
- const raisedSelections = selectIndexedEventTransitions(machine, descriptor, current, raised)
933
+ const raisedSelections = selectIndexedEventTransitions(machine, descriptor, current, raised, actorScope)
899
934
  if (raisedSelections.length === 0) continue
900
935
  const step = indexedMicrostep(machine, descriptor, current, raised, raisedSelections)
901
936
  current = step.next
@@ -913,10 +948,12 @@ export interface CompiledExecutionPlan {
913
948
  readonly plan: (
914
949
  state: unknown,
915
950
  event: unknown,
916
- retainMicrosteps?: boolean
951
+ retainMicrosteps?: boolean,
952
+ actorScope?: PlanningActorScope
917
953
  ) => ExecutionMacrostep
918
954
  readonly initial?: (
919
- args: ReadonlyArray<unknown>
955
+ args: ReadonlyArray<unknown>,
956
+ actorScope?: PlanningActorScope
920
957
  ) => {
921
958
  readonly state: Machine.Snapshot<any>
922
959
  readonly configuration: unknown
@@ -933,7 +970,14 @@ const makeActiveExecutionPlan = (machine: Machine.Any): CompiledExecutionPlan =>
933
970
  fromConfiguration: (configuration) => configuration,
934
971
  toConfiguration: (state) => state as ActiveConfiguration,
935
972
  snapshot: (state) => snapshotFromConfiguration(machine, state as ActiveConfiguration),
936
- plan: (state, event) => planConfiguration(machine as any, state as ActiveConfiguration, event as any)
973
+ plan: (state, event, _retainMicrosteps, actorScope) =>
974
+ planConfiguration(
975
+ machine as any,
976
+ actorScope === undefined
977
+ ? state as ActiveConfiguration
978
+ : withActorScope(state as ActiveConfiguration, actorScope),
979
+ event as any
980
+ )
937
981
  })
938
982
 
939
983
  const makeIndexedExecutionPlan = (
@@ -943,16 +987,17 @@ const makeIndexedExecutionPlan = (
943
987
  fromConfiguration: (configuration) => ownedIndexedStateFromActive(indexed, configuration),
944
988
  toConfiguration: (state) => activeConfigurationFromIndexedState(indexed, state as OwnedIndexedState),
945
989
  snapshot: (state) => snapshotFromIndexedState(indexed, state as OwnedIndexedState),
946
- plan: (state, event, retainMicrosteps = false) =>
947
- planIndexedState(machine, indexed, state as OwnedIndexedState, event, retainMicrosteps),
948
- initial: (args) => {
990
+ plan: (state, event, retainMicrosteps = false, actorScope) =>
991
+ planIndexedState(machine, indexed, state as OwnedIndexedState, event, retainMicrosteps, actorScope),
992
+ initial: (args, actorScope) => {
949
993
  const inputArgs = machine.input === undefined
950
994
  ? args
951
995
  : args.length === 0
952
996
  ? (decodeInputSync(machine, machine.input, undefined), args)
953
997
  : [decodeInputSync(machine, machine.input, args[0])]
954
998
  const initial = machine.initial(...inputArgs as any)
955
- const active = normalizeConfigurationSync(machine, initial as Machine.Snapshot<any>)
999
+ const normalized = normalizeConfigurationSync(machine, initial as Machine.Snapshot<any>)
1000
+ const active = actorScope === undefined ? normalized : withActorScope(normalized, actorScope)
956
1001
  validateInitialConfiguration(machine, active)
957
1002
  const completed = completeConfigurationSync(machine, active, InitialEvent).configuration
958
1003
  const configuration = ownedIndexedStateFromActive(indexed, completed)
@@ -235,9 +235,10 @@ export const startAll = (
235
235
  .filter((path) => configuration.active.has(path))
236
236
  .flatMap((path) => {
237
237
  const context = {
238
+ ...(Configuration.getActorScope(configuration) ?? { self: scope.self, parent: scope.parent }),
238
239
  state: configuration.values.get(path),
239
- parent: Configuration.getParentValue(machine, configuration, path),
240
- parents: Configuration.getParentValues(machine, configuration, path),
240
+ containingState: Configuration.getParentValue(machine, configuration, path),
241
+ ancestors: Configuration.getParentValues(machine, configuration, path),
241
242
  event
242
243
  }
243
244
  return InvocationEvent.definitions(Configuration.getStateConfigByPath(machine, path)?.invoke).map((definition) =>