rivetkit 2.3.0-rc.9 → 2.3.1

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 (226) hide show
  1. package/dist/browser/client.d.ts +511 -62
  2. package/dist/browser/client.js +230 -174
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +53 -23
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +4 -2
  7. package/dist/tsup/actor/errors.cjs.map +1 -1
  8. package/dist/tsup/actor/errors.d.cts +1 -1
  9. package/dist/tsup/actor/errors.d.ts +1 -1
  10. package/dist/tsup/actor/errors.js +3 -1
  11. package/dist/tsup/agent-os/index.cjs +2163 -2087
  12. package/dist/tsup/agent-os/index.cjs.map +1 -1
  13. package/dist/tsup/agent-os/index.d.cts +509 -69
  14. package/dist/tsup/agent-os/index.d.ts +509 -69
  15. package/dist/tsup/agent-os/index.js +2163 -2087
  16. package/dist/tsup/agent-os/index.js.map +1 -1
  17. package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-3MHDOUD7.cjs} +73 -3
  18. package/dist/tsup/chunk-3MHDOUD7.cjs.map +1 -0
  19. package/dist/tsup/{chunk-QAZLM4WT.cjs → chunk-4FC7TVS6.cjs} +8 -4
  20. package/dist/tsup/chunk-4FC7TVS6.cjs.map +1 -0
  21. package/dist/tsup/{chunk-4CGA6QJO.cjs → chunk-4UUEB43Y.cjs} +24 -9
  22. package/dist/tsup/chunk-4UUEB43Y.cjs.map +1 -0
  23. package/dist/tsup/{chunk-GVTOE34S.cjs → chunk-5IWLUJ6W.cjs} +222 -235
  24. package/dist/tsup/chunk-5IWLUJ6W.cjs.map +1 -0
  25. package/dist/tsup/{chunk-MMMEZM5J.js → chunk-H6VVZMWN.js} +4 -4
  26. package/dist/tsup/chunk-H6VVZMWN.js.map +1 -0
  27. package/dist/tsup/{chunk-3YY5S6TV.js → chunk-HXUEHHJF.js} +2 -2
  28. package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
  29. package/dist/tsup/{chunk-H7P7WR2Y.js → chunk-I35VSLEM.js} +6 -6
  30. package/dist/tsup/chunk-I35VSLEM.js.map +1 -0
  31. package/dist/tsup/{chunk-H37XQU3I.js → chunk-JBUZRPY5.js} +2 -2
  32. package/dist/tsup/{chunk-CPA4Y3RG.cjs → chunk-JLJJZYCJ.cjs} +10 -10
  33. package/dist/tsup/chunk-JLJJZYCJ.cjs.map +1 -0
  34. package/dist/tsup/{chunk-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
  35. package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
  36. package/dist/tsup/{chunk-VRCIXJRN.js → chunk-L2X3YFER.js} +64 -10
  37. package/dist/tsup/chunk-L2X3YFER.js.map +1 -0
  38. package/dist/tsup/{chunk-Y5NSCZA2.cjs → chunk-MNHKOS6L.cjs} +72 -18
  39. package/dist/tsup/chunk-MNHKOS6L.cjs.map +1 -0
  40. package/dist/tsup/{chunk-KJTA3ATT.js → chunk-NERUIBOT.js} +22 -7
  41. package/dist/tsup/chunk-NERUIBOT.js.map +1 -0
  42. package/dist/tsup/{chunk-4WPEZBK4.cjs → chunk-OST76LRW.cjs} +10 -10
  43. package/dist/tsup/chunk-OST76LRW.cjs.map +1 -0
  44. package/dist/tsup/{chunk-MALSPBAF.cjs → chunk-OZBCXBVP.cjs} +3 -3
  45. package/dist/tsup/{chunk-MALSPBAF.cjs.map → chunk-OZBCXBVP.cjs.map} +1 -1
  46. package/dist/tsup/{chunk-F3Q5BFQ6.js → chunk-PT6OIW5E.js} +66 -79
  47. package/dist/tsup/chunk-PT6OIW5E.js.map +1 -0
  48. package/dist/tsup/{chunk-W7EYSYVI.js → chunk-R6KPN5EW.js} +134 -20
  49. package/dist/tsup/chunk-R6KPN5EW.js.map +1 -0
  50. package/dist/tsup/{chunk-VJFRBJVQ.cjs → chunk-V5KMAMX3.cjs} +138 -24
  51. package/dist/tsup/chunk-V5KMAMX3.cjs.map +1 -0
  52. package/dist/tsup/{chunk-LD5YASJU.cjs → chunk-VE2X4KMG.cjs} +2 -2
  53. package/dist/tsup/{chunk-LD5YASJU.cjs.map → chunk-VE2X4KMG.cjs.map} +1 -1
  54. package/dist/tsup/{chunk-T6YVRM4K.js → chunk-XIX5DOZN.js} +72 -2
  55. package/dist/tsup/chunk-XIX5DOZN.js.map +1 -0
  56. package/dist/tsup/{chunk-2NDZ7JCR.cjs → chunk-ZA7FLHKH.cjs} +1 -1
  57. package/dist/tsup/chunk-ZA7FLHKH.cjs.map +1 -0
  58. package/dist/tsup/{chunk-KIWH5H3K.js → chunk-ZZ3WBRPD.js} +7 -3
  59. package/dist/tsup/chunk-ZZ3WBRPD.js.map +1 -0
  60. package/dist/tsup/client/mod.cjs +9 -9
  61. package/dist/tsup/client/mod.d.cts +5 -5
  62. package/dist/tsup/client/mod.d.ts +5 -5
  63. package/dist/tsup/client/mod.js +8 -8
  64. package/dist/tsup/common/log.cjs +3 -3
  65. package/dist/tsup/common/log.js +2 -2
  66. package/dist/tsup/common/websocket.cjs +4 -4
  67. package/dist/tsup/common/websocket.js +3 -3
  68. package/dist/tsup/{config-Ca8dN4cS.d.cts → config-CzvopP5m.d.cts} +544 -23
  69. package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.cts} +1 -2
  70. package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.ts} +1 -2
  71. package/dist/tsup/{config-0Ta55UV0.d.ts → config-DZuT7tcp.d.ts} +544 -23
  72. package/dist/tsup/context-CyAdY-aA.d.ts +128 -0
  73. package/dist/tsup/context-sNB28g0N.d.cts +128 -0
  74. package/dist/tsup/db/drizzle.cjs +3 -3
  75. package/dist/tsup/db/drizzle.d.cts +1 -1
  76. package/dist/tsup/db/drizzle.d.ts +1 -1
  77. package/dist/tsup/db/drizzle.js +1 -1
  78. package/dist/tsup/db/mod.cjs +2 -2
  79. package/dist/tsup/db/mod.d.cts +2 -2
  80. package/dist/tsup/db/mod.d.ts +2 -2
  81. package/dist/tsup/db/mod.js +1 -1
  82. package/dist/tsup/dynamic/mod.cjs +24 -0
  83. package/dist/tsup/dynamic/mod.cjs.map +1 -0
  84. package/dist/tsup/dynamic/mod.d.cts +37 -0
  85. package/dist/tsup/dynamic/mod.d.ts +37 -0
  86. package/dist/tsup/dynamic/mod.js +24 -0
  87. package/dist/tsup/dynamic/mod.js.map +1 -0
  88. package/dist/tsup/inspector/mod.cjs +6 -6
  89. package/dist/tsup/inspector/mod.js +5 -5
  90. package/dist/tsup/inspector-tab/mod.cjs +173 -0
  91. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  92. package/dist/tsup/inspector-tab/mod.d.cts +250 -0
  93. package/dist/tsup/inspector-tab/mod.d.ts +250 -0
  94. package/dist/tsup/inspector-tab/mod.js +173 -0
  95. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  96. package/dist/tsup/mod.cjs +758 -348
  97. package/dist/tsup/mod.cjs.map +1 -1
  98. package/dist/tsup/mod.d.cts +5 -5
  99. package/dist/tsup/mod.d.ts +5 -5
  100. package/dist/tsup/mod.js +662 -252
  101. package/dist/tsup/mod.js.map +1 -1
  102. package/dist/tsup/test/mod.cjs +21 -18
  103. package/dist/tsup/test/mod.cjs.map +1 -1
  104. package/dist/tsup/test/mod.d.cts +4 -4
  105. package/dist/tsup/test/mod.d.ts +4 -4
  106. package/dist/tsup/test/mod.js +18 -15
  107. package/dist/tsup/test/mod.js.map +1 -1
  108. package/dist/tsup/{utils-DVekpm4I.d.cts → utils-CqDnC_PS.d.cts} +2 -1
  109. package/dist/tsup/{utils-DVekpm4I.d.ts → utils-CqDnC_PS.d.ts} +2 -1
  110. package/dist/tsup/utils.cjs +3 -3
  111. package/dist/tsup/utils.d.cts +1 -1
  112. package/dist/tsup/utils.d.ts +1 -1
  113. package/dist/tsup/utils.js +2 -2
  114. package/dist/tsup/workflow/mod.cjs +383 -322
  115. package/dist/tsup/workflow/mod.cjs.map +1 -1
  116. package/dist/tsup/workflow/mod.d.cts +8 -8
  117. package/dist/tsup/workflow/mod.d.ts +8 -8
  118. package/dist/tsup/workflow/mod.js +360 -299
  119. package/dist/tsup/workflow/mod.js.map +1 -1
  120. package/package.json +35 -14
  121. package/src/actor/config.ts +173 -51
  122. package/src/actor/contexts/index.ts +7 -2
  123. package/src/actor/definition.ts +17 -19
  124. package/src/actor/driver.ts +3 -3
  125. package/src/actor/errors.ts +20 -3
  126. package/src/actor/instance/mod.ts +26 -34
  127. package/src/actor/keys.ts +1 -1
  128. package/src/actor/mod.ts +22 -20
  129. package/src/actor/schema.ts +2 -2
  130. package/src/agent-os/actor/index.ts +38 -18
  131. package/src/agent-os/actor/preview.ts +1 -2
  132. package/src/agent-os/actor/session.ts +2 -2
  133. package/src/agent-os/config.ts +1 -1
  134. package/src/agent-os/fs/database-vfs.ts +1 -1
  135. package/src/agent-os/index.ts +16 -15
  136. package/src/client/actor-common.ts +87 -54
  137. package/src/client/actor-conn.ts +8 -36
  138. package/src/client/actor-handle.ts +69 -51
  139. package/src/client/actor-query.ts +5 -5
  140. package/src/client/errors.ts +1 -1
  141. package/src/client/lifecycle-errors.ts +2 -4
  142. package/src/client/query.ts +1 -1
  143. package/src/client/queue.ts +8 -3
  144. package/src/client/raw-utils.ts +8 -6
  145. package/src/client/resolve-gateway-target.ts +1 -1
  146. package/src/client/utils.ts +2 -7
  147. package/src/common/actor-websocket.ts +3 -1
  148. package/src/common/bare/actor-persist/v1.ts +205 -163
  149. package/src/common/bare/actor-persist/v2.ts +265 -213
  150. package/src/common/bare/actor-persist/v3.ts +176 -172
  151. package/src/common/bare/actor-persist/v4.ts +254 -253
  152. package/src/common/bare/transport/v1.ts +659 -543
  153. package/src/common/client-protocol-versioned.ts +66 -64
  154. package/src/common/database/config.ts +2 -8
  155. package/src/common/database/native-database.ts +1 -1
  156. package/src/common/database/shared.ts +1 -0
  157. package/src/common/encoding.ts +250 -16
  158. package/src/common/engine.ts +28 -1
  159. package/src/common/eventsource.ts +1 -1
  160. package/src/common/inline-websocket-adapter.ts +14 -13
  161. package/src/common/log.ts +1 -0
  162. package/src/common/router.ts +13 -17
  163. package/src/common/utils.ts +1 -150
  164. package/src/common/websocket-interface.ts +1 -1
  165. package/src/db/mod.ts +1 -1
  166. package/src/devtools-loader/index.ts +4 -7
  167. package/src/devtools-loader/serve-devtools.ts +26 -0
  168. package/src/drivers/engine/actor-driver.ts +58 -56
  169. package/src/dynamic/instance.ts +32 -0
  170. package/src/dynamic/internal.ts +50 -0
  171. package/src/dynamic/isolate-runtime.ts +66 -0
  172. package/src/dynamic/mod.ts +32 -0
  173. package/src/engine-client/actor-http-client.ts +3 -3
  174. package/src/engine-client/actor-websocket-client.ts +6 -5
  175. package/src/engine-client/api-endpoints.ts +51 -2
  176. package/src/engine-client/api-utils.ts +2 -2
  177. package/src/engine-client/driver.ts +1 -1
  178. package/src/engine-client/mod.ts +6 -3
  179. package/src/engine-client/ws-proxy.ts +9 -4
  180. package/src/inspector/client.browser.ts +5 -11
  181. package/src/inspector/mod.ts +1 -3
  182. package/src/inspector-tab/mod.ts +315 -0
  183. package/src/registry/config/envoy.ts +1 -2
  184. package/src/registry/config/index.ts +40 -16
  185. package/src/registry/index.ts +209 -73
  186. package/src/registry/napi-runtime.ts +29 -2
  187. package/src/registry/native-validation.ts +10 -12
  188. package/src/registry/native.ts +433 -198
  189. package/src/registry/process-metrics.ts +250 -0
  190. package/src/registry/runtime.ts +52 -1
  191. package/src/registry/wasm-runtime.ts +29 -2
  192. package/src/registry/write-through-proxy.ts +40 -0
  193. package/src/serde.ts +2 -2
  194. package/src/serverless/configure.ts +18 -7
  195. package/src/test/mod.ts +11 -8
  196. package/src/utils/endpoint-parser.ts +1 -1
  197. package/src/utils/env-vars.ts +37 -0
  198. package/src/utils/router.ts +1 -1
  199. package/src/utils.ts +1 -2
  200. package/src/workflow/context.ts +699 -240
  201. package/src/workflow/driver.ts +23 -12
  202. package/src/workflow/inspector.ts +4 -3
  203. package/src/workflow/mod.ts +37 -23
  204. package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
  205. package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
  206. package/dist/tsup/chunk-4CGA6QJO.cjs.map +0 -1
  207. package/dist/tsup/chunk-4WPEZBK4.cjs.map +0 -1
  208. package/dist/tsup/chunk-CPA4Y3RG.cjs.map +0 -1
  209. package/dist/tsup/chunk-F3Q5BFQ6.js.map +0 -1
  210. package/dist/tsup/chunk-GVTOE34S.cjs.map +0 -1
  211. package/dist/tsup/chunk-H7P7WR2Y.js.map +0 -1
  212. package/dist/tsup/chunk-KIWH5H3K.js.map +0 -1
  213. package/dist/tsup/chunk-KJTA3ATT.js.map +0 -1
  214. package/dist/tsup/chunk-MMMEZM5J.js.map +0 -1
  215. package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
  216. package/dist/tsup/chunk-QAZLM4WT.cjs.map +0 -1
  217. package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
  218. package/dist/tsup/chunk-VJFRBJVQ.cjs.map +0 -1
  219. package/dist/tsup/chunk-VRCIXJRN.js.map +0 -1
  220. package/dist/tsup/chunk-W7EYSYVI.js.map +0 -1
  221. package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
  222. package/dist/tsup/chunk-Y5NSCZA2.cjs.map +0 -1
  223. package/dist/tsup/context-B_IWbWne.d.ts +0 -92
  224. package/dist/tsup/context-CUrQ9MHc.d.cts +0 -92
  225. package/src/utils/serve.ts +0 -217
  226. /package/dist/tsup/{chunk-H37XQU3I.js.map → chunk-JBUZRPY5.js.map} +0 -0
