rivetkit 0.0.0-skip-ready-wait-flatten-client-options.1cae221 → 0.0.0-sqlite-uds.4e59a38

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 (253) hide show
  1. package/dist/browser/client.d.ts +561 -89
  2. package/dist/browser/client.js +1063 -430
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.d.ts +22 -2
  5. package/dist/browser/inspector/client.js +1036 -232
  6. package/dist/browser/inspector/client.js.map +1 -1
  7. package/dist/tsup/actor/errors.cjs +6 -2
  8. package/dist/tsup/actor/errors.cjs.map +1 -1
  9. package/dist/tsup/actor/errors.d.cts +1 -74
  10. package/dist/tsup/actor/errors.d.ts +1 -74
  11. package/dist/tsup/actor/errors.js +5 -1
  12. package/dist/tsup/agent-os/index.cjs +2218 -2082
  13. package/dist/tsup/agent-os/index.cjs.map +1 -1
  14. package/dist/tsup/agent-os/index.d.cts +556 -85
  15. package/dist/tsup/agent-os/index.d.ts +556 -85
  16. package/dist/tsup/agent-os/index.js +2220 -2084
  17. package/dist/tsup/agent-os/index.js.map +1 -1
  18. package/dist/tsup/{chunk-NFC5VU36.cjs → chunk-3GC3EP6D.cjs} +18 -10
  19. package/dist/tsup/chunk-3GC3EP6D.cjs.map +1 -0
  20. package/dist/tsup/{chunk-7MRGNVSR.js → chunk-3GLNEWGY.js} +78 -6
  21. package/dist/tsup/chunk-3GLNEWGY.js.map +1 -0
  22. package/dist/tsup/{chunk-V3QNBJ7N.cjs → chunk-4FC7TVS6.cjs} +35 -10
  23. package/dist/tsup/chunk-4FC7TVS6.cjs.map +1 -0
  24. package/dist/tsup/{chunk-POTPHU3P.cjs → chunk-62LSMTP2.cjs} +3 -3
  25. package/dist/tsup/{chunk-POTPHU3P.cjs.map → chunk-62LSMTP2.cjs.map} +1 -1
  26. package/dist/tsup/{chunk-OIKOPSXQ.js → chunk-7IVUT2JT.js} +12 -4
  27. package/dist/tsup/chunk-7IVUT2JT.js.map +1 -0
  28. package/dist/tsup/{chunk-22XU3BVY.cjs → chunk-GEYQLGXC.cjs} +925 -328
  29. package/dist/tsup/chunk-GEYQLGXC.cjs.map +1 -0
  30. package/dist/tsup/{chunk-D2TLG75Y.cjs → chunk-GMN45CQ6.cjs} +10 -10
  31. package/dist/tsup/chunk-GMN45CQ6.cjs.map +1 -0
  32. package/dist/tsup/{chunk-3BFYSYRU.js → chunk-HXUEHHJF.js} +3 -2
  33. package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
  34. package/dist/tsup/{chunk-IOYKCB6Y.cjs → chunk-I336PMWT.cjs} +44 -9
  35. package/dist/tsup/chunk-I336PMWT.cjs.map +1 -0
  36. package/dist/tsup/{chunk-RZEJJJKU.js → chunk-IB73AMGJ.js} +42 -7
  37. package/dist/tsup/chunk-IB73AMGJ.js.map +1 -0
  38. package/dist/tsup/{chunk-4ZIWB4CQ.js → chunk-ITWJ6Y7G.js} +2 -2
  39. package/dist/tsup/{chunk-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
  40. package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
  41. package/dist/tsup/{chunk-W54QCENI.js → chunk-KTNBYGRU.js} +134 -20
  42. package/dist/tsup/chunk-KTNBYGRU.js.map +1 -0
  43. package/dist/tsup/{chunk-AK57AL7S.cjs → chunk-OAPVVVTX.cjs} +79 -7
  44. package/dist/tsup/chunk-OAPVVVTX.cjs.map +1 -0
  45. package/dist/tsup/{chunk-TPBHXFB2.cjs → chunk-OUDV3ITX.cjs} +138 -24
  46. package/dist/tsup/chunk-OUDV3ITX.cjs.map +1 -0
  47. package/dist/tsup/{chunk-XNZR7UD2.cjs → chunk-PRXTIERO.cjs} +90 -65
  48. package/dist/tsup/chunk-PRXTIERO.cjs.map +1 -0
  49. package/dist/tsup/{chunk-LLD2D5LO.cjs → chunk-VE2X4KMG.cjs} +3 -2
  50. package/dist/tsup/chunk-VE2X4KMG.cjs.map +1 -0
  51. package/dist/tsup/{chunk-KSG2COSQ.js → chunk-WRZEVVLL.js} +6 -6
  52. package/dist/tsup/chunk-WRZEVVLL.js.map +1 -0
  53. package/dist/tsup/{chunk-LNMB25HW.js → chunk-XAIMHUPG.js} +780 -183
  54. package/dist/tsup/chunk-XAIMHUPG.js.map +1 -0
  55. package/dist/tsup/{chunk-D4TSTM6C.js → chunk-XZ62SWSC.js} +83 -58
  56. package/dist/tsup/chunk-XZ62SWSC.js.map +1 -0
  57. package/dist/tsup/{chunk-2NDZ7JCR.cjs → chunk-ZA7FLHKH.cjs} +1 -1
  58. package/dist/tsup/chunk-ZA7FLHKH.cjs.map +1 -0
  59. package/dist/tsup/{chunk-K34B3OVG.js → chunk-ZZ3WBRPD.js} +34 -9
  60. package/dist/tsup/chunk-ZZ3WBRPD.js.map +1 -0
  61. package/dist/tsup/client/mod.cjs +9 -9
  62. package/dist/tsup/client/mod.cjs.map +1 -1
  63. package/dist/tsup/client/mod.d.cts +8 -9
  64. package/dist/tsup/client/mod.d.ts +8 -9
  65. package/dist/tsup/client/mod.js +8 -8
  66. package/dist/tsup/common/log.cjs +5 -3
  67. package/dist/tsup/common/log.cjs.map +1 -1
  68. package/dist/tsup/common/log.d.cts +5 -1
  69. package/dist/tsup/common/log.d.ts +5 -1
  70. package/dist/tsup/common/log.js +6 -4
  71. package/dist/tsup/common/websocket.cjs +4 -4
  72. package/dist/tsup/common/websocket.js +3 -3
  73. package/dist/tsup/{config-CRdGwwbr.d.cts → config-CxG53eQo.d.cts} +577 -36
  74. package/dist/tsup/{config-kxXbtrJU.d.ts → config-DLOxy81E.d.cts} +5 -5
  75. package/dist/tsup/{config-kxXbtrJU.d.cts → config-DLOxy81E.d.ts} +5 -5
  76. package/dist/tsup/{config-DIpBWm5C.d.ts → config-Ds6DCRhV.d.ts} +577 -36
  77. package/dist/tsup/context-8KlcOYIs.d.cts +129 -0
  78. package/dist/tsup/context-Cfbm4QLr.d.ts +129 -0
  79. package/dist/tsup/db/drizzle.cjs +151 -79
  80. package/dist/tsup/db/drizzle.cjs.map +1 -1
  81. package/dist/tsup/db/drizzle.d.cts +2 -2
  82. package/dist/tsup/db/drizzle.d.ts +2 -2
  83. package/dist/tsup/db/drizzle.js +151 -79
  84. package/dist/tsup/db/drizzle.js.map +1 -1
  85. package/dist/tsup/db/mod.cjs +79 -24
  86. package/dist/tsup/db/mod.cjs.map +1 -1
  87. package/dist/tsup/db/mod.d.cts +2 -2
  88. package/dist/tsup/db/mod.d.ts +2 -2
  89. package/dist/tsup/db/mod.js +78 -23
  90. package/dist/tsup/db/mod.js.map +1 -1
  91. package/dist/tsup/dynamic/mod.cjs +24 -0
  92. package/dist/tsup/dynamic/mod.cjs.map +1 -0
  93. package/dist/tsup/dynamic/mod.d.cts +37 -0
  94. package/dist/tsup/dynamic/mod.d.ts +37 -0
  95. package/dist/tsup/dynamic/mod.js +24 -0
  96. package/dist/tsup/dynamic/mod.js.map +1 -0
  97. package/dist/tsup/inspector/mod.cjs +47 -12
  98. package/dist/tsup/inspector/mod.cjs.map +1 -1
  99. package/dist/tsup/inspector/mod.d.cts +37 -15
  100. package/dist/tsup/inspector/mod.d.ts +37 -15
  101. package/dist/tsup/inspector/mod.js +46 -11
  102. package/dist/tsup/inspector/mod.js.map +1 -1
  103. package/dist/tsup/inspector-tab/mod.cjs +162 -0
  104. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  105. package/dist/tsup/inspector-tab/mod.d.cts +240 -0
  106. package/dist/tsup/inspector-tab/mod.d.ts +240 -0
  107. package/dist/tsup/inspector-tab/mod.js +162 -0
  108. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  109. package/dist/tsup/mod.cjs +1078 -479
  110. package/dist/tsup/mod.cjs.map +1 -1
  111. package/dist/tsup/mod.d.cts +5 -6
  112. package/dist/tsup/mod.d.ts +5 -6
  113. package/dist/tsup/mod.js +996 -397
  114. package/dist/tsup/mod.js.map +1 -1
  115. package/dist/tsup/test/mod.cjs +21 -18
  116. package/dist/tsup/test/mod.cjs.map +1 -1
  117. package/dist/tsup/test/mod.d.cts +4 -5
  118. package/dist/tsup/test/mod.d.ts +4 -5
  119. package/dist/tsup/test/mod.js +18 -15
  120. package/dist/tsup/test/mod.js.map +1 -1
  121. package/dist/tsup/utils-CqDnC_PS.d.cts +104 -0
  122. package/dist/tsup/utils-CqDnC_PS.d.ts +104 -0
  123. package/dist/tsup/utils.cjs +3 -3
  124. package/dist/tsup/utils.d.cts +1 -1
  125. package/dist/tsup/utils.d.ts +1 -1
  126. package/dist/tsup/utils.js +2 -2
  127. package/dist/tsup/workflow/mod.cjs +386 -322
  128. package/dist/tsup/workflow/mod.cjs.map +1 -1
  129. package/dist/tsup/workflow/mod.d.cts +8 -9
  130. package/dist/tsup/workflow/mod.d.ts +8 -9
  131. package/dist/tsup/workflow/mod.js +363 -299
  132. package/dist/tsup/workflow/mod.js.map +1 -1
  133. package/package.json +35 -14
  134. package/src/actor/config.ts +188 -59
  135. package/src/actor/contexts/index.ts +7 -2
  136. package/src/actor/definition.ts +17 -19
  137. package/src/actor/driver.ts +3 -3
  138. package/src/actor/errors.ts +70 -7
  139. package/src/actor/instance/mod.ts +39 -56
  140. package/src/actor/keys.ts +2 -1
  141. package/src/actor/mod.ts +22 -20
  142. package/src/actor/schema.ts +2 -2
  143. package/src/agent-os/actor/index.ts +38 -18
  144. package/src/agent-os/actor/preview.ts +1 -2
  145. package/src/agent-os/actor/session.ts +2 -2
  146. package/src/agent-os/config.ts +1 -1
  147. package/src/agent-os/fs/database-vfs.ts +1 -1
  148. package/src/agent-os/index.ts +16 -15
  149. package/src/client/actor-common.ts +88 -62
  150. package/src/client/actor-conn.ts +58 -63
  151. package/src/client/actor-handle.ts +125 -71
  152. package/src/client/actor-query.ts +5 -5
  153. package/src/client/config.ts +3 -3
  154. package/src/client/errors.ts +2 -1
  155. package/src/client/lifecycle-errors.ts +2 -4
  156. package/src/client/query.ts +1 -1
  157. package/src/client/queue.ts +8 -3
  158. package/src/client/raw-utils.ts +10 -10
  159. package/src/client/resolve-gateway-target.ts +1 -1
  160. package/src/client/utils.ts +34 -10
  161. package/src/common/actor-router-consts.ts +7 -4
  162. package/src/common/actor-websocket.ts +3 -1
  163. package/src/common/bare/actor-persist/v1.ts +205 -163
  164. package/src/common/bare/actor-persist/v2.ts +265 -213
  165. package/src/common/bare/actor-persist/v3.ts +176 -172
  166. package/src/common/bare/actor-persist/v4.ts +254 -253
  167. package/src/common/bare/generated/client-protocol/v4.ts +599 -0
  168. package/src/common/bare/generated/inspector/v5.ts +1016 -0
  169. package/src/common/bare/transport/v1.ts +694 -542
  170. package/src/common/client-protocol-versioned.ts +176 -67
  171. package/src/common/client-protocol-zod.ts +7 -0
  172. package/src/common/client-protocol.ts +1 -1
  173. package/src/common/database/config.ts +16 -5
  174. package/src/common/database/mod.test.ts +83 -16
  175. package/src/common/database/mod.ts +86 -30
  176. package/src/common/database/native-database.test.ts +35 -22
  177. package/src/common/database/native-database.ts +26 -10
  178. package/src/common/database/shared.ts +1 -0
  179. package/src/common/encoding.ts +250 -16
  180. package/src/common/engine.ts +28 -1
  181. package/src/common/eventsource.ts +1 -1
  182. package/src/common/inline-websocket-adapter.ts +14 -13
  183. package/src/common/log.ts +15 -8
  184. package/src/common/router.ts +49 -23
  185. package/src/common/utils.ts +10 -202
  186. package/src/common/websocket-interface.ts +1 -1
  187. package/src/db/drizzle.ts +173 -96
  188. package/src/db/mod.ts +1 -1
  189. package/src/devtools-loader/index.ts +4 -7
  190. package/src/devtools-loader/serve-devtools.ts +26 -0
  191. package/src/drivers/engine/actor-driver.ts +76 -73
  192. package/src/dynamic/instance.ts +32 -0
  193. package/src/dynamic/internal.ts +50 -0
  194. package/src/dynamic/isolate-runtime.ts +66 -0
  195. package/src/dynamic/mod.ts +32 -0
  196. package/src/engine-client/actor-http-client.ts +6 -9
  197. package/src/engine-client/actor-websocket-client.ts +14 -13
  198. package/src/engine-client/api-endpoints.ts +51 -2
  199. package/src/engine-client/api-utils.ts +2 -2
  200. package/src/engine-client/driver.ts +3 -4
  201. package/src/engine-client/mod.ts +17 -10
  202. package/src/engine-client/ws-proxy.ts +9 -4
  203. package/src/inspector/client.browser.ts +66 -15
  204. package/src/inspector/mod.ts +2 -4
  205. package/src/inspector-tab/mod.ts +300 -0
  206. package/src/registry/config/envoy.ts +1 -2
  207. package/src/registry/config/index.ts +46 -20
  208. package/src/registry/index.ts +364 -87
  209. package/src/registry/napi-runtime.ts +97 -8
  210. package/src/registry/native-validation.ts +10 -12
  211. package/src/registry/native.ts +592 -343
  212. package/src/registry/process-metrics.ts +250 -0
  213. package/src/registry/runtime.ts +85 -6
  214. package/src/registry/wasm-runtime.ts +72 -3
  215. package/src/registry/write-through-proxy.ts +40 -0
  216. package/src/serde.ts +2 -2
  217. package/src/serverless/configure.ts +19 -8
  218. package/src/test/mod.ts +11 -8
  219. package/src/utils/crypto.ts +14 -0
  220. package/src/utils/endpoint-parser.ts +1 -1
  221. package/src/utils/env-vars.ts +37 -0
  222. package/src/utils/router.ts +1 -1
  223. package/src/utils.ts +1 -2
  224. package/src/workflow/context.ts +703 -240
  225. package/src/workflow/driver.ts +23 -12
  226. package/src/workflow/inspector.ts +12 -3
  227. package/src/workflow/mod.ts +37 -23
  228. package/dist/tsup/chunk-22XU3BVY.cjs.map +0 -1
  229. package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
  230. package/dist/tsup/chunk-3BFYSYRU.js.map +0 -1
  231. package/dist/tsup/chunk-7MRGNVSR.js.map +0 -1
  232. package/dist/tsup/chunk-AK57AL7S.cjs.map +0 -1
  233. package/dist/tsup/chunk-D2TLG75Y.cjs.map +0 -1
  234. package/dist/tsup/chunk-D4TSTM6C.js.map +0 -1
  235. package/dist/tsup/chunk-IOYKCB6Y.cjs.map +0 -1
  236. package/dist/tsup/chunk-K34B3OVG.js.map +0 -1
  237. package/dist/tsup/chunk-KSG2COSQ.js.map +0 -1
  238. package/dist/tsup/chunk-LLD2D5LO.cjs.map +0 -1
  239. package/dist/tsup/chunk-LNMB25HW.js.map +0 -1
  240. package/dist/tsup/chunk-NFC5VU36.cjs.map +0 -1
  241. package/dist/tsup/chunk-OIKOPSXQ.js.map +0 -1
  242. package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
  243. package/dist/tsup/chunk-RZEJJJKU.js.map +0 -1
  244. package/dist/tsup/chunk-TPBHXFB2.cjs.map +0 -1
  245. package/dist/tsup/chunk-V3QNBJ7N.cjs.map +0 -1
  246. package/dist/tsup/chunk-W54QCENI.js.map +0 -1
  247. package/dist/tsup/chunk-XNZR7UD2.cjs.map +0 -1
  248. package/dist/tsup/context-B7G6sk7x.d.ts +0 -92
  249. package/dist/tsup/context-DzMRHkjC.d.cts +0 -92
  250. package/dist/tsup/utils-fwx3o3K9.d.cts +0 -18
  251. package/dist/tsup/utils-fwx3o3K9.d.ts +0 -18
  252. package/src/utils/serve.ts +0 -217
  253. /package/dist/tsup/{chunk-4ZIWB4CQ.js.map → chunk-ITWJ6Y7G.js.map} +0 -0
package/dist/tsup/mod.js CHANGED
@@ -1,28 +1,26 @@
1
+ import {
2
+ decodeWorkflowHistoryTransport
3
+ } from "./chunk-IB73AMGJ.js";
1
4
  import {
2
5
  ACTOR_CONTEXT_INTERNAL_SYMBOL,
3
6
  ActorConfigSchema,
4
7
  CONN_STATE_MANAGER_SYMBOL,
8
+ RAW_STATE_SYMBOL,
9
+ disposeRunInspector,
5
10
  getRunFunction,
6
11
  getRunInspectorConfig,
7
12
  getRunMetadata
8
- } from "./chunk-7MRGNVSR.js";
9
- import {
10
- decodeWorkflowHistoryTransport
11
- } from "./chunk-RZEJJJKU.js";
13
+ } from "./chunk-3GLNEWGY.js";
12
14
  import {
13
15
  ALLOWED_PUBLIC_HEADERS,
14
- CURRENT_VERSION,
15
16
  HEADER_CONN_PARAMS,
16
- HEADER_ENCODING,
17
- HTTP_RESPONSE_ERROR_VERSIONED,
18
- HttpResponseErrorSchema,
19
17
  RemoteEngineControlClient,
20
18
  convertRegistryConfigToClientConfig,
21
19
  createClientWithDriver,
22
20
  getDatacenters,
23
21
  tryParseEndpoint,
24
22
  updateRunnerConfig
25
- } from "./chunk-LNMB25HW.js";
23
+ } from "./chunk-XAIMHUPG.js";
26
24
  import {
27
25
  KEYS,
28
26
  makePrefixedKey,
@@ -30,18 +28,18 @@ import {
30
28
  queueMetadataKey,
31
29
  removePrefixFromKey,
32
30
  workflowStoragePrefix
33
- } from "./chunk-3BFYSYRU.js";
31
+ } from "./chunk-HXUEHHJF.js";
34
32
  import {
35
- contentTypeForEncoding,
33
+ assertJsonCompatValue,
36
34
  decodeCborCompat,
37
- decodeCborJsonCompat,
38
- encodeCborCompat,
39
- serializeWithEncoding
40
- } from "./chunk-W54QCENI.js";
41
- import "./chunk-4ZIWB4CQ.js";
35
+ encodeCborCompat
36
+ } from "./chunk-KTNBYGRU.js";
37
+ import "./chunk-JZ7TWV65.js";
38
+ import "./chunk-ITWJ6Y7G.js";
42
39
  import {
43
40
  LogLevelSchema,
44
41
  VERSION,
42
+ configureBaseLogger,
45
43
  deconstructError,
46
44
  getEnvUniversal,
47
45
  getLogger,
@@ -54,15 +52,20 @@ import {
54
52
  getRivetPublicEndpoint,
55
53
  getRivetPublicToken,
56
54
  getRivetRunEngine,
55
+ getRivetRunEngineHost,
56
+ getRivetRunEnginePort,
57
57
  getRivetRunEngineVersion,
58
58
  getRivetToken,
59
59
  getRivetTotalSlots,
60
+ getRivetkitPublicDir,
60
61
  getRivetkitRuntime,
62
+ getRivetkitRuntimeMode,
61
63
  isDev,
62
64
  noopNext,
65
+ parsePortEnv,
63
66
  stringifyError,
64
67
  toUint8Array
65
- } from "./chunk-D4TSTM6C.js";
68
+ } from "./chunk-XZ62SWSC.js";
66
69
  import {
67
70
  INTERNAL_ERROR_CODE,
68
71
  RivetError,
@@ -70,11 +73,11 @@ import {
70
73
  decodeBridgeRivetError,
71
74
  encodeBridgeRivetError,
72
75
  forbiddenError,
76
+ isActorAbortedError,
73
77
  isRivetErrorLike,
74
78
  toRivetError,
75
79
  unsupportedFeature
76
- } from "./chunk-K34B3OVG.js";
77
- import "./chunk-PCBNKI2J.js";
80
+ } from "./chunk-ZZ3WBRPD.js";
78
81
 