@@ -1,41 +1,40 @@
1
- // @ts-nocheck
2
- import type { RunContext } from "@/actor/config";
1
+ import type {
2
+ BranchConfig,
3
+ BranchOutput,
4
+ EntryKindType,
5
+ LoopConfig,
6
+ LoopResult,
7
+ StepConfig,
8
+ TryBlockConfig,
9
+ TryBlockResult,
10
+ TryStepConfig,
11
+ TryStepResult,
12
+ WorkflowContextInterface,
13
+ WorkflowQueueMessage,
14
+ } from "@rivetkit/workflow-engine";
3
15
  import type {
4
16
  QueueFilterName,
5
17
  QueueNextBatchOptions,
6
18
  QueueNextOptions,
7
19
  QueueResultMessageForName,
8
20
  } from "@/actor/config";
9
- import type { Client } from "@/client/client";
10
- import type { Registry } from "@/registry";
21
+ import { RAW_STATE_SYMBOL, type RunContext } from "@/actor/config";
11
22
  import type {
12
- BaseActorDefinition,
13
23
  AnyActorDefinition,
24
+ BaseActorDefinition,
14
25
  } from "@/actor/definition";
15
- import type {
16
- AnyDatabaseProvider,
17
- InferDatabaseClient,
18
- } from "@/common/database/config";
19
26
  import type {
20
27
  EventSchemaConfig,
21
28
  InferEventArgs,
22
29
  InferSchemaMap,
23
30
  QueueSchemaConfig,
24
31
  } from "@/actor/schema";
25
- import type { WorkflowContextInterface } from "@rivetkit/workflow-engine";
32
+ import type { Client } from "@/client/client";
26
33
  import type {
27
- BranchConfig,
28
- BranchOutput,
29
- EntryKindType,
30
- LoopConfig,
31
- LoopResult,
32
- StepConfig,
33
- TryBlockConfig,
34
- TryBlockResult,
35
- TryStepConfig,
36
- TryStepResult,
37
- WorkflowQueueMessage,
38
- } from "@rivetkit/workflow-engine";
34
+ AnyDatabaseProvider,
35
+ InferDatabaseClient,
36
+ } from "@/common/database/config";
37
+ import type { Registry } from "@/registry";
39
38
  import { WORKFLOW_GUARD_KV_KEY } from "./constants";
40
39
 
41
40
  type WorkflowActorQueueNextOptions<
@@ -56,7 +55,177 @@ type WorkflowActorQueueNextBatchOptions<
56
55
  type WorkflowActorQueueNextBatchOptionsFallback<TCompletable extends boolean> =
57
56
  Omit<QueueNextBatchOptions<string, TCompletable>, "signal">;
58
57
 
59
- type ActorWorkflowLoopConfig<
58
+ // Step run callbacks receive a WorkflowStepContext, which is the only place
59
+ // actor data (state/db/vars/client) may be touched.
60
+ type WorkflowStepRun<
61
+ T,
62
+ TState,
63
+ TConnParams,
64
+ TConnState,
65
+ TVars,
66
+ TInput,
67
+ TDatabase extends AnyDatabaseProvider,
68
+ TEvents extends EventSchemaConfig,
69
+ TQueues extends QueueSchemaConfig,
70
+ > = (
71
+ step: WorkflowStepContext<
72
+ TState,
73
+ TConnParams,
74
+ TConnState,
75
+ TVars,
76
+ TInput,
77
+ TDatabase,
78
+ TEvents,
79
+ TQueues
80
+ >,
81
+ ) => Promise<T>;
82
+
83
+ // Step rollback callbacks compensate a committed step, so they also run with a
84
+ // WorkflowStepContext to mutate actor data.
85
+ type WorkflowStepRollback<
86
+ T,
87
+ TState,
88
+ TConnParams,
89
+ TConnState,
90
+ TVars,
91
+ TInput,
92
+ TDatabase extends AnyDatabaseProvider,
93
+ TEvents extends EventSchemaConfig,
94
+ TQueues extends QueueSchemaConfig,
95
+ > = (
96
+ step: WorkflowStepContext<
97
+ TState,
98
+ TConnParams,
99
+ TConnState,
100
+ TVars,
101
+ TInput,
102
+ TDatabase,
103
+ TEvents,
104
+ TQueues
105
+ >,
106
+ output: T,
107
+ ) => Promise<void>;
108
+
109
+ // Orchestration callbacks (try/loop/race/join) receive a WorkflowContext,
110
+ // because inside them you sequence further steps rather than touch actor data.
111
+ type WorkflowContextRun<
112
+ T,
113
+ TState,
114
+ TConnParams,
115
+ TConnState,
116
+ TVars,
117
+ TInput,
118
+ TDatabase extends AnyDatabaseProvider,
119
+ TEvents extends EventSchemaConfig,
120
+ TQueues extends QueueSchemaConfig,
121
+ > = (
122
+ ctx: WorkflowContext<
123
+ TState,
124
+ TConnParams,
125
+ TConnState,
126
+ TVars,
127
+ TInput,
128
+ TDatabase,
129
+ TEvents,
130
+ TQueues
131
+ >,
132
+ ) => Promise<T>;
133
+
134
+ export type WorkflowStepConfig<
135
+ T,
136
+ TState,
137
+ TConnParams,
138
+ TConnState,
139
+ TVars,
140
+ TInput,
141
+ TDatabase extends AnyDatabaseProvider,
142
+ TEvents extends EventSchemaConfig,
143
+ TQueues extends QueueSchemaConfig,
144
+ > = Omit<StepConfig<T>, "run" | "rollback"> & {
145
+ run: WorkflowStepRun<
146
+ T,
147
+ TState,
148
+ TConnParams,
149
+ TConnState,
150
+ TVars,
151
+ TInput,
152
+ TDatabase,
153
+ TEvents,
154
+ TQueues
155
+ >;
156
+ rollback?: WorkflowStepRollback<
157
+ T,
158
+ TState,
159
+ TConnParams,
160
+ TConnState,
161
+ TVars,
162
+ TInput,
163
+ TDatabase,
164
+ TEvents,
165
+ TQueues
166
+ >;
167
+ };
168
+
169
+ export type WorkflowTryStepConfig<
170
+ T,
171
+ TState,
172
+ TConnParams,
173
+ TConnState,
174
+ TVars,
175
+ TInput,
176
+ TDatabase extends AnyDatabaseProvider,
177
+ TEvents extends EventSchemaConfig,
178
+ TQueues extends QueueSchemaConfig,
179
+ > = Omit<TryStepConfig<T>, "run" | "rollback"> & {
180
+ run: WorkflowStepRun<
181
+ T,
182
+ TState,
183
+ TConnParams,
184
+ TConnState,
185
+ TVars,
186
+ TInput,
187
+ TDatabase,
188
+ TEvents,
189
+ TQueues
190
+ >;
191
+ rollback?: WorkflowStepRollback<
192
+ T,
193
+ TState,
194
+ TConnParams,
195
+ TConnState,
196
+ TVars,
197
+ TInput,
198
+ TDatabase,
199
+ TEvents,
200
+ TQueues
201
+ >;
202
+ };
203
+
204
+ export type WorkflowTryConfig<
205
+ T,
206
+ TState,
207
+ TConnParams,
208
+ TConnState,
209
+ TVars,
210
+ TInput,
211
+ TDatabase extends AnyDatabaseProvider,
212
+ TEvents extends EventSchemaConfig,
213
+ TQueues extends QueueSchemaConfig,
214
+ > = Omit<TryBlockConfig<T>, "run"> & {
215
+ run: WorkflowContextRun<
216
+ T,
217
+ TState,
218
+ TConnParams,
219
+ TConnState,
220
+ TVars,
221
+ TInput,
222
+ TDatabase,
223
+ TEvents,
224
+ TQueues
225
+ >;
226
+ };
227
+
228
+ export type WorkflowLoopConfig<
60
229
  S,