79
82
  // src/actor/log.ts
80
83
  function loggerWithoutContext() {
@@ -146,7 +149,7 @@ function hasSchemaConfigKey(schemas, key) {
146
149
  if (!schemas) {
147
150
  return false;
148
151
  }
149
- return Object.prototype.hasOwnProperty.call(schemas, key);
152
+ return Object.hasOwn(schemas, key);
150
153
  }
151
154
  function getEventCanSubscribe(schemas, key) {
152
155
  const schema = schemas == null ? void 0 : schemas[key];
@@ -207,8 +210,8 @@ function validateSchemaSync(schemas, key, data) {
207
210
  }
208
211
 
209
212
  // src/common/inline-websocket-adapter.ts
210
- import { WSContext } from "hono/ws";
211
213
  import { VirtualWebSocket } from "@rivetkit/virtual-websocket";
214
+ import { WSContext } from "hono/ws";
212
215
  function logger() {
213
216
  return getLogger("inline-websocket-adapter");
214
217
  }
@@ -320,24 +323,24 @@ var InlineWebSocketAdapter = class {
320
323
  this.#close(1011, "Internal error during initialization");
321
324
  }
322
325
  }
323
- #handleError(err) {
324
- console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", err);
326
+ #handleError(error) {
327
+ console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", error);
325
328
  logger().error({
326
329
  msg: "error in websocket",
327
- error: err,
328
- errorMessage: err instanceof Error ? err.message : String(err),
329
- stack: err instanceof Error ? err.stack : void 0
330
+ error,
331
+ errorMessage: error instanceof Error ? error.message : String(error),
332
+ stack: error instanceof Error ? error.stack : void 0
330
333
  });
331
334
  try {
332
- this.#handler.onError(err, this.#wsContext);
333
- } catch (handlerErr) {
335
+ this.#handler.onError(error, this.#wsContext);
336
+ } catch (error2) {
334
337
  logger().error({
335
338
  msg: "error in onError handler",
336
- error: handlerErr
339
+ error: error2
337
340
  });
338
341
  }
339
- this.#clientWs.triggerError(err);
340
- this.#actorWs.triggerError(err);
342
+ this.#clientWs.triggerError(error);
343
+ this.#actorWs.triggerError(error);
341
344
  }
342
345
  #close(code, reason) {
343
346
  if (this.#readyState === 3 || this.#readyState === 2) {
@@ -350,8 +353,8 @@ var InlineWebSocketAdapter = class {
350
353
  { code, reason, wasClean: true },
351
354
  this.#wsContext
352
355
  );
353
- } catch (err) {
354
- logger().error({ msg: "error closing websocket", error: err });
356
+ } catch (error) {
357
+ logger().error({ msg: "error closing websocket", error });
355
358
  } finally {
356
359
  this.#readyState = 3;
357
360
  this.#clientWs.triggerClose(code, reason);
@@ -361,8 +364,23 @@ var InlineWebSocketAdapter = class {
361
364
  };
362
365
 
363
366
  // src/common/engine.ts
367
+ var ENGINE_HOST = "127.0.0.1";
364
368
  var ENGINE_PORT = 6420;
365
- var ENGINE_ENDPOINT = `http://127.0.0.1:${ENGINE_PORT}`;
369
+ var ENGINE_ENDPOINT = buildEngineEndpoint(ENGINE_HOST, ENGINE_PORT);
370
+ function buildEngineEndpoint(host, port) {
371
+ const urlHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
372
+ return `http://${urlHost}:${port}`;
373
+ }
374
+ function isLocalEngineEndpoint(endpoint) {
375
+ let url;
376
+ try {
377
+ url = new URL(endpoint);
378
+ } catch {
379
+ return false;
380
+ }
381
+ const hostname = url.hostname.toLowerCase();
382
+ return hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]" || hostname === "::1" || hostname === "[::1]" || /^127(?:\.\d{1,3}){0,3}$/.test(hostname);
383
+ }
366
384
 
367
385
  // src/registry/log.ts
368
386
  function logger2() {
@@ -377,10 +395,13 @@ function sleep(ms) {
377
395
  }
378
396
  function configureTimeoutMs() {
379
397
  const value = process.env.RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS;
380
- if (value === void 0 || value === "") return DEFAULT_CONFIGURE_TIMEOUT_MS;
398
+ if (value === void 0 || value === "")
399
+ return DEFAULT_CONFIGURE_TIMEOUT_MS;
381
400
  const parsed = Number(value);
382
401
  if (!Number.isFinite(parsed) || parsed < 0) {
383
- throw new Error("RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS must be a finite non-negative number");
402
+ throw new Error(
403
+ "RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS must be a finite non-negative number"
404
+ );
384
405
  }
385
406
  return parsed;
386
407
  }
@@ -394,13 +415,19 @@ async function configureServerlessPool(config) {
394
415
  attempts += 1;
395
416
  try {
396
417
  if (!config.namespace) {
397
- throw new Error("namespace is required for serverless configuration");
418
+ throw new Error(
419
+ "namespace is required for serverless configuration"
420
+ );
398
421
  }
399
422
  if (!config.endpoint) {
400
- throw new Error("endpoint is required for serverless configuration");
423
+ throw new Error(
424
+ "endpoint is required for serverless configuration"
425
+ );
401
426
  }
402
427
  if (!config.configurePool) {
403
- throw new Error("configurePool is required for serverless configuration");
428
+ throw new Error(
429
+ "configurePool is required for serverless configuration"
430
+ );
404
431
  }
405
432
  const customConfig = config.configurePool;
406
433
  const clientConfig = convertRegistryConfigToClientConfig(config);
@@ -415,7 +442,7 @@ async function configureServerlessPool(config) {
415
442
  serverless: {
416
443
  url: customConfig.url,
417
444
  headers,
418
- request_lifespan: customConfig.requestLifespan ?? 15 * 60,
445
+ request_lifespan: customConfig.requestLifespan ?? 60 * 60,
419
446
  drain_grace_period: customConfig.drainGracePeriod,
420
447
  metadata_poll_interval: customConfig.metadataPollInterval ?? 1e3,
421
448
  max_runners: 1e5,
@@ -569,6 +596,8 @@ var RegistryConfigSchema = z3.object({
569
596
  maxIncomingMessageSize: z3.number().optional().default(65536),
570
597
  /** @experimental */
571
598
  maxOutgoingMessageSize: z3.number().optional().default(1048576),
599
+ /** Enables the experimental per-actor Unix socket API. */
600
+ experimentalActorUds: z3.boolean().optional().default(false),
572
601
  // MARK: Runtime
573
602
  /**
574
603
  * @experimental
@@ -674,6 +703,18 @@ var RegistryConfigSchema = z3.object({
674
703
  * Starts the full Rust engine process locally.
675
704
  */
676
705
  startEngine: z3.boolean().default(() => getRivetRunEngine()),
706
+ /**
707
+ * @experimental
708
+ *
709
+ * Host to bind the spawned local engine process to.
710
+ */
711
+ engineHost: z3.string().optional().default(() => getRivetRunEngineHost() ?? ENGINE_HOST),
712
+ /**
713
+ * @experimental
714
+ *
715
+ * Port to bind the spawned local engine process to.
716
+ */
717
+ enginePort: z3.number().int().min(1).max(65535).optional().default(() => getRivetRunEnginePort() ?? ENGINE_PORT),
677
718
  /** @experimental */
678
719
  engineVersion: z3.string().optional().default(() => getRivetRunEngineVersion() ?? VERSION),
679
720
  /**
@@ -706,12 +747,12 @@ var RegistryConfigSchema = z3.object({
706
747
  shutdown: z3.object({
707
748
  /**
708
749
  * Wait this many milliseconds for the serve promise to resolve
709
- * after calling `CoreRegistry::shutdown()`. Defaults to 30s,
710
- * matching Kubernetes `terminationGracePeriodSeconds`.
750
+ * after calling `CoreRegistry::shutdown()`. Defaults to the
751
+ * engine-provided actor stop threshold once the envoy connects.
711
752
  *
712
- * Must be >= rivetkit-core's drain timeout (20s) + margin.
753
+ * Must be long enough for rivetkit-core to drain the envoy.
713
754
  */
714
- gracePeriodMs: z3.number().int().min(1e3).optional().default(3e4),
755
+ gracePeriodMs: z3.number().int().min(1e3).optional(),
715
756
  /**
716
757
  * If true, rivetkit will not install SIGINT/SIGTERM handlers.
717
758
  * Use when the host application owns signal policy and will
@@ -719,7 +760,6 @@ var RegistryConfigSchema = z3.object({
719
760
  */
720
761
  disableSignalHandlers: z3.boolean().optional().default(false)
721
762
  }).optional().default(() => ({
722
- gracePeriodMs: 3e4,
723
763
  disableSignalHandlers: false
724
764
  }))
725
765
  }).transform((config, ctx) => {
@@ -752,7 +792,11 @@ var RegistryConfigSchema = z3.object({
752
792
  message: "configurePool requires either endpoint or startEngine"
753
793
  });
754
794
  }
755
- const endpoint = config.startEngine ? ENGINE_ENDPOINT : (parsedEndpoint == null ? void 0 : parsedEndpoint.endpoint) ?? (isDevEnv ? ENGINE_ENDPOINT : void 0);
795
+ const localEngineEndpoint = buildEngineEndpoint(
796
+ config.engineHost,
797
+ config.enginePort
798
+ );
799
+ const endpoint = config.startEngine ? localEngineEndpoint : (parsedEndpoint == null ? void 0 : parsedEndpoint.endpoint) ?? (isDevEnv ? buildEngineEndpoint(ENGINE_HOST, ENGINE_PORT) : void 0);
756
800
  const validateServerlessEndpoint = Boolean(
757
801
  config.startEngine || parsedEndpoint
758
802
  );
@@ -769,7 +813,7 @@ var RegistryConfigSchema = z3.object({
769
813
  path: ["serverless", "publicEndpoint"]
770
814
  });
771
815
  }
772
- const publicEndpoint = (parsedPublicEndpoint == null ? void 0 : parsedPublicEndpoint.endpoint) ?? (isDevEnv && config.startEngine ? ENGINE_ENDPOINT : void 0);
816
+ const publicEndpoint = (parsedPublicEndpoint == null ? void 0 : parsedPublicEndpoint.endpoint) ?? (isDevEnv && config.startEngine ? endpoint : void 0);
773
817
  const publicNamespace = parsedPublicEndpoint == null ? void 0 : parsedPublicEndpoint.namespace;
774
818
  const publicToken = (parsedPublicEndpoint == null ? void 0 : parsedPublicEndpoint.token) ?? config.serverless.publicToken;
775
819
  return {
@@ -801,7 +845,8 @@ function buildActorNames(config) {
801
845
  keys: [
802
846
  Array.from(KEYS.PERSIST_DATA),
803
847
  Array.from(KEYS.INSPECTOR_TOKEN),
804
- Array.from(queueMetadataKey())
848
+ Array.from(queueMetadataKey()),
849
+ Array.from(KEYS.LAST_PUSHED_ALARM)
805
850
  ],
806
851
  prefixes: [
807
852
  {
@@ -929,7 +974,8 @@ function shouldAttachNativeKvError(message) {
929
974
  }
930
975
  function enrichNativeDatabaseError(database, error) {
931
976
  var _a;
932
- const bridged = typeof error === "string" ? decodeBridgeRivetError(error) : error instanceof Error ? decodeBridgeRivetError(error.message) : void 0;
977
+ const bridgeReason = typeof error === "string" ? error : error instanceof Error ? error.message : void 0;
978
+ const bridged = bridgeReason === void 0 ? void 0 : decodeBridgeRivetError(bridgeReason);
933
979
  if (bridged) {
934
980
  throw bridged;
935
981
  }
@@ -1080,7 +1126,7 @@ function wrapJsNativeDatabase(database) {
1080
1126
  const gate = new NativeCloseGate();
1081
1127
  let closePromise;
1082
1128
  let lastInsertRowId = null;
1083
- const executeNative = async (sql, params) => {
1129
+ const executeNative = async (sql, params, lease) => {
1084
1130
  const lastInsertRowIdColumn = lastInsertRowIdColumnName(sql);
1085
1131
  if (lastInsertRowIdColumn) {
1086
1132
  return {
@@ -1093,7 +1139,12 @@ function wrapJsNativeDatabase(database) {
1093
1139
  const release = gate.enter();
1094
1140
  try {
1095
1141
  const nativeParams = toNativeBindings(sql, params);
1096
- const result = await database.execute(sql, nativeParams);
1142
+ const result = await database.execute(
1143
+ sql,
1144
+ nativeParams,
1145
+ lease == null ? void 0 : lease.key,
1146
+ lease == null ? void 0 : lease.timeoutMs
1147
+ );
1097
1148
  if (result.lastInsertRowId !== void 0) {
1098
1149
  lastInsertRowId = result.lastInsertRowId;
1099
1150
  }
@@ -1105,11 +1156,11 @@ function wrapJsNativeDatabase(database) {
1105
1156
  }
1106
1157
  };
1107
1158
  return {
1108
- async exec(sql, callback) {
1159
+ async exec(sql, callback, lease) {
1109
1160
  const release = gate.enter();
1110
1161
  let result;
1111
1162
  try {
1112
- result = await database.exec(sql);
1163
+ result = await database.exec(sql, lease == null ? void 0 : lease.key, lease == null ? void 0 : lease.timeoutMs);
1113
1164
  } catch (error) {
1114
1165
  enrichNativeDatabaseError(database, error);
1115
1166
  } finally {
@@ -1122,8 +1173,8 @@ function wrapJsNativeDatabase(database) {
1122
1173
  callback(row, result.columns);
1123
1174
  }
1124
1175
  },
1125
- async execute(sql, params) {
1126
- return await executeNative(sql, params);
1176
+ async execute(sql, params, lease) {
1177
+ return await executeNative(sql, params, lease);
1127
1178
  },
1128
1179
  async run(sql, params) {
1129
1180
  await executeNative(sql, params);
@@ -1132,9 +1183,6 @@ function wrapJsNativeDatabase(database) {
1132
1183
  const { columns, rows } = await executeNative(sql, params);
1133
1184
  return { columns, rows };
1134
1185
  },
1135
- async writeMode(callback) {
1136
- return await callback();
1137
- },
1138
1186
  nativeMetrics() {
1139
1187
  var _a;
1140
1188
  return normalizeNativeMetrics((_a = database.metrics) == null ? void 0 : _a.call(database));
@@ -1162,6 +1210,82 @@ function lastInsertRowIdColumnName(sql) {
1162
1210
  return alias;
1163
1211
  }
1164
1212
 
1213
+ // src/utils/node.ts
1214
+ import { createRequire } from "module";
1215
+ var nodeCrypto;
1216
+ var nodeFsSync;
1217
+ var nodeFs;
1218
+ var nodePath;
1219
+ var nodeOs;
1220
+ var nodeChildProcess;
1221
+ var nodeStream;
1222
+ var nodeUrl;
1223
+ var hasImportedDependencies = false;
1224
+ function getRequireFn() {
1225
+ return createRequire(import.meta.url);
1226
+ }
1227
+ function importNodeDependencies() {
1228
+ if (hasImportedDependencies) return;
1229
+ try {
1230
+ const requireFn = getRequireFn();
1231
+ nodeCrypto = requireFn(
1232
+ /* webpackIgnore: true */
1233
+ "node:crypto"
1234
+ );
1235
+ nodeFsSync = requireFn(
1236
+ /* webpackIgnore: true */
1237
+ "node:fs"
1238
+ );
1239
+ nodeFs = requireFn(
1240
+ /* webpackIgnore: true */
1241
+ "node:fs/promises"
1242
+ );
1243
+ nodePath = requireFn(
1244
+ /* webpackIgnore: true */
1245
+ "node:path"
1246
+ );
1247
+ nodeOs = requireFn(
1248
+ /* webpackIgnore: true */
1249
+ "node:os"
1250
+ );
1251
+ nodeChildProcess = requireFn(
1252
+ /* webpackIgnore: true */
1253
+ "node:child_process"
1254
+ );
1255
+ nodeStream = requireFn(
1256
+ /* webpackIgnore: true */
1257
+ "node:stream/promises"
1258
+ );
1259
+ nodeUrl = requireFn(
1260
+ /* webpackIgnore: true */
1261
+ "node:url"
1262
+ );
1263
+ hasImportedDependencies = true;
1264
+ } catch (err) {
1265
+ console.warn(
1266
+ "Node.js modules not available, file system driver will not work",
1267
+ err
1268
+ );
1269
+ throw err;
1270
+ }
1271
+ }
1272
+ function getNodeFsSync() {
1273
+ if (!nodeFsSync) {
1274
+ throw new Error(
1275
+ "Node fs module not loaded. Ensure importNodeDependencies() has been called."
1276
+ );
1277
+ }
1278
+ return nodeFsSync;
1279
+ }
1280
+ function getNodePath() {
1281
+ if (!nodePath) {
1282
+ throw new Error(
1283
+ "Node path module not loaded. Ensure importNodeDependencies() has been called."
1284
+ );
1285
+ }
1286
+ return nodePath;
1287
+ }
1288
+
1165
1289
  // src/registry/runtime.ts
1166
1290
  function normalizeRuntimeSqlExecuteResult(result) {
1167
1291
  return result;
@@ -1282,11 +1406,31 @@ var NapiCoreRuntime = class {
1282
1406
  async shutdownRegistry(registry) {
1283
1407
  await asNativeRegistry(registry).shutdown();
1284
1408
  }
1285
- async registryDiagnostics(registry) {
1286
- const diagnostics = await asNativeRegistry(registry).diagnostics();
1409
+ async registryActorStopThresholdMs(registry) {
1410
+ return await asNativeRegistry(registry).actorStopThresholdMs() ?? void 0;
1411
+ }
1412
+ async registryHealth(registry) {
1413
+ const response = await asNativeRegistry(registry).health();
1414
+ return {
1415
+ status: response.status,
1416
+ headers: response.headers,
1417
+ body: response.body
1418
+ };
1419
+ }
1420
+ async registryMetadata(registry) {
1421
+ const response = asNativeRegistry(registry).metadata();
1287
1422
  return {
1288
- mode: diagnostics.mode,
1289
- envoyActiveActorCount: diagnostics.envoyActiveActorCount
1423
+ status: response.status,
1424
+ headers: response.headers,
1425
+ body: response.body
1426
+ };
1427
+ }
1428
+ async registryMetrics(registry) {
1429
+ const response = asNativeRegistry(registry).metrics();
1430
+ return {
1431
+ status: response.status,
1432
+ headers: response.headers,
1433
+ body: response.body
1290
1434
  };
1291
1435
  }
1292
1436
  async handleServerlessRequest(registry, req, onStreamEvent, cancelToken, config) {
@@ -1297,6 +1441,16 @@ var NapiCoreRuntime = class {
1297
1441
  config
1298
1442
  );
1299
1443
  }
1444
+ async serveListener(registry, listener, config) {
1445
+ await asNativeRegistry(registry).serveListener(
1446
+ {
1447
+ port: listener.port,
1448
+ host: listener.host,
1449
+ publicDir: listener.publicDir
1450
+ },
1451
+ config
1452
+ );
1453
+ }
1300
1454
  createActorFactory(callbacks, config) {
1301
1455
  return asActorFactoryHandle(
1302
1456
  new this.#bindings.NapiActorFactory(callbacks, config)
@@ -1409,6 +1563,12 @@ var NapiCoreRuntime = class {
1409
1563
  actorWaitUntil(ctx, promise) {
1410
1564
  asNativeActorContext(ctx).waitUntil(promise);
1411
1565
  }
1566
+ async actorWaitForTrackedShutdownWork(ctx) {
1567
+ return await asNativeActorContext(ctx).waitForTrackedShutdownWork();
1568
+ }
1569
+ async actorWaitForTrackedShutdownWorkUnbounded(ctx) {
1570
+ await asNativeActorContext(ctx).waitForTrackedShutdownWorkUnbounded();
1571
+ }
1412
1572
  actorKeepAwake(ctx, promise) {
1413
1573
  asNativeActorContext(ctx).keepAwake(promise);
1414
1574
  }
@@ -1463,13 +1623,19 @@ var NapiCoreRuntime = class {
1463
1623
  async actorKvBatchDelete(ctx, keys) {
1464
1624
  await asNativeActorContext(ctx).kv().batchDelete(keys.map(toNapiBuffer));
1465
1625
  }
1466
- async actorSqlExec(ctx, sql) {
1467
- return await this.#actorSql(ctx).exec(sql);
1626
+ async actorSqlExec(ctx, sql, lease) {
1627
+ return await this.#actorSql(ctx).exec(
1628
+ sql,
1629
+ lease == null ? void 0 : lease.key,
1630
+ lease == null ? void 0 : lease.timeoutMs
1631
+ );
1468
1632
  }
1469
- async actorSqlExecute(ctx, sql, params) {
1633
+ async actorSqlExecute(ctx, sql, params, lease) {
1470
1634
  const result = await this.#actorSql(ctx).execute(
1471
1635
  sql,
1472
- toNapiSqlBindParams(params)
1636
+ toNapiSqlBindParams(params),
1637
+ lease == null ? void 0 : lease.key,
1638
+ lease == null ? void 0 : lease.timeoutMs
1473
1639
  );
1474
1640
  return normalizeRuntimeSqlExecuteResult(result);
1475
1641
  }
@@ -1499,6 +1665,9 @@ var NapiCoreRuntime = class {
1499
1665
  this.#sql.delete(nativeCtx);
1500
1666
  await database.close();
1501
1667
  }
1668
+ async actorUdsProvision(ctx) {
1669
+ return await asNativeActorContext(ctx).provisionActorUds();
1670
+ }
1502
1671
  async actorQueueSend(ctx, name, body) {
1503
1672
  return toNapiQueueMessage(
1504
1673
  await asNativeActorContext(ctx).queue().send(name, toNapiBuffer(body))
@@ -1520,8 +1689,12 @@ var NapiCoreRuntime = class {
1520
1689
  )
1521
1690
  );
1522
1691
  }
1523
- async actorQueueWaitForNamesAvailable(ctx, names, options) {
1524
- await asNativeActorContext(ctx).queue().waitForNamesAvailable(names, options);
1692
+ async actorQueueWaitForNamesAvailable(ctx, names, options, signal) {
1693
+ await asNativeActorContext(ctx).queue().waitForNamesAvailable(
1694
+ names,
1695
+ options,
1696
+ signal ? asNativeCancellationToken(signal) : signal
1697
+ );
1525
1698
  }
1526
1699
  async actorQueueEnqueueAndWait(ctx, name, body, options, signal) {
1527
1700
  return await asNativeActorContext(ctx).queue().enqueueAndWait(
@@ -1540,6 +1713,9 @@ var NapiCoreRuntime = class {
1540
1713
  async actorQueueInspectMessages(ctx) {
1541
1714
  return await asNativeActorContext(ctx).queue().inspectMessages();
1542
1715
  }
1716
+ async actorQueueReset(ctx) {
1717
+ await asNativeActorContext(ctx).queue().reset();
1718
+ }
1543
1719
  actorScheduleAfter(ctx, durationMs, actionName, args) {
1544
1720
  asNativeActorContext(ctx).schedule().after(durationMs, actionName, toNapiBuffer(args));
1545
1721
  }
@@ -1655,20 +1831,18 @@ function validateQueueComplete(schemas, name, response) {
1655
1831
  response
1656
1832
  );
1657
1833
  if (!result.success) {
1658
- throw validationError(`queue \`${name}\` completion response`, result.issues);
1834
+ throw validationError(
1835
+ `queue \`${name}\` completion response`,
1836
+ result.issues
1837
+ );
1659
1838
  }
1660
1839
  return result.data;
1661
1840
  }
1662
1841
  function validationError(target, issues) {
1663
- return new RivetError(
1664
- "actor",
1665
- "validation_error",
1666
- `Invalid ${target}`,
1667
- {
1668
- public: true,
1669
- metadata: { issues }
1670
- }
1671
- );
1842
+ return new RivetError("actor", "validation_error", `Invalid ${target}`, {
1843
+ public: true,
1844
+ metadata: { issues }
1845
+ });
1672
1846
  }
1673
1847
 
1674
1848
  // src/registry/wasm-runtime.ts
@@ -1826,8 +2000,18 @@ var WasmCoreRuntime = class {
1826
2000
  async shutdownRegistry(registry) {
1827
2001
  await callWasm(() => asWasmRegistry(registry).shutdown());
1828
2002
  }
1829
- async registryDiagnostics() {
1830
- return { mode: "wasm", envoyActiveActorCount: null };
2003
+ async registryHealth() {
2004
+ return {
2005
+ status: 200,
2006
+ headers: { "content-type": "application/json" },
2007
+ body: new TextEncoder().encode(
2008
+ JSON.stringify({
2009
+ status: "ok",
2010
+ runtime: "rivetkit",
2011
+ version: "wasm"
2012
+ })
2013
+ )
2014
+ };
1831
2015
  }
1832
2016
  async handleServerlessRequest(registry, req, onStreamEvent, cancelToken, config) {
1833
2017
  return await callHandleAsync(
@@ -1839,6 +2023,11 @@ var WasmCoreRuntime = class {
1839
2023
  config
1840
2024
  );
1841
2025
  }
2026
+ async serveListener(_registry, _listener, _config) {
2027
+ throw new Error(
2028
+ "registry.listen() is not supported on the wasm runtime; use registry.serve() and mount the handler in your platform's HTTP server instead"
2029
+ );
2030
+ }
1842
2031
  createActorFactory(callbacks, config) {
1843
2032
  return callWasmSync(
1844
2033
  () => asActorFactoryHandle2(
@@ -1976,6 +2165,18 @@ var WasmCoreRuntime = class {
1976
2165
  actorWaitUntil(ctx, promise) {
1977
2166
  callHandle(asWasmActorContext(ctx), "waitUntil", promise);
1978
2167
  }
2168
+ async actorWaitForTrackedShutdownWork(ctx) {
2169
+ return await callHandle(
2170
+ asWasmActorContext(ctx),
2171
+ "waitForTrackedShutdownWork"
2172
+ );
2173
+ }
2174
+ async actorWaitForTrackedShutdownWorkUnbounded(ctx) {
2175
+ await callHandle(
2176
+ asWasmActorContext(ctx),
2177
+ "waitForTrackedShutdownWorkUnbounded"
2178
+ );
2179
+ }
1979
2180
  actorKeepAwake(ctx, promise) {
1980
2181
  const wasmCtx = asWasmActorContext(ctx);
1981
2182
  const regionId = callHandle(wasmCtx, "beginKeepAwake");
@@ -2063,10 +2264,20 @@ var WasmCoreRuntime = class {
2063
2264
  const kv = childHandle(asWasmActorContext(ctx), "kv");
2064
2265
  await callHandleAsync(kv, "batchDelete", keys);
2065
2266
  }
2066
- async actorSqlExec(ctx, sql) {
2267
+ async actorSqlExec(ctx, sql, lease) {
2268
+ if (lease) {
2269
+ throw new Error(
2270
+ "sqlite transaction leases are unavailable in the wasm runtime"
2271
+ );
2272
+ }
2067
2273
  return await callWasm(() => this.#actorSql(ctx).exec(sql));
2068
2274
  }
2069
- async actorSqlExecute(ctx, sql, params) {
2275
+ async actorSqlExecute(ctx, sql, params, lease) {
2276
+ if (lease) {
2277
+ throw new Error(
2278
+ "sqlite transaction leases are unavailable in the wasm runtime"
2279
+ );
2280
+ }
2070
2281
  const result = await callWasm(
2071
2282
  () => this.#actorSql(ctx).execute(sql, params)
2072
2283
  );
@@ -2095,6 +2306,9 @@ var WasmCoreRuntime = class {
2095
2306
  this.#sql.delete(wasmCtx);
2096
2307
  await callWasm(() => database.close());
2097
2308
  }
2309
+ async actorUdsProvision(_ctx) {
2310
+ throw new Error("actor UDS endpoints require the native runtime");
2311
+ }
2098
2312
  async actorQueueSend(ctx, name, body) {
2099
2313
  const queue2 = childHandle(asWasmActorContext(ctx), "queue");
2100
2314
  return normalizeQueueMessage(
@@ -2123,9 +2337,15 @@ var WasmCoreRuntime = class {
2123
2337
  )
2124
2338
  );
2125
2339
  }
2126
- async actorQueueWaitForNamesAvailable(ctx, names, options) {
2340
+ async actorQueueWaitForNamesAvailable(ctx, names, options, signal) {
2127
2341
  const queue2 = childHandle(asWasmActorContext(ctx), "queue");
2128
- await callHandleAsync(queue2, "waitForNamesAvailable", names, options);
2342
+ await callHandleAsync(
2343
+ queue2,
2344
+ "waitForNamesAvailable",
2345
+ names,
2346
+ options,
2347
+ signal
2348
+ );
2129
2349
  }
2130
2350
  async actorQueueEnqueueAndWait(ctx, name, body, options, signal) {
2131
2351
  const queue2 = childHandle(asWasmActorContext(ctx), "queue");
@@ -2156,6 +2376,10 @@ var WasmCoreRuntime = class {
2156
2376
  const queue2 = childHandle(asWasmActorContext(ctx), "queue");
2157
2377
  return await callHandleAsync(queue2, "inspectMessages");
2158
2378
  }
2379
+ async actorQueueReset(ctx) {
2380
+ const queue2 = childHandle(asWasmActorContext(ctx), "queue");
2381
+ await callHandleAsync(queue2, "reset");
2382
+ }
2159
2383
  actorScheduleAfter(ctx, durationMs, actionName, args) {
2160
2384
  const schedule = childHandle(asWasmActorContext(ctx), "schedule");
2161
2385
  callHandle(schedule, "after", wasmNumber(durationMs), actionName, args);
@@ -2217,6 +2441,29 @@ async function loadWasmRuntime(config) {
2217
2441
  };
2218
2442
  }
2219
2443
 
2444
+ // src/registry/write-through-proxy.ts
2445
+ import onChange from "@rivetkit/on-change";
2446
+ function createWriteThroughProxy(value, commit, beforeChange) {
2447
+ if (!value || typeof value !== "object") {
2448
+ return value;
2449
+ }
2450
+ return onChange(
2451
+ value,
2452
+ () => {
2453
+ commit(value);
2454
+ },
2455
+ {
2456
+ // Rejection is throw-based: beforeChange throws to prevent the
2457
+ // mutation. We always return true so on-change applies the change
2458
+ // if beforeChange did not throw.
2459
+ onValidate(_path, newValue) {
2460
+ beforeChange == null ? void 0 : beforeChange(newValue);
2461
+ return true;
2462
+ }
2463
+ }
2464
+ );
2465
+ }
2466
+
2220
2467
  // src/registry/native.ts
2221
2468
  var textEncoder = new TextEncoder();
2222
2469
  var textDecoder = new TextDecoder();
@@ -2370,6 +2617,14 @@ function databaseNotConfiguredError() {
2370
2617
  { public: true }
2371
2618
  );
2372
2619
  }
2620
+ function databaseClientNotReadyError() {
2621
+ return new RivetError(
2622
+ "actor",
2623
+ "database_client_not_ready",
2624
+ "actor database client was not initialized before user code ran. this is an internal lifecycle error; the migration callback should have pre-warmed the client. file an issue if you can reproduce.",
2625
+ { public: true }
2626
+ );
2627
+ }
2373
2628
  function stateNotEnabledError() {
2374
2629
  return new RivetError(
2375
2630
  "actor",
@@ -2421,7 +2676,23 @@ function resolveNativeDestroy(runtime, ctx) {
2421
2676
  function clearNativeRuntimeState(runtime, ctx) {
2422
2677
  callNativeSync(() => runtime.actorClearRuntimeState(ctx));
2423
2678
  }
2424
- async function cleanupNativeSleepRuntimeState(runtime, ctx) {
2679
+ async function cleanupNativeSleepRuntimeState(runtime, ctx, afterTrackedWorkDrained) {
2680
+ const drained = await runtime.actorWaitForTrackedShutdownWork(ctx);
2681
+ if (!drained) {
2682
+ await closeNativeDatabaseClient(runtime, ctx);
2683
+ await closeNativeSqlDatabase(runtime, ctx);
2684
+ void runtime.actorWaitForTrackedShutdownWorkUnbounded(ctx).then(async () => {
2685
+ await (afterTrackedWorkDrained == null ? void 0 : afterTrackedWorkDrained());
2686
+ clearNativeRuntimeState(runtime, ctx);
2687
+ }).catch((error) => {
2688
+ logger2().warn({
2689
+ msg: "deferred native sleep cleanup failed",
2690
+ error: stringifyError(error)
2691
+ });
2692
+ });
2693
+ return;
2694
+ }
2695
+ await (afterTrackedWorkDrained == null ? void 0 : afterTrackedWorkDrained());
2425
2696
  await closeNativeDatabaseClient(runtime, ctx);
2426
2697
  await closeNativeSqlDatabase(runtime, ctx);
2427
2698
  clearNativeRuntimeState(runtime, ctx);
@@ -2453,8 +2724,17 @@ function getOrCreateNativeSqlDatabase(runtime, ctx) {
2453
2724
  return cachedDatabase;
2454
2725
  }
2455
2726
  const database = wrapJsNativeDatabase({
2456
- exec: (sql) => runtime.actorSqlExec(ctx, sql),
2457
- execute: (sql, params) => runtime.actorSqlExecute(ctx, sql, params),
2727
+ exec: (sql, leaseKey, leaseTimeoutMs) => runtime.actorSqlExec(
2728
+ ctx,
2729
+ sql,
2730
+ leaseKey === void 0 ? void 0 : { key: leaseKey, timeoutMs: leaseTimeoutMs }
2731
+ ),
2732
+ execute: (sql, params, leaseKey, leaseTimeoutMs) => runtime.actorSqlExecute(
2733
+ ctx,
2734
+ sql,
2735
+ params,
2736
+ leaseKey === void 0 ? void 0 : { key: leaseKey, timeoutMs: leaseTimeoutMs }
2737
+ ),
2458
2738
  query: (sql, params) => runtime.actorSqlQuery(ctx, sql, params),
2459
2739
  run: (sql, params) => runtime.actorSqlRun(ctx, sql, params),
2460
2740
  metrics: () => runtime.actorSqlMetrics(ctx),
@@ -2526,11 +2806,14 @@ function decodeValue(value) {
2526
2806
  if (!value || value.length === 0) {
2527
2807
  return void 0;
2528
2808
  }
2529
- return decodeCborJsonCompat(value);
2809
+ return decodeCborCompat(value);
2530
2810
  }
2531
2811
  function encodeValue(value) {
2532
2812
  return encodeCborCompat(value);
2533
2813
  }
2814
+ function normalizeArgs(value) {
2815
+ return Array.isArray(value) ? value : value === void 0 || value === null ? [] : [value];
2816
+ }
2534
2817
  function unwrapTsfnPayload(error, payload) {
2535
2818
  if (error !== null && error !== void 0) {
2536
2819
  throw error;
@@ -2562,27 +2845,7 @@ function isStructuredBridgeError(error) {
2562
2845
  return isRivetErrorLike(error) && "__type" in error && (error.__type === "RivetError" || error.__type === "ActorError");
2563
2846
  }
2564
2847
  function encodeNativeCallbackError(error) {
2565
- const structuredError = isStructuredBridgeError(error) ? error : deconstructError(error, logger2(), {
2566
- bridge: "native_callback"
2567
- });
2568
- let stack;
2569
- if (error instanceof Error) {
2570
- try {
2571
- stack = error.stack;
2572
- } catch {
2573
- stack = void 0;
2574
- }
2575
- }
2576
- logger2().warn({
2577
- msg: "native callback error encoded for bridge",
2578
- group: structuredError.group,
2579
- code: structuredError.code,
2580
- message: structuredError.message,
2581
- metadata: structuredError.metadata,
2582
- originalError: stringifyError(error),
2583
- stack,
2584
- bridge: "native_callback"
2585
- });
2848
+ const structuredError = isStructuredBridgeError(error) ? error : deconstructError(error, true);
2586
2849
  const bridgeError = new Error(encodeBridgeRivetError(structuredError), {
2587
2850
  cause: error instanceof Error ? error : void 0
2588
2851
  });
@@ -2606,12 +2869,6 @@ function callNativeSync(invoke) {
2606
2869
  throw normalizeNativeBridgeError(error);
2607
2870
  }
2608
2871
  }
2609
- function actorAbortedError() {
2610
- return Object.assign(new Error("Actor aborted"), {
2611
- group: "actor",
2612
- code: "aborted"
2613
- });
2614
- }
2615
2872
  function isClosedTaskRegistrationError(error) {
2616
2873
  const metadata = error instanceof RivetError ? error.metadata : void 0;
2617
2874
  const metadataError = metadata && typeof metadata === "object" && "error" in metadata ? metadata.error : void 0;
@@ -2737,6 +2994,14 @@ function serializeWorkflowEntryKind(kind) {
2737
2994
  originalName: kind.val.originalName
2738
2995
  }
2739
2996
  };
2997
+ case "WorkflowVersionCheckEntry":
2998
+ return {
2999
+ tag: kind.tag,
3000
+ val: {
3001
+ resolved: kind.val.resolved,
3002
+ latest: kind.val.latest
3003
+ }
3004
+ };
2740
3005
  }
2741
3006
  }
2742
3007
  function serializeWorkflowHistoryForJson(data) {
@@ -2744,7 +3009,7 @@ function serializeWorkflowHistoryForJson(data) {
2744
3009
  return null;
2745
3010
  }
2746
3011
  const history = decodeWorkflowHistoryTransport(data);
2747
- return {
3012
+ return jsonSafe({
2748
3013
  nameRegistry: [...history.nameRegistry],
2749
3014
  entries: history.entries.map((entry) => ({
2750
3015
  id: entry.id,
@@ -2768,7 +3033,7 @@ function serializeWorkflowHistoryForJson(data) {
2768
3033
  ]
2769
3034
  )
2770
3035
  )
2771
- };
3036
+ });
2772
3037
  }
2773
3038
  function toHttpJsonCompatible(value) {
2774
3039
  return JSON.parse(
@@ -2819,45 +3084,7 @@ function wrapNativeCallback(callback) {
2819
3084
  }
2820
3085
  function decodeArgs(value) {
2821
3086
  const decoded = decodeValue(value);
2822
- return Array.isArray(decoded) ? decoded : decoded === void 0 ? [] : [decoded];
2823
- }
2824
- function createWriteThroughProxy(value, commit, beforeChange) {
2825
- if (!value || typeof value !== "object") {
2826
- return value;
2827
- }
2828
- const proxies = /* @__PURE__ */ new WeakMap();
2829
- const wrap = (target) => {
2830
- const cached = proxies.get(target);
2831
- if (cached) {
2832
- return cached;
2833
- }
2834
- const proxy = new Proxy(target, {
2835
- get(innerTarget, property, receiver) {
2836
- const result = Reflect.get(innerTarget, property, receiver);
2837
- return result && typeof result === "object" ? wrap(result) : result;
2838
- },
2839
- set(innerTarget, property, nextValue, receiver) {
2840
- beforeChange == null ? void 0 : beforeChange();
2841
- const updated = Reflect.set(
2842
- innerTarget,
2843
- property,
2844
- nextValue,
2845
- receiver
2846
- );
2847
- commit(value);
2848
- return updated;
2849
- },
2850
- deleteProperty(innerTarget, property) {
2851
- beforeChange == null ? void 0 : beforeChange();
2852
- const updated = Reflect.deleteProperty(innerTarget, property);
2853
- commit(value);
2854
- return updated;
2855
- }
2856
- });
2857
- proxies.set(target, proxy);
2858
- return proxy;
2859
- };
2860
- return wrap(value);
3087
+ return normalizeArgs(decoded);
2861
3088
  }
2862
3089
  function buildRequest(init) {
2863
3090
  const url = init.uri.startsWith("http") ? init.uri : new URL(init.uri, "http://127.0.0.1").toString();
@@ -2911,13 +3138,23 @@ var NativeConnAdapter = class {
2911
3138
  decodeValue(this.#runtime.connParams(this.#conn))
2912
3139
  );
2913
3140
  }
3141
+ [RAW_STATE_SYMBOL]() {
3142
+ return this.#readState();
3143
+ }
2914
3144
  get state() {
2915
3145
  const nextState = this.#readState();
2916
- return createWriteThroughProxy(nextState, (nextValue) => {
2917
- this.#writeState(nextValue, { writeNative: true });
2918
- });
3146
+ return createWriteThroughProxy(
3147
+ nextState,
3148
+ (nextValue) => {
3149
+ this.#writeState(nextValue, { writeNative: true });
3150
+ },
3151
+ (newValue) => {
3152
+ assertJsonCompatValue(newValue);
3153
+ }
3154
+ );
2919
3155
  }
2920
3156
  set state(value) {
3157
+ assertJsonCompatValue(value);
2921
3158
  this.#writeState(value, { writeNative: true });
2922
3159
  }
2923
3160
  initializeState(value) {
@@ -3269,44 +3506,23 @@ var NativeQueueAdapter = class {
3269
3506
  }
3270
3507
  }
3271
3508
  async waitForNamesAvailable(names, options) {
3272
- if (!(options == null ? void 0 : options.signal)) {
3509
+ const { token, cleanup } = await createCancellationTokenHandle(
3510
+ this.#runtime,
3511
+ options == null ? void 0 : options.signal
3512
+ );
3513
+ try {
3273
3514
  await callNative(
3274
3515
  () => this.#runtime.actorQueueWaitForNamesAvailable(
3275
3516
  this.#ctx,
3276
3517
  [...names],
3277
3518
  {
3278
3519
  timeoutMs: options == null ? void 0 : options.timeout
3279
- }
3520
+ },
3521
+ token
3280
3522
  )
3281
3523
  );
3282
- return;
3283
- }
3284
- const deadline = options.timeout === void 0 ? void 0 : Date.now() + options.timeout;
3285
- for (; ; ) {
3286
- if (options.signal.aborted) {
3287
- throw actorAbortedError();
3288
- }
3289
- const remainingTimeout = deadline === void 0 ? void 0 : Math.max(0, deadline - Date.now());
3290
- const sliceTimeout = remainingTimeout === void 0 ? 100 : Math.min(remainingTimeout, 100);
3291
- try {
3292
- await callNative(
3293
- () => this.#runtime.actorQueueWaitForNamesAvailable(
3294
- this.#ctx,
3295
- [...names],
3296
- {
3297
- timeoutMs: sliceTimeout
3298
- }
3299
- )
3300
- );
3301
- return;
3302
- } catch (error) {
3303
- if (error.group === "queue" && error.code === "timed_out") {
3304
- if (remainingTimeout === void 0 || remainingTimeout > 100) {
3305
- continue;
3306
- }
3307
- }
3308
- throw error;
3309
- }
3524
+ } finally {
3525
+ cleanup == null ? void 0 : cleanup();
3310
3526
  }
3311
3527
  }
3312
3528
  async enqueueAndWait(name, body, options) {
@@ -3376,7 +3592,7 @@ var NativeQueueAdapter = class {
3376
3592
  }
3377
3593
  yield message;
3378
3594
  } catch (error) {
3379
- if (isRivetErrorLike(error) && error.group === "actor" && error.code === "aborted") {
3595
+ if (isActorAbortedError(error)) {
3380
3596
  return;
3381
3597
  }
3382
3598
  throw error;
@@ -3741,6 +3957,68 @@ var TrackedWebSocketHandleAdapter = class {
3741
3957
  return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
3742
3958
  }
3743
3959
  };
3960
+ var NativeConnectionMap = class {
3961
+ #runtime;
3962
+ #ctx;
3963
+ #schemas;
3964
+ constructor(runtime, ctx, schemas) {
3965
+ this.#runtime = runtime;
3966
+ this.#ctx = ctx;
3967
+ this.#schemas = schemas;
3968
+ }
3969
+ #connToAdapter(conn) {
3970
+ return new NativeConnAdapter(
3971
+ this.#runtime,
3972
+ conn,
3973
+ this.#schemas,
3974
+ this.#ctx,
3975
+ (connId) => callNativeSync(
3976
+ () => this.#runtime.actorQueueHibernationRemoval(
3977
+ this.#ctx,
3978
+ connId
3979
+ )
3980
+ )
3981
+ );
3982
+ }
3983
+ get size() {
3984
+ return callNativeSync(() => this.#runtime.actorConns(this.#ctx)).length;
3985
+ }
3986
+ get(key) {
3987
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3988
+ const conn = conns.find((c) => this.#runtime.connId(c) === key);
3989
+ if (!conn) return void 0;
3990
+ return this.#connToAdapter(conn);
3991
+ }
3992
+ has(key) {
3993
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3994
+ return conns.some((c) => this.#runtime.connId(c) === key);
3995
+ }
3996
+ keys() {
3997
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
3998
+ return conns.map((c) => this.#runtime.connId(c))[Symbol.iterator]();
3999
+ }
4000
+ values() {
4001
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
4002
+ return conns.map((c) => this.#connToAdapter(c))[Symbol.iterator]();
4003
+ }
4004
+ entries() {
4005
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
4006
+ return conns.map(
4007
+ (c) => [this.#runtime.connId(c), this.#connToAdapter(c)]
4008
+ )[Symbol.iterator]();
4009
+ }
4010
+ forEach(callback, thisArg) {
4011
+ const conns = callNativeSync(() => this.#runtime.actorConns(this.#ctx));
4012
+ for (const conn of conns) {
4013
+ const id = this.#runtime.connId(conn);
4014
+ callback.call(thisArg, this.#connToAdapter(conn), id, this);
4015
+ }
4016
+ }
4017
+ [Symbol.iterator]() {
4018
+ return this.entries();
4019
+ }
4020
+ [Symbol.toStringTag] = "NativeConnectionMap";
4021
+ };
3744
4022
  var ActorContextHandleAdapter = class {
3745
4023
  #runtime;
3746
4024
  #ctx;
@@ -3749,9 +4027,9 @@ var ActorContextHandleAdapter = class {
3749
4027
  #abortSignalCleanup;
3750
4028
  #client;
3751
4029
  #clientFactory;
4030
+ #connMap;
3752
4031
  #databaseProvider;
3753
4032
  #db;
3754
- #dbProxy;
3755
4033
  #dispatchCancelToken;
3756
4034
  #kv;
3757
4035
  #queue;
@@ -3790,55 +4068,57 @@ var ActorContextHandleAdapter = class {
3790
4068
  }
3791
4069
  return this.#sql;
3792
4070
  }
4071
+ async actorUds() {
4072
+ return await this.#runtime.actorUdsProvision(this.#ctx);
4073
+ }
3793
4074
  get db() {
3794
4075
  if (!this.#databaseProvider) {
3795
4076
  throw databaseNotConfiguredError();
3796
4077
  }
3797
- if (!this.#dbProxy) {
3798
- this.#dbProxy = new Proxy(
3799
- {},
3800
- {
3801
- get: (_target, property) => {
3802
- if (property === "then") {
3803
- return void 0;
3804
- }
3805
- return async (...args) => {
3806
- const client = await this.ensureDatabaseClient();
3807
- const value = Reflect.get(
3808
- client,
3809
- property
3810
- );
3811
- if (typeof value !== "function") {
3812
- return value;
3813
- }
3814
- return await value.apply(client, args);
3815
- };
3816
- }
3817
- }
3818
- );
4078
+ if (this.#db) {
4079
+ return this.#db;
4080
+ }
4081
+ const runtimeState = getNativeRuntimeState(this.#runtime, this.#ctx);
4082
+ const cachedClient = runtimeState.databaseClient;
4083
+ if (cachedClient) {
4084
+ this.#db = cachedClient.client;
4085
+ return this.#db;
3819
4086
  }
3820
- return this.#dbProxy;
4087
+ throw databaseClientNotReadyError();
4088
+ }
4089
+ [RAW_STATE_SYMBOL]() {
4090
+ if (!this.#stateEnabled) {
4091
+ throw stateNotEnabledError();
4092
+ }
4093
+ return this.#readState();
3821
4094
  }
3822
4095
  get state() {
3823
4096
  if (!this.#stateEnabled) {
3824
4097
  throw stateNotEnabledError();
3825
4098
  }
4099
+ const actorState = getNativePersistState(this.#runtime, this.#ctx);
3826
4100
  const nextState = this.#readState();
3827
- return createWriteThroughProxy(
3828
- nextState,
3829
- (nextValue) => {
3830
- this.#writeState(nextValue, { scheduleSave: true });
3831
- },
3832
- () => {
3833
- this.#assertCanMutateState();
3834
- }
3835
- );
4101
+ if (actorState.stateProxy === void 0 || actorState.stateProxyTarget !== nextState) {
4102
+ actorState.stateProxyTarget = nextState;
4103
+ actorState.stateProxy = createWriteThroughProxy(
4104
+ nextState,
4105
+ (nextValue) => {
4106
+ this.#writeState(nextValue, { scheduleSave: true });
4107
+ },
4108
+ (newValue) => {
4109
+ this.#assertCanMutateState();
4110
+ assertJsonCompatValue(newValue);
4111
+ }
4112
+ );
4113
+ }
4114
+ return actorState.stateProxy;
3836
4115
  }
3837
4116
  set state(value) {
3838
4117
  if (!this.#stateEnabled) {
3839
4118
  throw stateNotEnabledError();
3840
4119
  }
3841
4120
  this.#assertCanMutateState();
4121
+ assertJsonCompatValue(value);
3842
4122
  this.#writeState(value, { scheduleSave: true });
3843
4123
  }
3844
4124
  initializeState(value) {
@@ -3895,25 +4175,14 @@ var ActorContextHandleAdapter = class {
3895
4175
  return callNativeSync(() => this.#runtime.actorRegion(this.#ctx));
3896
4176
  }
3897
4177
  get conns() {
3898
- return new Map(
3899
- callNativeSync(() => this.#runtime.actorConns(this.#ctx)).map(
3900
- (conn) => [
3901
- this.#runtime.connId(conn),
3902
- new NativeConnAdapter(
3903
- this.#runtime,
3904
- conn,
3905
- this.#schemas,
3906
- this.#ctx,
3907
- (connId) => callNativeSync(
3908
- () => this.#runtime.actorQueueHibernationRemoval(
3909
- this.#ctx,
3910
- connId
3911
- )
3912
- )
3913
- )
3914
- ]
3915
- )
3916
- );
4178
+ if (!this.#connMap) {
4179
+ this.#connMap = new NativeConnectionMap(
4180
+ this.#runtime,
4181
+ this.#ctx,
4182
+ this.#schemas
4183
+ );
4184
+ }
4185
+ return this.#connMap;
3917
4186
  }
3918
4187
  get log() {
3919
4188
  return logger2();
@@ -4111,35 +4380,17 @@ var ActorContextHandleAdapter = class {
4111
4380
  });
4112
4381
  }
4113
4382
  keepAwake(promise) {
4114
- const runtimeState = getNativeRuntimeState(this.#runtime, this.#ctx);
4115
- runtimeState.keepAwakeCount = (runtimeState.keepAwakeCount ?? 0) + 1;
4116
4383
  const trackedPromise = Promise.resolve(promise).catch((error) => {
4117
4384
  logger2().warn({
4118
4385
  msg: "keepAwake promise rejected",
4119
4386
  error: stringifyError(error)
4120
4387
  });
4121
- }).finally(async () => {
4122
- runtimeState.keepAwakeCount = Math.max(
4123
- (runtimeState.keepAwakeCount ?? 1) - 1,
4124
- 0
4125
- );
4126
- if (runtimeState.keepAwakeCount === 0 && runtimeState.deferSleepCleanupUntilKeepAwakeIdle) {
4127
- runtimeState.deferSleepCleanupUntilKeepAwakeIdle = false;
4128
- await cleanupNativeSleepRuntimeState(
4129
- this.#runtime,
4130
- this.#ctx
4131
- );
4132
- }
4133
4388
  }).then(() => null);
4134
4389
  try {
4135
4390
  callNativeSync(
4136
4391
  () => this.#runtime.actorKeepAwake(this.#ctx, trackedPromise)
4137
4392
  );
4138
4393
  } catch (error) {
4139
- runtimeState.keepAwakeCount = Math.max(
4140
- (runtimeState.keepAwakeCount ?? 1) - 1,
4141
- 0
4142
- );
4143
4394
  if (!isClosedTaskRegistrationError(error)) {
4144
4395
  throw error;
4145
4396
  }
@@ -4152,7 +4403,10 @@ var ActorContextHandleAdapter = class {
4152
4403
  }
4153
4404
  internalKeepAwake(run) {
4154
4405
  const promise = typeof run === "function" ? run() : run;
4155
- const trackedPromise = promise.then(() => null);
4406
+ const trackedPromise = promise.then(
4407
+ () => null,
4408
+ () => null
4409
+ );
4156
4410
  try {
4157
4411
  callNativeSync(
4158
4412
  () => this.#runtime.actorRegisterTask(this.#ctx, trackedPromise)
@@ -4208,6 +4462,7 @@ var ActorContextHandleAdapter = class {
4208
4462
  return false;
4209
4463
  }
4210
4464
  sleep() {
4465
+ this.#flushStateChange();
4211
4466
  callNativeSync(() => this.#runtime.actorSleep(this.#ctx));
4212
4467
  }
4213
4468
  destroy() {
@@ -4225,6 +4480,7 @@ var ActorContextHandleAdapter = class {
4225
4480
  }
4226
4481
  async dispose() {
4227
4482
  var _a;
4483
+ this.#flushStateChange();
4228
4484
  (_a = this.#abortSignalCleanup) == null ? void 0 : _a.call(this);
4229
4485
  this.#sql = void 0;
4230
4486
  }
@@ -4252,13 +4508,12 @@ var ActorContextHandleAdapter = class {
4252
4508
  return actorState.state;
4253
4509
  }
4254
4510
  #writeState(value, options) {
4255
- encodeValue(value);
4256
4511
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
4257
4512
  actorState.state = value;
4258
4513
  if (!options.scheduleSave) {
4259
4514
  return;
4260
4515
  }
4261
- this.#handleStateChange();
4516
+ this.#scheduleSave();
4262
4517
  }
4263
4518
  #assertCanMutateState() {
4264
4519
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
@@ -4266,9 +4521,31 @@ var ActorContextHandleAdapter = class {
4266
4521
  throw stateMutationReentrantError();
4267
4522
  }
4268
4523
  }
4269
- #handleStateChange() {
4524
+ // Coalesce the request-save and onStateChange work to once per event loop
4525
+ // tick. A synchronous burst of mutations (for example
4526
+ // `Object.assign(c.state, ...)`) would otherwise cross the NAPI boundary and
4527
+ // run onStateChange once per field, re-serializing the whole state each time
4528
+ // and pinning the event loop on large state.
4529
+ #scheduleSave() {
4530
+ const actorState = getNativePersistState(this.#runtime, this.#ctx);
4531
+ if (actorState.saveScheduled) {
4532
+ return;
4533
+ }
4534
+ actorState.saveScheduled = true;
4535
+ actorState.pendingSaveHandle = setImmediate(() => {
4536
+ this.#flushStateChange();
4537
+ });
4538
+ }
4539
+ #flushStateChange() {
4270
4540
  const actorState = getNativePersistState(this.#runtime, this.#ctx);
4271
- encodeValue(actorState.state);
4541
+ if (!actorState.saveScheduled) {
4542
+ return;
4543
+ }
4544
+ actorState.saveScheduled = false;
4545
+ if (actorState.pendingSaveHandle !== void 0) {
4546
+ clearImmediate(actorState.pendingSaveHandle);
4547
+ actorState.pendingSaveHandle = void 0;
4548
+ }
4272
4549
  callNativeSync(
4273
4550
  () => this.#runtime.actorRequestSave(this.#ctx, { immediate: false })
4274
4551
  );
@@ -4446,40 +4723,7 @@ function withConnContext(runtime, ctx, conn, clientFactory, schemas = {}, databa
4446
4723
  }
4447
4724
  );
4448
4725
  }
4449
- function buildNativeRequestErrorResponse(encoding, path, error) {
4450
- const { statusCode, group, code, message, metadata } = deconstructError(
4451
- error,
4452
- logger2(),
4453
- {
4454
- path,
4455
- runtime: "native"
4456
- },
4457
- false
4458
- );
4459
- const body = serializeWithEncoding(
4460
- encoding,
4461
- { group, code, message, metadata },
4462
- HTTP_RESPONSE_ERROR_VERSIONED,
4463
- CURRENT_VERSION,
4464
- HttpResponseErrorSchema,
4465
- (value) => value,
4466
- (value) => ({
4467
- group: value.group,
4468
- code: value.code,
4469
- message: value.message,
4470
- metadata: value.metadata === void 0 ? null : runtimeBytesToArrayBuffer(
4471
- encodeCborCompat(value.metadata)
4472
- )
4473
- })
4474
- );
4475
- return new Response(body, {
4476
- status: statusCode,
4477
- headers: {
4478
- "Content-Type": contentTypeForEncoding(encoding)
4479
- }
4480
- });
4481
- }
4482
- function buildActorConfig(definition, registryConfig) {
4726
+ function buildActorConfig(definition, registryConfig, runtimeKind) {
4483
4727
  const config = definition.config;
4484
4728
  const options = config.options ?? {};
4485
4729
  const canHibernate = options.canHibernateWebSocket;
@@ -4488,6 +4732,7 @@ function buildActorConfig(definition, registryConfig) {
4488
4732
  icon: options.icon,
4489
4733
  hasDatabase: config.db !== void 0,
4490
4734
  remoteSqlite: config.db !== void 0 && sqliteBackendForConfig(registryConfig) === "remote",
4735
+ experimentalActorUds: registryConfig.experimentalActorUds,
4491
4736
  hasState: config.state !== void 0 || typeof config.createState === "function",
4492
4737
  canHibernateWebsocket: typeof canHibernate === "boolean" ? canHibernate : void 0,
4493
4738
  stateSaveIntervalMs: options.stateSaveInterval,
@@ -4508,9 +4753,79 @@ function buildActorConfig(definition, registryConfig) {
4508
4753
  maxOutgoingMessageSize: registryConfig.maxOutgoingMessageSize,
4509
4754
  preloadMaxWorkflowBytes: options.preloadMaxWorkflowBytes,
4510
4755
  preloadMaxConnectionsBytes: options.preloadMaxConnectionsBytes,
4511
- actions: Object.keys(config.actions ?? {}).sort().map((name) => ({ name }))
4756
+ actions: Object.keys(config.actions ?? {}).sort().map((name) => ({ name })),
4757
+ inspectorTabs: buildInspectorTabs(config.inspector, runtimeKind)
4512
4758
  };
4513
4759
  }
4760
+ function buildInspectorTabs(inspector, runtimeKind) {
4761
+ if (!inspector || typeof inspector !== "object") return void 0;
4762
+ const tabs = inspector.tabs;
4763
+ if (!Array.isArray(tabs) || tabs.length === 0) return void 0;
4764
+ return tabs.map((raw) => {
4765
+ const entry = raw;
4766
+ if (entry.hidden === true) {
4767
+ return { id: entry.id, hidden: true };
4768
+ }
4769
+ if (runtimeKind === "wasm") {
4770
+ if (entry.source !== void 0) {
4771
+ logger2().warn(
4772
+ {
4773
+ tabId: entry.id,
4774
+ runtimeKind
4775
+ },
4776
+ "inspector.tabs[].source is not supported on wasm runners (current host: wasm). Tab descriptors will still appear in the dashboard strip but the tab body will render a not-available placeholder."
4777
+ );
4778
+ }
4779
+ return {
4780
+ id: entry.id,
4781
+ label: entry.label,
4782
+ icon: entry.icon,
4783
+ source: void 0
4784
+ };
4785
+ }
4786
+ const resolved = entry.source !== void 0 ? getNodePath().resolve(entry.source) : void 0;
4787
+ if (resolved !== void 0) {
4788
+ validateInspectorTabSource(entry.id, resolved);
4789
+ }
4790
+ return {
4791
+ id: entry.id,
4792
+ label: entry.label,
4793
+ icon: entry.icon,
4794
+ source: resolved
4795
+ };
4796
+ });
4797
+ }
4798
+ function validateInspectorTabSource(tabId, resolved) {
4799
+ if (resolved === getNodePath().parse(resolved).root) {
4800
+ throw new Error(
4801
+ `inspector.tabs[id="${tabId}"].source resolves to the filesystem root (${resolved}). Point it at the tab's own static-asset directory instead.`
4802
+ );
4803
+ }
4804
+ let stat;
4805
+ try {
4806
+ stat = getNodeFsSync().statSync(resolved);
4807
+ } catch (err) {
4808
+ const code = err == null ? void 0 : err.code;
4809
+ if (code === "ENOENT") {
4810
+ throw new Error(
4811
+ `inspector.tabs[id="${tabId}"].source (${resolved}) does not exist.`
4812
+ );
4813
+ }
4814
+ if (code === "EACCES") {
4815
+ throw new Error(
4816
+ `inspector.tabs[id="${tabId}"].source (${resolved}) is not readable (EACCES).`
4817
+ );
4818
+ }
4819
+ throw new Error(
4820
+ `inspector.tabs[id="${tabId}"].source (${resolved}) could not be stat'd: ${(err == null ? void 0 : err.message) ?? err}`
4821
+ );
4822
+ }
4823
+ if (!stat.isDirectory()) {
4824
+ throw new Error(
4825
+ `inspector.tabs[id="${tabId}"].source (${resolved}) must be a directory, got ${stat.isFile() ? "file" : "non-directory"}.`
4826
+ );
4827
+ }
4828
+ }
4514
4829
  function buildNativeFactory(runtime, registryConfig, definition) {
4515
4830
  var _a;
4516
4831
  const config = definition.config;
@@ -4602,13 +4917,16 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4602
4917
  }
4603
4918
  );
4604
4919
  };
4605
- try {
4606
- await runtime.actorVerifyInspectorAuth(
4607
- ctx,
4608
- ((_a2 = jsRequest.headers.get("authorization")) == null ? void 0 : _a2.replace(/^Bearer\s+/i, "")) ?? null
4609
- );
4610
- } catch (error) {
4611
- return errorResponse(error, 401);
4920
+ const isPublicPerActorPath = jsRequest.method === "GET" && url.pathname.startsWith("/inspector/custom-tabs/");
4921
+ if (!isPublicPerActorPath) {
4922
+ try {
4923
+ await runtime.actorVerifyInspectorAuth(
4924
+ ctx,
4925
+ ((_a2 = jsRequest.headers.get("authorization")) == null ? void 0 : _a2.replace(/^Bearer\s+/i, "")) ?? null
4926
+ );
4927
+ } catch (error) {
4928
+ return errorResponse(error, 401);
4929
+ }
4612
4930
  }
4613
4931
  const workflowHistory = () => {
4614
4932
  var _a3;
@@ -4675,6 +4993,47 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4675
4993
  messages
4676
4994
  });
4677
4995
  }
4996
+ if (url.pathname === "/inspector/queue" && jsRequest.method === "DELETE") {
4997
+ await runtime.actorQueueReset(ctx);
4998
+ return jsonResponse({});
4999
+ }
5000
+ if (url.pathname === "/inspector/queue" && jsRequest.method === "POST") {
5001
+ let body;
5002
+ try {
5003
+ body = await jsRequest.json();
5004
+ } catch {
5005
+ return errorResponse(
5006
+ new RivetError(
5007
+ "actor",
5008
+ "invalid_request",
5009
+ "Invalid inspector JSON body",
5010
+ { public: true }
5011
+ ),
5012
+ 400
5013
+ );
5014
+ }
5015
+ const name = body.name ?? "";
5016
+ if (name === "") {
5017
+ return errorResponse(
5018
+ new RivetError(
5019
+ "actor",
5020
+ "invalid_request",
5021
+ "Queue message name must not be empty",
5022
+ { public: true }
5023
+ ),
5024
+ 400
5025
+ );
5026
+ }
5027
+ const cbor = encodeCborCompat(
5028
+ body.body ?? null
5029
+ );
5030
+ const message = await runtime.actorQueueSend(ctx, name, cbor);
5031
+ return jsonResponse({
5032
+ id: message.id().toString(),
5033
+ name: message.name(),
5034
+ createdAtMs: message.createdAt()
5035
+ });
5036
+ }
4678
5037
  if (url.pathname === "/inspector/traces" && jsRequest.method === "GET") {
4679
5038
  return jsonResponse({ otlp: [], clamped: false });
4680
5039
  }
@@ -4699,6 +5058,10 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4699
5058
  isWorkflowEnabled: getNativeWorkflowInspector(ctx) !== void 0
4700
5059
  });
4701
5060
  } catch (error) {
5061
+ logger2().error({
5062
+ msg: "error replaying workflow history",
5063
+ error
5064
+ });
4702
5065
  return errorResponse(error);
4703
5066
  }
4704
5067
  }
@@ -4839,17 +5202,34 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4839
5202
  );
4840
5203
  }
4841
5204
  const body = await jsRequest.json();
5205
+ if (body.args !== void 0 && body.properties !== void 0) {
5206
+ return jsonResponse(
5207
+ { error: "use either args or properties, not both" },
5208
+ { status: 400 }
5209
+ );
5210
+ }
5211
+ if (body.properties !== void 0 && (body.properties === null || typeof body.properties !== "object" || Array.isArray(body.properties))) {
5212
+ return jsonResponse(
5213
+ { error: "properties must be an object" },
5214
+ { status: 400 }
5215
+ );
5216
+ }
5217
+ const args = body.properties !== void 0 ? [body.properties] : normalizeArgs(body.args);
4842
5218
  try {
4843
5219
  const output = await action(
4844
5220
  actorCtx,
4845
5221
  ...validateActionArgs(
4846
5222
  schemaConfig.actionInputSchemas,
4847
5223
  actionName,
4848
- body.args ?? []
5224
+ args
4849
5225
  )
4850
5226
  );
4851
5227
  return jsonResponse({ output });
4852
5228
  } catch (error) {
5229
+ logger2().error({
5230
+ msg: "Error handling inspector action request",
5231
+ error
5232
+ });
4853
5233
  return errorResponse(error);
4854
5234
  }
4855
5235
  }
@@ -4863,6 +5243,10 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4863
5243
  { status: 404 }
4864
5244
  );
4865
5245
  } catch (error) {
5246
+ logger2().error({
5247
+ msg: "Error handling inspector request",
5248
+ error
5249
+ });
4866
5250
  return errorResponse(error);
4867
5251
  } finally {
4868
5252
  await actorCtx.dispose();
@@ -4985,29 +5369,33 @@ function buildNativeFactory(runtime, registryConfig, definition) {
4985
5369
  async (error, payload) => {
4986
5370
  const { ctx } = unwrapTsfnPayload(error, payload);
4987
5371
  const actorCtx = makeActorCtx(ctx);
5372
+ const saveActorState = async () => {
5373
+ if (runtime.kind === "wasm") {
5374
+ await runtime.actorSaveState(
5375
+ ctx,
5376
+ actorCtx.serializeForTick("save")
5377
+ );
5378
+ } else {
5379
+ await actorCtx.saveState({
5380
+ immediate: true
5381
+ });
5382
+ }
5383
+ };
4988
5384
  try {
4989
5385
  if (onSleep) {
4990
- try {
4991
- await onSleep(actorCtx);
4992
- } finally {
4993
- if (runtime.kind === "wasm") {
4994
- await runtime.actorSaveState(
4995
- ctx,
4996
- actorCtx.serializeForTick("save")
4997
- );
4998
- } else {
4999
- await actorCtx.saveState({ immediate: true });
5000
- }
5001
- }
5386
+ await onSleep(actorCtx);
5002
5387
  }
5388
+ await saveActorState();
5003
5389
  } finally {
5004
- const runtimeState = getNativeRuntimeState(runtime, ctx);
5005
- if ((runtimeState.keepAwakeCount ?? 0) > 0) {
5006
- runtimeState.deferSleepCleanupUntilKeepAwakeIdle = true;
5007
- } else {
5008
- await cleanupNativeSleepRuntimeState(runtime, ctx);
5390
+ try {
5391
+ await cleanupNativeSleepRuntimeState(
5392
+ runtime,
5393
+ ctx,
5394
+ saveActorState
5395
+ );
5396
+ } finally {
5397
+ await actorCtx.dispose();
5009
5398
  }
5010
- await actorCtx.dispose();
5011
5399
  }
5012
5400
  }
5013
5401
  ),
@@ -5020,6 +5408,9 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5020
5408
  await config.onDestroy(actorCtx);
5021
5409
  }
5022
5410
  } finally {
5411
+ const actorId = callNativeSync(() => runtime.actorId(ctx));
5412
+ nativeRunHandlerActiveByActorId.delete(actorId);
5413
+ disposeRunInspector(config.run, actorId);
5023
5414
  resolveNativeDestroy(runtime, ctx);
5024
5415
  await actorCtx.closeDatabase();
5025
5416
  clearNativeRuntimeState(runtime, ctx);
@@ -5246,17 +5637,6 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5246
5637
  );
5247
5638
  }
5248
5639
  return await toRuntimeHttpResponse(response);
5249
- } catch (error2) {
5250
- const encodingHeader = jsRequest.headers.get(HEADER_ENCODING);
5251
- const encoding = encodingHeader === "cbor" || encodingHeader === "bare" ? encodingHeader : "json";
5252
- const path = new URL(jsRequest.url).pathname;
5253
- return await toRuntimeHttpResponse(
5254
- buildNativeRequestErrorResponse(
5255
- encoding,
5256
- path,
5257
- error2
5258
- )
5259
- );
5260
5640
  } finally {
5261
5641
  await (requestCtx == null ? void 0 : requestCtx.dispose());
5262
5642
  if (conn) {
@@ -5304,7 +5684,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5304
5684
  try {
5305
5685
  await run(actorCtx);
5306
5686
  } finally {
5307
- nativeRunHandlerActiveByActorId.set(actorId, false);
5687
+ nativeRunHandlerActiveByActorId.delete(actorId);
5308
5688
  await actorCtx.dispose();
5309
5689
  }
5310
5690
  }
@@ -5437,7 +5817,7 @@ function buildNativeFactory(runtime, registryConfig, definition) {
5437
5817
  };
5438
5818
  return runtime.createActorFactory(
5439
5819
  callbacks,
5440
- buildActorConfig(definition, registryConfig)
5820
+ buildActorConfig(definition, registryConfig, runtime.kind)
5441
5821
  );
5442
5822
  }
5443
5823
  async function buildServeConfig(config) {
@@ -5460,10 +5840,17 @@ async function buildServeConfig(config) {
5460
5840
  serverlessValidateEndpoint: config.validateServerlessEndpoint,
5461
5841
  serverlessMaxStartPayloadBytes: config.serverless.maxStartPayloadBytes
5462
5842
  };
5463
- if (config.startEngine) {
5843
+ try {
5464
5844
  const { getEnginePath } = await loadEngineCli();
5465
5845
  serveConfig.engineBinaryPath = getEnginePath();
5846
+ } catch (error) {
5847
+ logger2().warn({
5848
+ msg: "could not resolve a local engine binary; if a local engine must be spawned it will fail with engine.binary_unavailable \u2014 set RIVET_ENGINE_BINARY_PATH or install the @rivetkit/engine-cli platform package",
5849
+ error: stringifyError(error)
5850
+ });
5466
5851
  }
5852
+ serveConfig.engineHost = config.engineHost;
5853
+ serveConfig.enginePort = config.enginePort;
5467
5854
  if ((_a = config.test) == null ? void 0 : _a.enabled) {
5468
5855
  serveConfig.inspectorTestToken = getEnvUniversal("_RIVET_TEST_INSPECTOR_TOKEN") ?? "token";
5469
5856
  }
@@ -5474,6 +5861,9 @@ async function buildRegistryWithRuntime(config, runtime) {
5474
5861
  if (((_a = config.test) == null ? void 0 : _a.enabled) && getEnvUniversal("_RIVET_TEST_INSPECTOR_TOKEN") === void 0) {
5475
5862
  trySetProcessEnv("_RIVET_TEST_INSPECTOR_TOKEN", "token");
5476
5863
  }
5864
+ if (runtime.kind === "napi") {
5865
+ importNodeDependencies();
5866
+ }
5477
5867
  const registry = runtime.createRegistry();
5478
5868
  for (const [name, definition] of Object.entries(config.use)) {
5479
5869
  runtime.registerActor(
@@ -5497,8 +5887,24 @@ async function buildConfiguredRegistry(config) {
5497
5887
  }
5498
5888
 
5499
5889
  // src/registry/index.ts
5890
+ function signalExitCode(signal) {
5891
+ switch (signal) {
5892
+ case "SIGINT":
5893
+ return 130;
5894
+ case "SIGTERM":
5895
+ return 143;
5896
+ }
5897
+ }
5898
+ function finishShutdownSignal(signal) {
5899
+ if (process.pid === 1) {
5900
+ process.exit(signalExitCode(signal));
5901
+ }
5902
+ process.kill(process.pid, signal);
5903
+ }
5500
5904
  var Registry = class {
5501
5905
  #config;
5906
+ #buildConfiguredRegistry;
5907
+ routes;
5502
5908
  get config() {
5503
5909
  return this.#config;
5504
5910
  }
@@ -5513,18 +5919,34 @@ var Registry = class {
5513
5919
  #shutdownInstalled = false;
5514
5920
  #shutdownInFlight = null;
5515
5921
  #signalHandlers = {};
5516
- constructor(config) {
5922
+ constructor(config, deps) {
5923
+ var _a;
5517
5924
  this.#config = config;
5925
+ if ((_a = config.logging) == null ? void 0 : _a.baseLogger) {
5926
+ configureBaseLogger(config.logging.baseLogger);
5927
+ }
5928
+ this.#buildConfiguredRegistry = (deps == null ? void 0 : deps.buildConfiguredRegistry) ?? buildConfiguredRegistry;
5929
+ this.routes = {
5930
+ health: () => this.#healthRoute(),
5931
+ metadata: () => this.#metadataRoute(),
5932
+ prometheusMetrics: (request) => this.#prometheusMetricsRoute(request)
5933
+ };
5518
5934
  }
5935
+ /**
5936
+ * Fires `configureServerlessPool` once per process when the registry
5937
+ * config opts into it. Cached on the instance so repeated calls (from
5938
+ * `handler()` and `listen()`) only run the upsert once. The retry loop
5939
+ * inside `configureServerlessPool` tolerates the engine still warming up.
5940
+ */
5519
5941
  #ensureServerlessPoolConfigured(config) {
5520
5942
  if (!config.configurePool) return void 0;
5521
5943
  if (!this.#configureServerlessPoolPromise) {
5522
- this.#configureServerlessPoolPromise = configureServerlessPool(config).catch(
5523
- (error) => {
5524
- this.#configureServerlessPoolPromise = void 0;
5525
- throw error;
5526
- }
5527
- );
5944
+ this.#configureServerlessPoolPromise = configureServerlessPool(
5945
+ config
5946
+ ).catch((error) => {
5947
+ this.#configureServerlessPoolPromise = void 0;
5948
+ throw error;
5949
+ });
5528
5950
  this.#configureServerlessPoolPromise.catch(() => {
5529
5951
  });
5530
5952
  }
@@ -5545,7 +5967,7 @@ var Registry = class {
5545
5967
  const config = this.parseConfig();
5546
5968
  this.#printWelcome(config, "serverless");
5547
5969
  if (!this.#runtimeServerlessPromise) {
5548
- this.#runtimeServerlessPromise = buildConfiguredRegistry(config);
5970
+ this.#runtimeServerlessPromise = this.#buildConfiguredRegistry(config);
5549
5971
  }
5550
5972
  const { runtime, registry, serveConfig } = await this.#runtimeServerlessPromise;
5551
5973
  const isStartRequest = isServerlessStartRequest(
@@ -5560,7 +5982,7 @@ var Registry = class {
5560
5982
  if (isStartRequest) {
5561
5983
  try {
5562
5984
  await this.#ensureServerlessPoolConfigured(config);
5563
- } catch (error) {
5985
+ } catch (_error) {
5564
5986
  return new Response(
5565
5987
  JSON.stringify({
5566
5988
  group: "guard",
@@ -5674,7 +6096,7 @@ var Registry = class {
5674
6096
  if (isMetadataRequest && !isEngineMetadataRequest) {
5675
6097
  try {
5676
6098
  await this.#ensureServerlessPoolConfigured(config);
5677
- } catch (error) {
6099
+ } catch (_error) {
5678
6100
  return new Response(
5679
6101
  JSON.stringify({
5680
6102
  group: "guard",
@@ -5707,40 +6129,147 @@ var Registry = class {
5707
6129
  fetch: (request) => this.handler(request)
5708
6130
  };
5709
6131
  }
5710
- async diagnostics() {
5711
- var _a;
6132
+ /**
6133
+ * Bind an HTTP listener provided by the native (Rust) runtime and serve
6134
+ * the registry's serverless endpoints over it. Resolves only after the
6135
+ * registry is shut down (SIGINT/SIGTERM or `nativeRegistry.shutdown()`).
6136
+ *
6137
+ * @param opts.port Port to listen on. Defaults to `process.env.RIVET_PORT`
6138
+ * if set, otherwise 3000.
6139
+ * @param opts.host Address to bind. Defaults to `0.0.0.0`.
6140
+ * @param opts.publicDir If set, serves static files from this directory
6141
+ * as a fallback below the framework routes.
6142
+ *
6143
+ * @example
6144
+ * ```ts
6145
+ * await registry.listen();
6146
+ * await registry.listen({ port: 8080, publicDir: "./public" });
6147
+ * ```
6148
+ */
6149
+ async listen(opts = {}) {
6150
+ const port = opts.port ?? parsePortEnv(process.env.RIVET_PORT) ?? 3e3;
6151
+ const publicDir = opts.publicDir ?? getRivetkitPublicDir();
6152
+ const config = this.parseConfig();
6153
+ const configuredRegistryPromise = buildConfiguredRegistry(config);
6154
+ this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
6155
+ this.#runtimeServerlessPromise = configuredRegistryPromise;
6156
+ this.#installSignalHandlers(config);
6157
+ this.#printWelcome(config, "serverless", {
6158
+ port,
6159
+ host: opts.host,
6160
+ publicDir
6161
+ });
6162
+ this.#ensureServerlessPoolConfigured(config);
6163
+ const { runtime, registry, serveConfig } = await configuredRegistryPromise;
6164
+ await runtime.serveListener(
6165
+ registry,
6166
+ { port, host: opts.host, publicDir },
6167
+ serveConfig
6168
+ );
6169
+ }
6170
+ /**
6171
+ * Returns a health response suitable for mounting in a user-owned router.
6172
+ */
6173
+ async #healthRoute() {
6174
+ const configured = await this.#activeConfiguredRegistry();
6175
+ if (!configured) {
6176
+ return jsonRouteResponse(503, {
6177
+ status: "not_started",
6178
+ runtime: "rivetkit",
6179
+ version: VERSION
6180
+ });
6181
+ }
6182
+ const { runtime, registry } = configured;
6183
+ if (!runtime.registryHealth) {
6184
+ return jsonRouteResponse(501, {
6185
+ status: "unsupported",
6186
+ runtime: "rivetkit",
6187
+ version: VERSION
6188
+ });
6189
+ }
6190
+ const response = await runtime.registryHealth(registry);
6191
+ return new Response(new Uint8Array(response.body), {
6192
+ status: response.status,
6193
+ headers: response.headers
6194
+ });
6195
+ }
6196
+ /**
6197
+ * Returns serverless metadata suitable for mounting in a user-owned router.
6198
+ */
6199
+ async #metadataRoute() {
6200
+ const configured = await this.#activeConfiguredRegistry();
6201
+ if (!configured) {
6202
+ return new Response("registry not started\n", {
6203
+ status: 503,
6204
+ headers: { "content-type": "text/plain; charset=utf-8" }
6205
+ });
6206
+ }
6207
+ const { runtime, registry } = configured;
6208
+ if (!runtime.registryMetadata) {
6209
+ return new Response("metadata is not supported by this runtime\n", {
6210
+ status: 501,
6211
+ headers: { "content-type": "text/plain; charset=utf-8" }
6212
+ });
6213
+ }
6214
+ const response = await runtime.registryMetadata(registry);
6215
+ return new Response(new Uint8Array(response.body), {
6216
+ status: response.status,
6217
+ headers: response.headers
6218
+ });
6219
+ }
6220
+ /**
6221
+ * Returns a Prometheus metrics response suitable for mounting in a user-owned router.
6222
+ */
6223
+ async #prometheusMetricsRoute(_request) {
6224
+ const configured = await this.#activeConfiguredRegistry();
6225
+ if (!configured) {
6226
+ return new Response("registry not started\n", {
6227
+ status: 503,
6228
+ headers: { "content-type": "text/plain; charset=utf-8" }
6229
+ });
6230
+ }
6231
+ const { runtime, registry } = configured;
6232
+ if (!runtime.registryMetrics) {
6233
+ return new Response("metrics are not supported by this runtime\n", {
6234
+ status: 501,
6235
+ headers: { "content-type": "text/plain; charset=utf-8" }
6236
+ });
6237
+ }
6238
+ const response = await runtime.registryMetrics(registry);
6239
+ return new Response(new Uint8Array(response.body), {
6240
+ status: response.status,
6241
+ headers: response.headers
6242
+ });
6243
+ }
6244
+ async #activeConfiguredRegistry() {
5712
6245
  const candidates = [
5713
6246
  this.#runtimeServerlessPromise,
5714
6247
  this.#runtimeServeConfiguredPromise
5715
6248
  ].filter(
5716
6249
  (candidate) => candidate !== void 0
5717
6250
  );
5718
- for (const candidate of candidates) {
5719
- const { runtime, registry } = await candidate;
5720
- const diagnostics = await ((_a = runtime.registryDiagnostics) == null ? void 0 : _a.call(runtime, registry));
5721
- if (diagnostics) return diagnostics;
5722
- }
5723
- return { mode: "not_started", envoyActiveActorCount: null };
6251
+ if (candidates.length === 0) return void 0;
6252
+ return await candidates[0];
5724
6253
  }
5725
6254
  /**
5726
6255
  * Starts an actor envoy for standalone server deployments.
5727
6256
  */
5728
6257
  #startEnvoy(config, printWelcome) {
5729
6258
  if (!this.#runtimeServePromise) {
5730
- const configuredRegistryPromise = buildConfiguredRegistry(config);
6259
+ const configuredRegistryPromise = this.#buildConfiguredRegistry(config);
5731
6260
  this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
5732
6261
  this.#runtimeServePromise = configuredRegistryPromise.then(async ({ runtime, registry, serveConfig }) => {
5733
6262
  await runtime.serveRegistry(registry, serveConfig);
5734
- }).catch((err) => {
5735
- logger2().warn({ err }, "runtime registry serve errored");
6263
+ }).catch((error) => {
6264
+ logger2().warn({ error }, "runtime registry serve errored");
5736
6265
  });
5737
- this.#installSignalHandlers(config, configuredRegistryPromise);
6266
+ this.#installSignalHandlers(config);
5738
6267
  }
5739
6268
  if (printWelcome) {
5740
6269
  this.#printWelcome(config, "serverful");
5741
6270
  }
5742
6271
  }
5743
- #installSignalHandlers(config, configuredRegistryPromise) {
6272
+ #installSignalHandlers(config) {
5744
6273
  var _a;
5745
6274
  if (this.#shutdownInstalled) return;
5746
6275
  if ((_a = config.shutdown) == null ? void 0 : _a.disableSignalHandlers) return;
@@ -5749,58 +6278,86 @@ var Registry = class {
5749
6278
  }
5750
6279
  this.#shutdownInstalled = true;
5751
6280
  const install = (signal) => {
5752
- const handler = () => this.#onShutdownSignal(
5753
- signal,
5754
- config,
5755
- configuredRegistryPromise
5756
- );
6281
+ const handler = () => this.#onShutdownSignal(signal, config);
5757
6282
  this.#signalHandlers[signal] = handler;
5758
6283
  process.on(signal, handler);
5759
6284
  };
5760
6285
  install("SIGINT");
5761
6286
  install("SIGTERM");
5762
6287
  }
5763
- #onShutdownSignal(signal, config, configuredRegistryPromise) {
6288
+ #onShutdownSignal(signal, config) {
5764
6289
  if (this.#shutdownInFlight !== null) {
5765
6290
  this.#removeSignalHandlers();
5766
- process.kill(process.pid, signal);
6291
+ finishShutdownSignal(signal);
5767
6292
  return;
5768
6293
  }
5769
- this.#shutdownInFlight = this.#runShutdown(
5770
- signal,
5771
- config,
5772
- configuredRegistryPromise
5773
- ).catch((err) => {
6294
+ this.#shutdownInFlight = this.#drain(config).catch((err) => {
6295
+ logger2().warn({ err }, "shutdown error");
6296
+ }).then(() => {
6297
+ this.#removeSignalHandlers();
6298
+ finishShutdownSignal(signal);
6299
+ });
6300
+ }
6301
+ /**
6302
+ * Gracefully drains all live registries.
6303
+ *
6304
+ * Programmatic counterpart to the SIGINT/SIGTERM handlers: tears down
6305
+ * every live `CoreRegistry` (both `start()` and `handler()` modes) and
6306
+ * waits for the serve promise to resolve, all bounded by the shutdown
6307
+ * grace period. Unlike a signal-driven shutdown, this does not re-raise a
6308
+ * signal or exit the process. The caller owns process lifetime.
6309
+ *
6310
+ * Idempotent: concurrent or repeated calls share a single drain. Safe to
6311
+ * call even if nothing has been started.
6312
+ *
6313
+ * @example
6314
+ * ```ts
6315
+ * const registry = setup({ use: { counter } });
6316
+ * registry.start();
6317
+ * // ...later, on your own shutdown trigger:
6318
+ * await registry.shutdown();
6319
+ * ```
6320
+ */
6321
+ async shutdown() {
6322
+ if (this.#shutdownInFlight !== null) return this.#shutdownInFlight;
6323
+ const config = this.parseConfig();
6324
+ this.#removeSignalHandlers();
6325
+ this.#shutdownInFlight = this.#drain(config).catch((err) => {
5774
6326
  logger2().warn({ err }, "shutdown error");
5775
6327
  });
6328
+ return this.#shutdownInFlight;
5776
6329
  }
5777
- async #runShutdown(signal, config, configuredRegistryPromise) {
6330
+ async #drain(config) {
5778
6331
  var _a;
5779
- const gracePeriodMs = ((_a = config.shutdown) == null ? void 0 : _a.gracePeriodMs) ?? 3e4;
6332
+ const modeAPromise = this.#runtimeServeConfiguredPromise;
6333
+ const modeBPromise = this.#runtimeServerlessPromise;
6334
+ const gracePeriodMs = ((_a = config.shutdown) == null ? void 0 : _a.gracePeriodMs) ?? await this.#actorStopThresholdMs(modeAPromise ?? modeBPromise) ?? 30 * 60 * 1e3;
5780
6335
  const drain = async () => {
5781
- const registries = [
5782
- (async () => {
5783
- try {
5784
- const { runtime, registry } = await configuredRegistryPromise;
5785
- await runtime.shutdownRegistry(registry);
5786
- } catch (err) {
5787
- logger2().warn(
5788
- { err },
5789
- "runtime registry shutdown errored (mode A)"
5790
- );
5791
- }
5792
- })()
5793
- ];
5794
- const runtimeServerlessPromise = this.#runtimeServerlessPromise;
5795
- if (runtimeServerlessPromise !== void 0) {
6336
+ const registries = [];
6337
+ if (modeAPromise !== void 0) {
5796
6338
  registries.push(
5797
6339
  (async () => {
5798
6340
  try {
5799
- const { runtime, registry } = await runtimeServerlessPromise;
6341
+ const { runtime, registry } = await modeAPromise;
5800
6342
  await runtime.shutdownRegistry(registry);
5801
6343
  } catch (err) {
5802
6344
  logger2().warn(
5803
6345
  { err },
6346
+ "runtime registry shutdown errored (mode A)"
6347
+ );
6348
+ }
6349
+ })()
6350
+ );
6351
+ }
6352
+ if (modeBPromise !== void 0) {
6353
+ registries.push(
6354
+ (async () => {
6355
+ try {
6356
+ const { runtime, registry } = await modeBPromise;
6357
+ await runtime.shutdownRegistry(registry);
6358
+ } catch (err) {
6359
+ logger2().warn(
6360
+ { error: err },
5804
6361
  "runtime registry shutdown errored (mode B)"
5805
6362
  );
5806
6363
  }
@@ -5822,8 +6379,23 @@ var Registry = class {
5822
6379
  }
5823
6380
  )
5824
6381
  ]);
5825
- this.#removeSignalHandlers();
5826
- process.kill(process.pid, signal);
6382
+ }
6383
+ async #actorStopThresholdMs(configuredRegistryPromise) {
6384
+ var _a;
6385
+ if (configuredRegistryPromise === void 0) return void 0;
6386
+ try {
6387
+ const { runtime, registry } = await configuredRegistryPromise;
6388
+ const thresholdMs = await ((_a = runtime.registryActorStopThresholdMs) == null ? void 0 : _a.call(runtime, registry));
6389
+ if (thresholdMs !== void 0 && Number.isFinite(thresholdMs) && thresholdMs > 0) {
6390
+ return thresholdMs;
6391
+ }
6392
+ } catch (err) {
6393
+ logger2().warn(
6394
+ { err },
6395
+ "failed to read actor stop threshold for shutdown grace"
6396
+ );
6397
+ }
6398
+ return void 0;
5827
6399
  }
5828
6400
  #removeSignalHandlers() {
5829
6401
  for (const [signal, handler] of Object.entries(
@@ -5839,6 +6411,10 @@ var Registry = class {
5839
6411
  /**
5840
6412
  * Starts the actor envoy for standalone server deployments.
5841
6413
  *
6414
+ * Set `RIVETKIT_RUNTIME_MODE=serverless` to instead bind an HTTP listener
6415
+ * via `listen()` (Mode B). Mode A (envoy) and Mode B (listener) are
6416
+ * mutually exclusive per registry instance.
6417
+ *
5842
6418
  * @example
5843
6419
  * ```ts
5844
6420
  * const registry = setup({ use: { counter } });
@@ -5846,10 +6422,20 @@ var Registry = class {
5846
6422
  * ```
5847
6423
  */
5848
6424
  start() {
6425
+ if (getRivetkitRuntimeMode() === "serverless") {
6426
+ const publicDir = getRivetkitPublicDir() ?? "/public";
6427
+ this.listen({ publicDir }).catch((error) => {
6428
+ logger2().error({ error }, "auto-listen failed; exiting");
6429
+ if (typeof process !== "undefined" && typeof process.exit === "function") {
6430
+ process.exit(1);
6431
+ }
6432
+ });
6433
+ return;
6434
+ }
5849
6435
  const config = this.parseConfig();
5850
6436
  this.#startEnvoy(config, true);
5851
6437
  }
5852
- #printWelcome(config, kind) {
6438
+ #printWelcome(config, kind, listener) {
5853
6439
  if (config.noWelcome || this.#welcomePrinted) return;
5854
6440
  this.#welcomePrinted = true;
5855
6441
  const logLine = (label, value) => {
@@ -5864,13 +6450,20 @@ var Registry = class {
5864
6450
  logLine("Namespace", config.namespace);
5865
6451
  }
5866
6452
  if (config.endpoint) {
5867
- const endpointType = config.endpoint === ENGINE_ENDPOINT ? "local native" : "remote";
6453
+ const endpointType = config.startEngine || isLocalEngineEndpoint(config.endpoint) ? "local native" : "remote";
5868
6454
  logLine("Endpoint", `${config.endpoint} (${endpointType})`);
5869
6455
  }
5870
6456
  if (kind === "serverless" && config.publicEndpoint) {
5871
6457
  logLine("Client", config.publicEndpoint);
5872
6458
  }
5873
6459
  logLine("Actors", Object.keys(config.use).length.toString());
6460
+ if (listener) {
6461
+ const host = listener.host ?? "0.0.0.0";
6462
+ logLine("Listening", `http://${host}:${listener.port}`);
6463
+ if (listener.publicDir) {
6464
+ logLine("Public Dir", listener.publicDir);
6465
+ }
6466
+ }
5874
6467
  console.log();
5875
6468
  }
5876
6469
  };
@@ -5886,6 +6479,12 @@ function isServerlessMetadataRequest(request, basePath) {
5886
6479
  const normalizedBase = basePath === "/" ? "" : `/${basePath.replace(/^\/+|\/+$/g, "")}`;
5887
6480
  return parsed.pathname === `${normalizedBase}/metadata`;
5888
6481
  }
6482
+ function jsonRouteResponse(status, body) {
6483
+ return new Response(JSON.stringify(body), {
6484
+ status,
6485
+ headers: { "content-type": "application/json" }
6486
+ });
6487
+ }
5889
6488
  function setup(input) {
5890
6489
  return new Registry(input);
5891
6490
  }