61
230
  T,
62
231
  TState,
@@ -69,7 +238,7 @@ type ActorWorkflowLoopConfig<
69
238
  TQueues extends QueueSchemaConfig,
70
239
  > = Omit<LoopConfig<S, T>, "run"> & {
71
240
  run: (
72
- ctx: ActorWorkflowContext<
241
+ ctx: WorkflowContext<
73
242
  TState,
74
243
  TConnParams,
75
244
  TConnState,
@@ -80,10 +249,12 @@ type ActorWorkflowLoopConfig<
80
249
  TQueues
81
250
  >,
82
251
  state: S,
83
- ) => Promise<LoopResult<S, T> | (S extends undefined ? void : never)>;
252
+ ) => Promise<
253
+ LoopResult<S, T> | (S extends undefined ? undefined | void : never)
254
+ >;
84
255
  };
85
256
 
86
- type ActorWorkflowBranchConfig<
257
+ export type WorkflowBranchConfig<
87
258
  TOutput,
88
259
  TState,
89
260
  TConnParams,
@@ -94,8 +265,54 @@ type ActorWorkflowBranchConfig<
94
265
  TEvents extends EventSchemaConfig,
95
266
  TQueues extends QueueSchemaConfig,
96
267
  > = {
97
- run: (
98
- ctx: ActorWorkflowContext<
268
+ run: WorkflowContextRun<
269
+ TOutput,
270
+ TState,
271
+ TConnParams,
272
+ TConnState,
273
+ TVars,
274
+ TInput,
275
+ TDatabase,
276
+ TEvents,
277
+ TQueues
278
+ >;
279
+ };
280
+
281
+ // Marks a step context inactive once its step has finished. Module-private so it
282
+ // never appears on the public surface.
283
+ const DEACTIVATE_STEP = Symbol("workflow.step.deactivate");
284
+
285
+ /**
286
+ * The context handed to a workflow step (`step` / `tryStep` callbacks). This is
287
+ * the only scope where actor data (state, vars, db, client) and side effects
288
+ * (broadcast, queue.send) are reachable. It is valid only while its step is
289
+ * executing; using it after the step resolves throws.
290
+ */
291
+ export class WorkflowStepContext<
292
+ TState,
293
+ TConnParams,
294
+ TConnState,
295
+ TVars,
296
+ TInput,
297
+ TDatabase extends AnyDatabaseProvider,
298
+ TEvents extends EventSchemaConfig = Record<never, never>,
299
+ TQueues extends QueueSchemaConfig = Record<never, never>,
300
+ > {
301
+ #runCtx: RunContext<
302
+ TState,
303
+ TConnParams,
304
+ TConnState,
305
+ TVars,
306
+ TInput,
307
+ TDatabase,
308
+ TEvents,
309
+ TQueues
310
+ >;
311
+ #active = true;
312
+ #onGuardViolation: () => void;
313
+
314
+ constructor(
315
+ runCtx: RunContext<
99
316
  TState,
100
317
  TConnParams,
101
318
  TConnState,
@@ -105,10 +322,133 @@ type ActorWorkflowBranchConfig<
105
322
  TEvents,
106
323
  TQueues
107
324
  >,
108
- ) => Promise<TOutput>;
109
- };
325
+ onGuardViolation: () => void,
326
+ ) {
327
+ this.#runCtx = runCtx;
328
+ this.#onGuardViolation = onGuardViolation;
329
+ }
330
+
331
+ [DEACTIVATE_STEP](): void {
332
+ this.#active = false;
333
+ }
334
+
335
+ #ensureActive(feature: string): void {
336
+ if (!this.#active) {
337
+ this.#onGuardViolation();
338
+ throw new Error(
339
+ `${feature} is only available inside workflow steps`,
340
+ );
341
+ }
342
+ }
343
+
344
+ get actorId(): string {
345
+ return this.#runCtx.actorId;
346
+ }
347
+
348
+ get name(): string {
349
+ return this.#runCtx.name;
350
+ }
351
+
352
+ get key(): string[] {
353
+ return this.#runCtx.key;
354
+ }
110
355
 
111
- export class ActorWorkflowContext<
356
+ get log() {
357
+ return this.#runCtx.log;
358
+ }
359
+
360
+ get abortSignal(): AbortSignal {
361
+ return this.#runCtx.abortSignal;
362
+ }
363
+
364
+ get state(): TState extends never ? never : TState {
365
+ this.#ensureActive("state");
366
+ return this.#runCtx.state as TState extends never ? never : TState;
367
+ }
368
+
369
+ get vars(): TVars extends never ? never : TVars {
370
+ this.#ensureActive("vars");
371
+ return this.#runCtx.vars as TVars extends never ? never : TVars;
372
+ }
373
+
374
+ get db(): TDatabase extends never ? never : InferDatabaseClient<TDatabase> {
375
+ this.#ensureActive("db");
376
+ return this.#runCtx.db as TDatabase extends never
377
+ ? never
378
+ : InferDatabaseClient<TDatabase>;
379
+ }
380
+
381
+ client<R extends Registry<any> = Registry<any>>(): Client<R> {
382
+ this.#ensureActive("client");
383
+ return this.#runCtx.client<R>();
384
+ }
385
+
386
+ broadcast<K extends keyof TEvents & string>(
387
+ name: K,
388
+ ...args: InferEventArgs<InferSchemaMap<TEvents>[K]>
389
+ ): void;
390
+ broadcast(
391
+ name: keyof TEvents extends never ? string : never,
392
+ ...args: Array<unknown>
393
+ ): void;
394
+ broadcast(name: string, ...args: Array<unknown>): void {
395
+ this.#ensureActive("broadcast");
396
+ this.#runCtx.broadcast(
397
+ name as never,
398
+ ...(args as unknown[] as never[]),
399
+ );
400
+ }
401
+
402
+ get queue() {
403
+ const self = this;
404
+ function send<K extends keyof TQueues & string>(
405
+ name: K,
406
+ body: InferSchemaMap<TQueues>[K],
407
+ ): Promise<void>;
408
+ function send(
409
+ name: keyof TQueues extends never ? string : never,
410
+ body: unknown,
411
+ ): Promise<void>;
412
+ async function send(name: string, body: unknown): Promise<void> {
413
+ self.#ensureActive("queue.send");
414
+ await self.#runCtx.queue.send(name as never, body as never);
415
+ }
416
+ return { send };
417
+ }
418
+
419
+ /**
420
+ * Holds the actor awake for the duration of the provided promise. The actor
421
+ * cannot idle-sleep or finalize the sleep grace period until the promise
422
+ * settles.
423
+ */
424
+ keepAwake<T>(promise: Promise<T>): Promise<T> {
425
+ this.#ensureActive("keepAwake");
426
+ return this.#runCtx.keepAwake(promise);
427
+ }
428
+
429
+ /**
430
+ * Registers a promise that the sleep grace period will wait on. Use this for
431
+ * best-effort flush/cleanup work that may complete inside the grace window.
432
+ */
433
+ waitUntil(promise: Promise<void>): void {
434
+ this.#ensureActive("waitUntil");
435
+ this.#runCtx.waitUntil(promise);
436
+ }
437
+
438
+ destroy(): void {
439
+ this.#ensureActive("destroy");
440
+ this.#runCtx.destroy();
441
+ }
442
+ }
443
+
444
+ /**
445
+ * The context handed to the workflow function and to orchestration callbacks
446
+ * (`try` / `loop` / `race` / `join`). It exposes the deterministic, replayable
447
+ * workflow primitives (step, sleep, queue waits, control flow). It deliberately
448
+ * does NOT expose actor data; reach `state`, `db`, `vars`, `client`, and
449
+ * `broadcast` through the step context passed to `step` / `tryStep`.
450
+ */
451
+ export class WorkflowContext<
112
452
  TState,
113
453
  TConnParams,
114
454
  TConnState,
@@ -117,8 +457,7 @@ export class ActorWorkflowContext<
117
457
  TDatabase extends AnyDatabaseProvider,
118
458
  TEvents extends EventSchemaConfig = Record<never, never>,
119
459
  TQueues extends QueueSchemaConfig = Record<never, never>,
120
- > implements WorkflowContextInterface
121
- {
460
+ > {
122
461
  #inner: WorkflowContextInterface;
123
462
  #runCtx: RunContext<
124
463
  TState,
@@ -130,9 +469,6 @@ export class ActorWorkflowContext<
130
469
  TEvents,
131
470
  TQueues
132
471
  >;
133
- #actorAccessDepth = 0;
134
- #allowActorAccess = false;
135
- #guardViolation = false;
136
472
 
137
473
  constructor(
138
474
  inner: WorkflowContextInterface,
@@ -159,6 +495,22 @@ export class ActorWorkflowContext<
159
495
  return this.#inner.abortSignal;
160
496
  }
161
497
 
498
+ get actorId(): string {
499
+ return this.#runCtx.actorId;
500
+ }
501
+
502
+ get name(): string {
503
+ return this.#runCtx.name;
504
+ }
505
+
506
+ get key(): string[] {
507
+ return this.#runCtx.key;
508
+ }
509
+
510
+ get log() {
511
+ return this.#runCtx.log;
512
+ }
513
+
162
514
  get queue() {
163
515
  const self = this;
164
516
  function next<
@@ -178,10 +530,9 @@ export class ActorWorkflowContext<
178
530
  TCompletable
179
531
  >
180
532
  >;
181
- async function next(
182
- name: string,
183
- opts?: WorkflowActorQueueNextOptions<string, boolean>,
184
- ): Promise<WorkflowQueueMessage<unknown>> {
533
+ // The implementation signature stays broad so the schema-typed public
534
+ // overloads above remain compatible with it.
535
+ async function next(name: string, opts?: any): Promise<any> {
185
536
  const message = await self.#inner.queue.next(name, opts);
186
537
  return self.#toActorQueueMessage(message);
187
538
  }
@@ -207,108 +558,232 @@ export class ActorWorkflowContext<
207
558
  >
208
559
  >
209
560
  >;
210
- async function nextBatch(
211
- name: string,
212
- opts?: WorkflowActorQueueNextBatchOptions<string, boolean>,
213
- ): Promise<Array<WorkflowQueueMessage<unknown>>> {
561
+ async function nextBatch(name: string, opts?: any): Promise<any> {
214
562
  const messages = await self.#inner.queue.nextBatch(name, opts);
215
563
  return messages.map((message) =>
216
564
  self.#toActorQueueMessage(message),
217
565
  );
218
566
  }
219
567
 
220
- function send<K extends keyof TQueues & string>(
221
- name: K,
222
- body: InferSchemaMap<TQueues>[K],
223
- ): Promise<void>;
224
- function send(
225
- name: keyof TQueues extends never ? string : never,
226
- body: unknown,
227
- ): Promise<void>;
228
- async function send(name: string, body: unknown): Promise<void> {
229
- self.#ensureActorAccess("queue.send");
230
- await self.#runCtx.queue.send(name as never, body as never);
231
- }
232
-
233
568
  return {
234
569
  next,
235
570
  nextBatch,
236
- send,
237
571
  };
238
572
  }
239
573
 
574
+ step<T>(
575
+ name: string,
576
+ run: WorkflowStepRun<
577
+ T,
578
+ TState,
579
+ TConnParams,
580
+ TConnState,
581
+ TVars,
582
+ TInput,
583
+ TDatabase,
584
+ TEvents,
585
+ TQueues
586
+ >,
587
+ ): Promise<T>;
588
+ step<T>(
589
+ config: WorkflowStepConfig<
590
+ T,
591
+ TState,
592
+ TConnParams,
593
+ TConnState,
594
+ TVars,
595
+ TInput,
596
+ TDatabase,
597
+ TEvents,
598
+ TQueues
599
+ >,
600
+ ): Promise<T>;
240
601
  async step<T>(
241
- nameOrConfig: string | Parameters<WorkflowContextInterface["step"]>[0],
242
- run?: () => Promise<T>,
602
+ nameOrConfig:
603
+ | string
604
+ | WorkflowStepConfig<
605
+ T,
606
+ TState,
607
+ TConnParams,
608
+ TConnState,
609
+ TVars,
610
+ TInput,
611
+ TDatabase,
612
+ TEvents,
613
+ TQueues
614
+ >,
615
+ run?: WorkflowStepRun<
616
+ T,
617
+ TState,
618
+ TConnParams,
619
+ TConnState,
620
+ TVars,
621
+ TInput,
622
+ TDatabase,
623
+ TEvents,
624
+ TQueues
625
+ >,
243
626
  ): Promise<T> {
244
627
  if (typeof nameOrConfig === "string") {
245
628
  if (!run) {
246
629
  throw new Error("Step run function missing");
247
630
  }
631
+ const stepRun = run;
248
632
  return await this.#wrapActive(() =>
249
- this.#inner.step(nameOrConfig, () =>
250
- this.#withActorAccess(run),
251
- ),
633
+ this.#inner.step(nameOrConfig, () => this.#runStep(stepRun)),
252
634
  );
253
635
  }
254
- const stepConfig = nameOrConfig as StepConfig<T>;
636
+ const stepConfig = nameOrConfig;
637
+ const rollback = stepConfig.rollback;
255
638
  const config: StepConfig<T> = {
256
639
  ...stepConfig,
257
- run: () => this.#withActorAccess(stepConfig.run),
640
+ run: () => this.#runStep(stepConfig.run),
641
+ rollback: rollback
642
+ ? (_ctx, output) => this.#runRollback(rollback, output)
643
+ : undefined,
258
644
  };
259
645
  return await this.#wrapActive(() => this.#inner.step(config));
260
646
  }
261
647
 
648
+ tryStep<T>(
649
+ name: string,
650
+ run: WorkflowStepRun<
651
+ T,
652
+ TState,
653
+ TConnParams,
654
+ TConnState,
655
+ TVars,
656
+ TInput,
657
+ TDatabase,
658
+ TEvents,
659
+ TQueues
660
+ >,
661
+ ): Promise<TryStepResult<T>>;
662
+ tryStep<T>(
663
+ config: WorkflowTryStepConfig<
664
+ T,
665
+ TState,
666
+ TConnParams,
667
+ TConnState,
668
+ TVars,
669
+ TInput,
670
+ TDatabase,
671
+ TEvents,
672
+ TQueues
673
+ >,
674
+ ): Promise<TryStepResult<T>>;
262
675
  async tryStep<T>(
263
676
  nameOrConfig:
264
677
  | string
265
- | Parameters<WorkflowContextInterface["tryStep"]>[0],
266
- run?: () => Promise<T>,
678
+ | WorkflowTryStepConfig<
679
+ T,
680
+ TState,
681
+ TConnParams,
682
+ TConnState,
683
+ TVars,
684
+ TInput,
685
+ TDatabase,
686
+ TEvents,
687
+ TQueues
688
+ >,
689
+ run?: WorkflowStepRun<
690
+ T,
691
+ TState,
692
+ TConnParams,
693
+ TConnState,
694
+ TVars,
695
+ TInput,
696
+ TDatabase,
697
+ TEvents,
698
+ TQueues
699
+ >,
267
700
  ): Promise<TryStepResult<T>> {
268
701
  if (typeof nameOrConfig === "string") {
269
702
  if (!run) {
270
703
  throw new Error("Step run function missing");
271
704
  }
705
+ const stepRun = run;
272
706
  return await this.#wrapActive(() =>
273
- this.#inner.tryStep(nameOrConfig, () =>
274
- this.#withActorAccess(run),
275
- ),
707
+ this.#inner.tryStep(nameOrConfig, () => this.#runStep(stepRun)),
276
708
  );
277
709
  }
278
- const stepConfig = nameOrConfig as TryStepConfig<T>;
710
+ const stepConfig = nameOrConfig;
711
+ const rollback = stepConfig.rollback;
279
712
  const config: TryStepConfig<T> = {
280
713
  ...stepConfig,
281
- run: () => this.#withActorAccess(stepConfig.run),
714
+ run: () => this.#runStep(stepConfig.run),
715
+ rollback: rollback
716
+ ? (_ctx, output) => this.#runRollback(rollback, output)
717
+ : undefined,
282
718
  };
283
719
  return await this.#wrapActive(() => this.#inner.tryStep(config));
284
720
  }
285
721
 
722
+ try<T>(
723
+ name: string,
724
+ run: WorkflowContextRun<
725
+ T,
726
+ TState,
727
+ TConnParams,
728
+ TConnState,
729
+ TVars,
730
+ TInput,
731
+ TDatabase,
732
+ TEvents,
733
+ TQueues
734
+ >,
735
+ ): Promise<TryBlockResult<T>>;
736
+ try<T>(
737
+ config: WorkflowTryConfig<
738
+ T,
739
+ TState,
740
+ TConnParams,
741
+ TConnState,
742
+ TVars,
743
+ TInput,
744
+ TDatabase,
745
+ TEvents,
746
+ TQueues
747
+ >,
748
+ ): Promise<TryBlockResult<T>>;
286
749
  async try<T>(
287
- nameOrConfig: string | Parameters<WorkflowContextInterface["try"]>[0],
288
- run?: (
289
- ctx: ActorWorkflowContext<
290
- TState,
291
- TConnParams,
292
- TConnState,
293
- TVars,
294
- TInput,
295
- TDatabase,
296
- TEvents,
297
- TQueues
298
- >,
299
- ) => Promise<T>,
750
+ nameOrConfig:
751
+ | string
752
+ | WorkflowTryConfig<
753
+ T,
754
+ TState,
755
+ TConnParams,
756
+ TConnState,
757
+ TVars,
758
+ TInput,
759
+ TDatabase,
760
+ TEvents,
761
+ TQueues
762
+ >,
763
+ run?: WorkflowContextRun<
764
+ T,
765
+ TState,
766
+ TConnParams,
767
+ TConnState,
768
+ TVars,
769
+ TInput,
770
+ TDatabase,
771
+ TEvents,
772
+ TQueues
773
+ >,
300
774
  ): Promise<TryBlockResult<T>> {
301
775
  if (typeof nameOrConfig === "string") {
302
776
  if (!run) {
303
777
  throw new Error("Try run function missing");
304
778
  }
779
+ const tryRun = run;
305
780
  return await this.#wrapActive(() =>
306
781
  this.#inner.try(nameOrConfig, async (ctx) =>
307
- run(this.#createChildContext(ctx)),
782
+ tryRun(this.#createChildContext(ctx)),
308
783
  ),
309
784
  );
310
785
  }
311
- const tryConfig = nameOrConfig as TryBlockConfig<T>;
786
+ const tryConfig = nameOrConfig;
312
787
  const config: TryBlockConfig<T> = {
313
788
  ...tryConfig,
314
789
  run: async (ctx) => tryConfig.run(this.#createChildContext(ctx)),
@@ -316,10 +791,10 @@ export class ActorWorkflowContext<
316
791
  return await this.#wrapActive(() => this.#inner.try(config));
317
792
  }
318
793
 
319
- async loop<T>(
794
+ loop<T>(
320
795
  name: string,
321
796
  run: (
322
- ctx: ActorWorkflowContext<
797
+ ctx: WorkflowContext<
323
798
  TState,
324
799
  TConnParams,
325
800
  TConnState,
@@ -329,16 +804,10 @@ export class ActorWorkflowContext<
329
804
  TEvents,
330
805
  TQueues
331
806
  >,
332
- ) => Promise<LoopResult<undefined, T> | void>,
333
- ): Promise<T>;
334
- async loop<T>(
335
- name: string,
336
- run: (
337
- ctx: WorkflowContextInterface,
338
- ) => Promise<LoopResult<undefined, T> | void>,
807
+ ) => Promise<LoopResult<undefined, T> | undefined | void>,
339
808
  ): Promise<T>;
340
- async loop<S, T>(
341
- config: ActorWorkflowLoopConfig<
809
+ loop<S, T>(
810
+ config: WorkflowLoopConfig<
342
811
  S,
343
812
  T,
344
813
  TState,
@@ -351,12 +820,10 @@ export class ActorWorkflowContext<
351
820
  TQueues
352
821
  >,
353
822
  ): Promise<T>;
354
- async loop<S, T>(config: LoopConfig<S, T>): Promise<T>;
355
823
  async loop(
356
824
  nameOrConfig:
357
825
  | string
358
- | LoopConfig<any, any>
359
- | ActorWorkflowLoopConfig<
826
+ | WorkflowLoopConfig<
360
827
  any,
361
828
  any,
362
829
  TState,
@@ -369,7 +836,7 @@ export class ActorWorkflowContext<
369
836
  TQueues
370
837
  >,
371
838
  run?: (
372
- ctx: ActorWorkflowContext<
839
+ ctx: WorkflowContext<
373
840
  TState,
374
841
  TConnParams,
375
842
  TConnState,
@@ -379,22 +846,32 @@ export class ActorWorkflowContext<
379
846
  TEvents,
380
847
  TQueues
381
848
  >,
382
- ) => Promise<LoopResult<undefined, any> | void>,
849
+ ) => Promise<LoopResult<undefined, any> | undefined | void>,
383
850
  ): Promise<any> {
384
851
  if (typeof nameOrConfig === "string") {
385
852
  if (!run) {
386
853
  throw new Error("Loop run function missing");
387
854
  }
855
+ const loopRun = run;
388
856
  return await this.#wrapActive(() =>
389
- this.#inner.loop(nameOrConfig, async (ctx) =>
390
- run(this.#createChildContext(ctx)),
857
+ this.#inner.loop(
858
+ nameOrConfig,
859
+ // A void return (no explicit Loop result) is undefined at
860
+ // runtime, which the engine treats as continue.
861
+ async (
862
+ ctx,
863
+ ): Promise<LoopResult<undefined, any> | undefined> =>
864
+ (await loopRun(this.#createChildContext(ctx))) ??
865
+ undefined,
391
866
  ),
392
867
  );
393
868
  }
869
+ const loopConfig = nameOrConfig;
394
870
  const wrapped: LoopConfig<any, any> = {
395
- ...nameOrConfig,
396
- run: async (ctx, state) =>
397
- nameOrConfig.run(this.#createChildContext(ctx), state),
871
+ ...loopConfig,
872
+ run: (async (ctx, state) =>
873
+ (await loopConfig.run(this.#createChildContext(ctx), state)) ??
874
+ undefined) as LoopConfig<any, any>["run"],
398
875
  };
399
876
  return await this.#wrapActive(() => this.#inner.loop(wrapped));
400
877
  }
@@ -407,11 +884,6 @@ export class ActorWorkflowContext<
407
884
  return this.#inner.sleepUntil(name, timestampMs);
408
885
  }
409
886
 
410
- destroy(): void {
411
- this.#ensureActorAccess("destroy");
412
- this.#runCtx.destroy();
413
- }
414
-
415
887
  async rollbackCheckpoint(name: string): Promise<void> {
416
888
  await this.#wrapActive(() => this.#inner.rollbackCheckpoint(name));
417
889
  }
@@ -419,7 +891,7 @@ export class ActorWorkflowContext<
419
891
  async join<
420
892
  T extends Record<
421
893
  string,
422
- ActorWorkflowBranchConfig<
894
+ WorkflowBranchConfig<
423
895
  unknown,
424
896
  TState,
425
897
  TConnParams,
@@ -439,7 +911,10 @@ export class ActorWorkflowContext<
439
911
  name: string,
440
912
  branches: T,
441
913
  ): Promise<{ [K in keyof T]: BranchOutput<T[K]> }>;
442
- async join(name: string, branches: Record<string, BranchConfig<unknown>>) {
914
+ async join(
915
+ name: string,
916
+ branches: Record<string, { run: (ctx: any) => Promise<unknown> }>,
917
+ ) {
443
918
  const wrappedBranches = Object.fromEntries(
444
919
  Object.entries(branches).map(([key, branch]) => [
445
920
  key,
@@ -458,25 +933,17 @@ export class ActorWorkflowContext<
458
933
  name: string,
459
934
  branches: Array<{
460
935
  name: string;
461
- run: (
462
- ctx: ActorWorkflowContext<
463
- TState,
464
- TConnParams,
465
- TConnState,
466
- TVars,
467
- TInput,
468
- TDatabase,
469
- TEvents,
470
- TQueues
471
- >,
472
- ) => Promise<T>;
473
- }>,
474
- ): Promise<{ winner: string; value: T }>;
475
- async race<T>(
476
- name: string,
477
- branches: Array<{
478
- name: string;
479
- run: (ctx: WorkflowContextInterface) => Promise<T>;
936
+ run: WorkflowContextRun<
937
+ T,
938
+ TState,
939
+ TConnParams,
940
+ TConnState,
941
+ TVars,
942
+ TInput,
943
+ TDatabase,
944
+ TEvents,
945
+ TQueues
946
+ >;
480
947
  }>,
481
948
  ): Promise<{ winner: string; value: T }> {
482
949
  const wrappedBranches = branches.map((branch) => ({
@@ -497,82 +964,58 @@ export class ActorWorkflowContext<
497
964
  return this.#inner.isEvicted();
498
965
  }
499
966
 
500
- get state(): TState extends never ? never : TState {
501
- this.#ensureActorAccess("state");
502
- return this.#runCtx.state as TState extends never ? never : TState;
503
- }
504
-
505
- get vars(): TVars extends never ? never : TVars {
506
- this.#ensureActorAccess("vars");
507
- return this.#runCtx.vars as TVars extends never ? never : TVars;
508
- }
509
-
510
- client<R extends Registry<any> = Registry<any>>(): Client<R> {
511
- this.#ensureActorAccess("client");
512
- return this.#runCtx.client<R>();
513
- }
514
-
515
- get db(): TDatabase extends never ? never : InferDatabaseClient<TDatabase> {
516
- this.#ensureActorAccess("db");
517
- return this.#runCtx.db as TDatabase extends never
518
- ? never
519
- : InferDatabaseClient<TDatabase>;
520
- }
521
-
522
- get log() {
523
- return this.#runCtx.log;
524
- }
525
-
526
- /** @deprecated No-op. Use `keepAwake(promise)` or `waitUntil(promise)` instead. */
527
- setPreventSleep(_prevent: boolean): void {
528
- this.#ensureActorAccess("setPreventSleep");
529
- }
530
-
531
- /** @deprecated No-op. Always returns `false`. */
532
- get preventSleep(): boolean {
533
- this.#ensureActorAccess("preventSleep");
534
- return false;
535
- }
536
-
537
- /**
538
- * Holds the actor awake for the duration of the provided promise. The
539
- * actor cannot idle-sleep or finalize the sleep grace period until the
540
- * promise settles.
541
- */
542
- keepAwake<T>(promise: Promise<T>): Promise<T> {
543
- this.#ensureActorAccess("keepAwake");
544
- return this.#runCtx.keepAwake(promise);
545
- }
546
-
547
- /**
548
- * Registers a promise that the sleep grace period will wait on. Use this
549
- * for best-effort flush/cleanup work that may complete inside the grace
550
- * window. For work the actor must stay running through, prefer
551
- * `c.keepAwake(promise)` which also blocks idle sleep.
552
- */
553
- waitUntil(promise: Promise<void>): void {
554
- this.#ensureActorAccess("waitUntil");
555
- this.#runCtx.waitUntil(promise);
556
- }
967
+ // Runs a user step body inside a fresh step context, snapshotting actor
968
+ // state/vars so a thrown step rolls back its mutations, and deactivating the
969
+ // step context once the body settles so it cannot be used after the step.
970
+ async #runStep<T>(
971
+ run: WorkflowStepRun<
972
+ T,
973
+ TState,
974
+ TConnParams,
975
+ TConnState,
976
+ TVars,
977
+ TInput,
978
+ TDatabase,
979
+ TEvents,
980
+ TQueues
981
+ >,
982
+ ): Promise<T> {
983
+ const stepCtx = new WorkflowStepContext<
984
+ TState,
985
+ TConnParams,
986
+ TConnState,
987
+ TVars,
988
+ TInput,
989
+ TDatabase,
990
+ TEvents,
991
+ TQueues
992
+ >(this.#runCtx, () => this.#markGuardTriggered());
557
993
 
558
- get actorId(): string {
559
- return this.#runCtx.actorId;
560
- }
994
+ let stateSnapshot: { state: TState } | null = null;
995
+ try {
996
+ stateSnapshot = { state: this.#runCtx[RAW_STATE_SYMBOL]() };
997
+ } catch (error) {
998
+ this.#runCtx.log.debug({
999
+ msg: "failed to get state, likely due to being stateless workflow",
1000
+ error,
1001
+ });
1002
+ }
1003
+ if (stateSnapshot) {
1004
+ stateSnapshot.state = structuredClone(stateSnapshot.state);
1005
+ }
1006
+ const varsSnapshot = structuredClone(this.#runCtx.vars);
561
1007
 
562
- broadcast<K extends keyof TEvents & string>(
563
- name: K,
564
- ...args: InferEventArgs<InferSchemaMap<TEvents>[K]>
565
- ): void;
566
- broadcast(
567
- name: keyof TEvents extends never ? string : never,
568
- ...args: Array<unknown>
569
- ): void;
570
- broadcast(name: string, ...args: Array<unknown>): void {
571
- this.#ensureActorAccess("broadcast");
572
- this.#runCtx.broadcast(
573
- name as never,
574
- ...(args as unknown[] as never[]),
575
- );
1008
+ try {
1009
+ return await run(stepCtx);
1010
+ } catch (error) {
1011
+ if (stateSnapshot) {
1012
+ this.#runCtx.state = stateSnapshot.state;
1013
+ }
1014
+ this.#runCtx.vars = varsSnapshot;
1015
+ throw error;
1016
+ } finally {
1017
+ stepCtx[DEACTIVATE_STEP]();
1018
+ }
576
1019
  }
577
1020
 
578
1021
  #toActorQueueMessage<T>(
@@ -593,41 +1036,45 @@ export class ActorWorkflowContext<
593
1036
  };
594
1037
  }
595
1038
 
596
- async #wrapActive<T>(run: () => Promise<T>): Promise<T> {
597
- return await this.#runCtx.internalKeepAwake(run);
598
- }
599
-
600
- async #withActorAccess<T>(run: () => Promise<T>): Promise<T> {
601
- this.#actorAccessDepth++;
602
- if (this.#actorAccessDepth === 1) {
603
- this.#allowActorAccess = true;
604
- }
1039
+ // Runs a step rollback compensation with an active step context. Rollbacks
1040
+ // intentionally mutate actor state, so their writes are not snapshotted.
1041
+ async #runRollback<T>(
1042
+ rollback: WorkflowStepRollback<
1043
+ T,
1044
+ TState,
1045
+ TConnParams,
1046
+ TConnState,
1047
+ TVars,
1048
+ TInput,
1049
+ TDatabase,
1050
+ TEvents,
1051
+ TQueues
1052
+ >,
1053
+ output: T,
1054
+ ): Promise<void> {
1055
+ const stepCtx = new WorkflowStepContext<
1056
+ TState,
1057
+ TConnParams,
1058
+ TConnState,
1059
+ TVars,
1060
+ TInput,
1061
+ TDatabase,
1062
+ TEvents,
1063
+ TQueues
1064
+ >(this.#runCtx, () => this.#markGuardTriggered());
605
1065
  try {
606
- return await run();
1066
+ await rollback(stepCtx, output);
607
1067
  } finally {
608
- this.#actorAccessDepth--;
609
- if (this.#actorAccessDepth === 0) {
610
- this.#allowActorAccess = false;
611
- }
612
- }
613
- }
614
-
615
- #ensureActorAccess(feature: string): void {
616
- if (!this.#allowActorAccess) {
617
- this.#guardViolation = true;
618
- this.#markGuardTriggered();
619
- throw new Error(
620
- `${feature} is only available inside workflow steps`,
621
- );
1068
+ stepCtx[DEACTIVATE_STEP]();
622
1069
  }
623
1070
  }
624
1071
 
625
- consumeGuardViolation(): boolean {
626
- const violated = this.#guardViolation;
627
- this.#guardViolation = false;
628
- return violated;
1072
+ async #wrapActive<T>(run: () => Promise<T>): Promise<T> {
1073
+ return await this.#runCtx.internalKeepAwake(run);
629
1074
  }
630
1075
 
1076
+ // Records that a step context was used outside its step. Mirrors the value
1077
+ // onto actor state and a KV flag so callers can observe the violation.
631
1078
  #markGuardTriggered(): void {
632
1079
  try {
633
1080
  const state = this.#runCtx.state as Record<string, unknown>;
@@ -658,7 +1105,7 @@ export class ActorWorkflowContext<
658
1105
 
659
1106
  #createChildContext(
660
1107
  ctx: WorkflowContextInterface,
661
- ): ActorWorkflowContext<
1108
+ ): WorkflowContext<
662
1109
  TState,
663
1110
  TConnParams,
664
1111
  TConnState,
@@ -668,7 +1115,7 @@ export class ActorWorkflowContext<
668
1115
  TEvents,
669
1116
  TQueues
670
1117
  > {
671
- return new ActorWorkflowContext(ctx, this.#runCtx);
1118
+ return new WorkflowContext(ctx, this.#runCtx);
672
1119
  }
673
1120
  }
674
1121
 
@@ -684,7 +1131,7 @@ export type WorkflowContextOf<AD extends AnyActorDefinition> =
684
1131
  infer Q extends QueueSchemaConfig,
685
1132
  any
686
1133
  >
687
- ? ActorWorkflowContext<S, CP, CS, V, I, DB, E, Q>
1134
+ ? WorkflowContext<S, CP, CS, V, I, DB, E, Q>
688
1135
  : never;
689
1136
 
690
1137
  export type WorkflowLoopContextOf<AD extends AnyActorDefinition> =
@@ -694,4 +1141,16 @@ export type WorkflowBranchContextOf<AD extends AnyActorDefinition> =
694
1141
  WorkflowContextOf<AD>;
695
1142
 
696
1143
  export type WorkflowStepContextOf<AD extends AnyActorDefinition> =
697
- WorkflowContextOf<AD>;
1144
+ AD extends BaseActorDefinition<
1145
+ infer S,
1146
+ infer CP,
1147
+ infer CS,
1148
+ infer V,
1149
+ infer I,
1150
+ infer DB extends AnyDatabaseProvider,
1151
+ infer E extends EventSchemaConfig,
1152
+ infer Q extends QueueSchemaConfig,
1153
+ any
1154
+ >
1155
+ ? WorkflowStepContext<S, CP, CS, V, I, DB, E, Q>
1156
+ : never;