rivetkit 2.3.0-rc.8 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/dist/browser/client.d.ts +481 -74
  2. package/dist/browser/client.js +174 -148
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +47 -18
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +2 -2
  7. package/dist/tsup/actor/errors.d.cts +1 -1
  8. package/dist/tsup/actor/errors.d.ts +1 -1
  9. package/dist/tsup/actor/errors.js +1 -1
  10. package/dist/tsup/agent-os/index.cjs +2160 -2086
  11. package/dist/tsup/agent-os/index.cjs.map +1 -1
  12. package/dist/tsup/agent-os/index.d.cts +479 -73
  13. package/dist/tsup/agent-os/index.d.ts +479 -73
  14. package/dist/tsup/agent-os/index.js +2160 -2086
  15. package/dist/tsup/agent-os/index.js.map +1 -1
  16. package/dist/tsup/{chunk-KY3CERZR.js → chunk-2OTRTA3J.js} +7 -21
  17. package/dist/tsup/chunk-2OTRTA3J.js.map +1 -0
  18. package/dist/tsup/{chunk-HGW6PBWR.cjs → chunk-3677IIOV.cjs} +11 -25
  19. package/dist/tsup/chunk-3677IIOV.cjs.map +1 -0
  20. package/dist/tsup/{chunk-OT7FF6GB.cjs → chunk-47HHIEXH.cjs} +24 -9
  21. package/dist/tsup/chunk-47HHIEXH.cjs.map +1 -0
  22. package/dist/tsup/{chunk-EMFKMVJR.js → chunk-4JDSFJS5.js} +69 -58
  23. package/dist/tsup/chunk-4JDSFJS5.js.map +1 -0
  24. package/dist/tsup/{chunk-7HLFSAJP.cjs → chunk-7QKCIVAY.cjs} +225 -214
  25. package/dist/tsup/chunk-7QKCIVAY.cjs.map +1 -0
  26. package/dist/tsup/{chunk-AWTPTUQ7.cjs → chunk-B6VUNZUD.cjs} +10 -10
  27. package/dist/tsup/{chunk-AWTPTUQ7.cjs.map → chunk-B6VUNZUD.cjs.map} +1 -1
  28. package/dist/tsup/{chunk-D3T3ZBSY.js → chunk-BEI24WTI.js} +2 -2
  29. package/dist/tsup/{chunk-TMLOKTRB.js → chunk-BRP62GZC.js} +1 -1
  30. package/dist/tsup/chunk-BRP62GZC.js.map +1 -0
  31. package/dist/tsup/{chunk-D5G75T7J.js → chunk-DPIMKYNB.js} +61 -2
  32. package/dist/tsup/chunk-DPIMKYNB.js.map +1 -0
  33. package/dist/tsup/{chunk-BATTOVHF.cjs → chunk-DXXJPH55.cjs} +40 -13
  34. package/dist/tsup/chunk-DXXJPH55.cjs.map +1 -0
  35. package/dist/tsup/{chunk-3YY5S6TV.js → chunk-HXUEHHJF.js} +2 -2
  36. package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
  37. package/dist/tsup/{chunk-4BPKKZJO.cjs → chunk-I4LN3FNT.cjs} +10 -10
  38. package/dist/tsup/chunk-I4LN3FNT.cjs.map +1 -0
  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-63WNTDRC.cjs → chunk-KORQB2IR.cjs} +1 -1
  42. package/dist/tsup/{chunk-63WNTDRC.cjs.map → chunk-KORQB2IR.cjs.map} +1 -1
  43. package/dist/tsup/{chunk-6TQSSJ4F.cjs → chunk-LVTBW2RE.cjs} +3 -3
  44. package/dist/tsup/{chunk-6TQSSJ4F.cjs.map → chunk-LVTBW2RE.cjs.map} +1 -1
  45. package/dist/tsup/{chunk-4JU3IPG2.js → chunk-MEHBWPLJ.js} +6 -6
  46. package/dist/tsup/chunk-MEHBWPLJ.js.map +1 -0
  47. package/dist/tsup/{chunk-SRNOPUC6.cjs → chunk-NIY3RSPX.cjs} +62 -3
  48. package/dist/tsup/chunk-NIY3RSPX.cjs.map +1 -0
  49. package/dist/tsup/{chunk-UZXQEGVJ.js → chunk-P2GNQ4RN.js} +4 -4
  50. package/dist/tsup/{chunk-UZXQEGVJ.js.map → chunk-P2GNQ4RN.js.map} +1 -1
  51. package/dist/tsup/{chunk-VUGENVIK.js → chunk-UMZVD6DQ.js} +22 -7
  52. package/dist/tsup/chunk-UMZVD6DQ.js.map +1 -0
  53. package/dist/tsup/{chunk-LD5YASJU.cjs → chunk-VE2X4KMG.cjs} +2 -2
  54. package/dist/tsup/{chunk-LD5YASJU.cjs.map → chunk-VE2X4KMG.cjs.map} +1 -1
  55. package/dist/tsup/{chunk-GBG63SUG.js → chunk-VTTFNQQI.js} +32 -5
  56. package/dist/tsup/chunk-VTTFNQQI.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/client/mod.cjs +9 -9
  60. package/dist/tsup/client/mod.d.cts +5 -5
  61. package/dist/tsup/client/mod.d.ts +5 -5
  62. package/dist/tsup/client/mod.js +8 -8
  63. package/dist/tsup/common/log.cjs +3 -3
  64. package/dist/tsup/common/log.js +2 -2
  65. package/dist/tsup/common/websocket.cjs +4 -4
  66. package/dist/tsup/common/websocket.js +3 -3
  67. package/dist/tsup/{config-Ak1lv4gF.d.ts → config-BxWAw3iH.d.ts} +512 -27
  68. package/dist/tsup/{config-DU_xj4qZ.d.cts → config-CZQQ-mso.d.cts} +512 -27
  69. package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.cts} +1 -2
  70. package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.ts} +1 -2
  71. package/dist/tsup/{context-DAAp4Lpg.d.ts → context-Bw7xq8w3.d.cts} +8 -8
  72. package/dist/tsup/{context-Dt_L55q8.d.cts → context-D8QA76sV.d.ts} +8 -8
  73. package/dist/tsup/db/drizzle.cjs +3 -3
  74. package/dist/tsup/db/drizzle.d.cts +1 -1
  75. package/dist/tsup/db/drizzle.d.ts +1 -1
  76. package/dist/tsup/db/drizzle.js +1 -1
  77. package/dist/tsup/db/mod.cjs +2 -2
  78. package/dist/tsup/db/mod.d.cts +2 -2
  79. package/dist/tsup/db/mod.d.ts +2 -2
  80. package/dist/tsup/db/mod.js +1 -1
  81. package/dist/tsup/dynamic/mod.cjs +24 -0
  82. package/dist/tsup/dynamic/mod.cjs.map +1 -0
  83. package/dist/tsup/dynamic/mod.d.cts +37 -0
  84. package/dist/tsup/dynamic/mod.d.ts +37 -0
  85. package/dist/tsup/dynamic/mod.js +24 -0
  86. package/dist/tsup/dynamic/mod.js.map +1 -0
  87. package/dist/tsup/inspector/mod.cjs +6 -6
  88. package/dist/tsup/inspector/mod.js +5 -5
  89. package/dist/tsup/inspector-tab/mod.cjs +173 -0
  90. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  91. package/dist/tsup/inspector-tab/mod.d.cts +250 -0
  92. package/dist/tsup/inspector-tab/mod.d.ts +250 -0
  93. package/dist/tsup/inspector-tab/mod.js +173 -0
  94. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  95. package/dist/tsup/mod.cjs +615 -348
  96. package/dist/tsup/mod.cjs.map +1 -1
  97. package/dist/tsup/mod.d.cts +5 -5
  98. package/dist/tsup/mod.d.ts +5 -5
  99. package/dist/tsup/mod.js +511 -244
  100. package/dist/tsup/mod.js.map +1 -1
  101. package/dist/tsup/test/mod.cjs +21 -18
  102. package/dist/tsup/test/mod.cjs.map +1 -1
  103. package/dist/tsup/test/mod.d.cts +4 -4
  104. package/dist/tsup/test/mod.d.ts +4 -4
  105. package/dist/tsup/test/mod.js +18 -15
  106. package/dist/tsup/test/mod.js.map +1 -1
  107. package/dist/tsup/{utils-DVekpm4I.d.cts → utils-DQosb24I.d.cts} +1 -1
  108. package/dist/tsup/{utils-DVekpm4I.d.ts → utils-DQosb24I.d.ts} +1 -1
  109. package/dist/tsup/utils.cjs +3 -3
  110. package/dist/tsup/utils.d.cts +1 -1
  111. package/dist/tsup/utils.d.ts +1 -1
  112. package/dist/tsup/utils.js +2 -2
  113. package/dist/tsup/workflow/mod.cjs +279 -279
  114. package/dist/tsup/workflow/mod.cjs.map +1 -1
  115. package/dist/tsup/workflow/mod.d.cts +6 -6
  116. package/dist/tsup/workflow/mod.d.ts +6 -6
  117. package/dist/tsup/workflow/mod.js +380 -380
  118. package/dist/tsup/workflow/mod.js.map +1 -1
  119. package/package.json +29 -9
  120. package/src/actor/config.ts +156 -51
  121. package/src/actor/contexts/index.ts +7 -2
  122. package/src/actor/definition.ts +17 -19
  123. package/src/actor/driver.ts +3 -3
  124. package/src/actor/errors.ts +8 -2
  125. package/src/actor/instance/mod.ts +26 -34
  126. package/src/actor/keys.ts +1 -1
  127. package/src/actor/mod.ts +22 -20
  128. package/src/actor/schema.ts +2 -2
  129. package/src/agent-os/actor/index.ts +38 -18
  130. package/src/agent-os/actor/preview.ts +1 -2
  131. package/src/agent-os/config.ts +1 -1
  132. package/src/agent-os/fs/database-vfs.ts +1 -1
  133. package/src/agent-os/index.ts +16 -15
  134. package/src/client/actor-common.ts +87 -54
  135. package/src/client/actor-conn.ts +11 -11
  136. package/src/client/actor-handle.ts +69 -52
  137. package/src/client/actor-query.ts +5 -5
  138. package/src/client/errors.ts +1 -1
  139. package/src/client/lifecycle-errors.ts +2 -4
  140. package/src/client/query.ts +1 -1
  141. package/src/client/queue.ts +8 -4
  142. package/src/client/raw-utils.ts +8 -6
  143. package/src/client/resolve-gateway-target.ts +1 -1
  144. package/src/client/utils.ts +2 -6
  145. package/src/common/actor-websocket.ts +3 -1
  146. package/src/common/bare/actor-persist/v1.ts +205 -163
  147. package/src/common/bare/actor-persist/v2.ts +265 -213
  148. package/src/common/bare/actor-persist/v3.ts +176 -172
  149. package/src/common/bare/actor-persist/v4.ts +254 -253
  150. package/src/common/bare/transport/v1.ts +659 -543
  151. package/src/common/client-protocol-versioned.ts +66 -64
  152. package/src/common/database/config.ts +2 -8
  153. package/src/common/database/native-database.ts +1 -1
  154. package/src/common/database/shared.ts +1 -0
  155. package/src/common/encoding.ts +13 -17
  156. package/src/common/engine.ts +28 -1
  157. package/src/common/eventsource.ts +1 -1
  158. package/src/common/inline-websocket-adapter.ts +3 -2
  159. package/src/common/router.ts +13 -17
  160. package/src/common/utils.ts +1 -2
  161. package/src/common/websocket-interface.ts +1 -1
  162. package/src/db/mod.ts +1 -1
  163. package/src/devtools-loader/index.ts +4 -7
  164. package/src/devtools-loader/serve-devtools.ts +26 -0
  165. package/src/drivers/engine/actor-driver.ts +48 -46
  166. package/src/dynamic/instance.ts +32 -0
  167. package/src/dynamic/internal.ts +50 -0
  168. package/src/dynamic/isolate-runtime.ts +66 -0
  169. package/src/dynamic/mod.ts +32 -0
  170. package/src/engine-client/actor-http-client.ts +3 -3
  171. package/src/engine-client/actor-websocket-client.ts +5 -5
  172. package/src/engine-client/api-endpoints.ts +51 -2
  173. package/src/engine-client/api-utils.ts +2 -2
  174. package/src/engine-client/driver.ts +1 -1
  175. package/src/engine-client/mod.ts +5 -3
  176. package/src/engine-client/ws-proxy.ts +9 -4
  177. package/src/inspector/client.browser.ts +5 -11
  178. package/src/inspector/mod.ts +1 -3
  179. package/src/inspector-tab/mod.ts +315 -0
  180. package/src/registry/config/envoy.ts +1 -2
  181. package/src/registry/config/index.ts +40 -16
  182. package/src/registry/index.ts +226 -83
  183. package/src/registry/napi-runtime.ts +46 -12
  184. package/src/registry/native-validation.ts +10 -12
  185. package/src/registry/native.ts +307 -164
  186. package/src/registry/process-metrics.ts +90 -23
  187. package/src/registry/runtime.ts +53 -6
  188. package/src/registry/wasm-runtime.ts +30 -3
  189. package/src/serde.ts +1 -1
  190. package/src/serverless/configure.ts +18 -7
  191. package/src/test/mod.ts +11 -8
  192. package/src/utils/endpoint-parser.ts +1 -1
  193. package/src/utils/env-vars.ts +6 -0
  194. package/src/utils/router.ts +1 -1
  195. package/src/utils/serve.ts +4 -5
  196. package/src/utils.ts +1 -2
  197. package/src/workflow/context.ts +30 -29
  198. package/src/workflow/driver.ts +4 -6
  199. package/src/workflow/inspector.ts +2 -2
  200. package/src/workflow/mod.ts +15 -17
  201. package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
  202. package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
  203. package/dist/tsup/chunk-4BPKKZJO.cjs.map +0 -1
  204. package/dist/tsup/chunk-4JU3IPG2.js.map +0 -1
  205. package/dist/tsup/chunk-7HLFSAJP.cjs.map +0 -1
  206. package/dist/tsup/chunk-BATTOVHF.cjs.map +0 -1
  207. package/dist/tsup/chunk-D5G75T7J.js.map +0 -1
  208. package/dist/tsup/chunk-EMFKMVJR.js.map +0 -1
  209. package/dist/tsup/chunk-GBG63SUG.js.map +0 -1
  210. package/dist/tsup/chunk-HGW6PBWR.cjs.map +0 -1
  211. package/dist/tsup/chunk-KY3CERZR.js.map +0 -1
  212. package/dist/tsup/chunk-OT7FF6GB.cjs.map +0 -1
  213. package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
  214. package/dist/tsup/chunk-SRNOPUC6.cjs.map +0 -1
  215. package/dist/tsup/chunk-TMLOKTRB.js.map +0 -1
  216. package/dist/tsup/chunk-VUGENVIK.js.map +0 -1
  217. package/dist/tsup/process-metrics-NW754INA.js +0 -118
  218. package/dist/tsup/process-metrics-NW754INA.js.map +0 -1
  219. package/dist/tsup/process-metrics-TYAGKCEJ.cjs +0 -118
  220. package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +0 -1
  221. /package/dist/tsup/{chunk-D3T3ZBSY.js.map → chunk-BEI24WTI.js.map} +0 -0
@@ -11,10 +11,37 @@
11
11
  * All data collection happens here in TypeScript. The NAPI bridge is pure
12
12
  * type marshalling and the Rust side only registers + stores the metrics.
13
13
  */
14
- import { monitorEventLoopDelay, performance, PerformanceObserver } from "node:perf_hooks";
14
+ import {
15
+ monitorEventLoopDelay,
16
+ PerformanceObserver,
17
+ performance,
18
+ } from "node:perf_hooks";
15
19
  import { getHeapStatistics } from "node:v8";
16
20
  import * as napi from "@rivetkit/rivetkit-napi";
17
21
 
22
+ type OptionalProcessMetricsNapi = typeof napi & {
23
+ jsObserveGcDuration?: (kind: string, durationSeconds: number) => void;
24
+ jsSetEventloopHeartbeatTsMs?: (timestampMs: number) => void;
25
+ jsSetEventloopLagQuantile?: (
26
+ quantile: string,
27
+ valueSeconds: number,
28
+ ) => void;
29
+ jsSetEventloopUtilization?: (utilization: number) => void;
30
+ jsAddProcessCpuSeconds?: (mode: string, valueSeconds: number) => void;
31
+ jsSetProcessResidentMemoryBytes?: (bytes: number) => void;
32
+ jsSetHeapBytes?: (kind: string, bytes: number) => void;
33
+ jsSetActiveHandles?: (count: number) => void;
34
+ jsSetActiveRequests?: (count: number) => void;
35
+ };
36
+
37
+ type GcPerformanceEntry = {
38
+ duration: number;
39
+ detail?: { kind?: number };
40
+ kind?: number;
41
+ };
42
+
43
+ const processMetricsNapi = napi as OptionalProcessMetricsNapi;
44
+
18
45
  // Some napi process-metrics symbols may be missing on older native binaries
19
46
  // (the auto-generated index.js destructures them as `undefined` if the
20
47
  // underlying `.node` was built before they were added). Guard each call so
@@ -50,7 +77,9 @@ interface ProcessMetricsState {
50
77
  gcObserver: PerformanceObserver;
51
78
  eventLoopHistogram: ReturnType<typeof monitorEventLoopDelay>;
52
79
  lastCpuUsage: NodeJS.CpuUsage;
53
- lastEventLoopUtilization: ReturnType<typeof performance.eventLoopUtilization>;
80
+ lastEventLoopUtilization: ReturnType<
81
+ typeof performance.eventLoopUtilization
82
+ >;
54
83
  }
55
84
 
56
85
  let state: ProcessMetricsState | undefined;
@@ -67,15 +96,17 @@ export function startProcessMetrics(): void {
67
96
 
68
97
  const gcObserver = new PerformanceObserver((list) => {
69
98
  for (const entry of list.getEntries()) {
70
- const kind =
71
- (entry as PerformanceEntry & { detail?: { kind?: number }; kind?: number }).detail
72
- ?.kind ??
73
- (entry as PerformanceEntry & { kind?: number }).kind;
99
+ const gcEntry = entry as GcPerformanceEntry;
100
+ const kind = gcEntry.detail?.kind ?? gcEntry.kind;
74
101
  if (typeof kind !== "number") continue;
75
102
  const kindName = GC_KIND_NAMES[kind];
76
103
  if (!kindName) continue;
77
104
  // `entry.duration` is in milliseconds; convert to seconds.
78
- callIfFn(napi.jsObserveGcDuration, kindName, entry.duration / 1000);
105
+ callIfFn(
106
+ processMetricsNapi.jsObserveGcDuration,
107
+ kindName,
108
+ gcEntry.duration / 1000,
109
+ );
79
110
  }
80
111
  });
81
112
  gcObserver.observe({ entryTypes: ["gc"], buffered: false });
@@ -84,7 +115,7 @@ export function startProcessMetrics(): void {
84
115
  const lastEventLoopUtilization = performance.eventLoopUtilization();
85
116
 
86
117
  const heartbeatInterval = setInterval(() => {
87
- callIfFn(napi.jsSetEventloopHeartbeatTsMs, Date.now());
118
+ callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
88
119
  }, HEARTBEAT_INTERVAL_MS);
89
120
  heartbeatInterval.unref();
90
121
 
@@ -108,7 +139,7 @@ export function startProcessMetrics(): void {
108
139
  };
109
140
 
110
141
  // Emit one snapshot immediately so freshly-scraped instances have data.
111
- callIfFn(napi.jsSetEventloopHeartbeatTsMs, Date.now());
142
+ callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
112
143
  try {
113
144
  collectAndPush();
114
145
  } catch {
@@ -134,17 +165,39 @@ function collectAndPush(): void {
134
165
  // nanoseconds; convert to seconds. Reset after reading so the next window
135
166
  // reflects only the new interval.
136
167
  const hist = state.eventLoopHistogram;
137
- callIfFn(napi.jsSetEventloopLagQuantile, "p50", hist.percentile(50) / NS_PER_SECOND);
138
- callIfFn(napi.jsSetEventloopLagQuantile, "p90", hist.percentile(90) / NS_PER_SECOND);
139
- callIfFn(napi.jsSetEventloopLagQuantile, "p99", hist.percentile(99) / NS_PER_SECOND);
140
- callIfFn(napi.jsSetEventloopLagQuantile, "max", hist.max / NS_PER_SECOND);
168
+ callIfFn(
169
+ processMetricsNapi.jsSetEventloopLagQuantile,
170
+ "p50",
171
+ hist.percentile(50) / NS_PER_SECOND,
172
+ );
173
+ callIfFn(
174
+ processMetricsNapi.jsSetEventloopLagQuantile,
175
+ "p90",
176
+ hist.percentile(90) / NS_PER_SECOND,
177
+ );
178
+ callIfFn(
179
+ processMetricsNapi.jsSetEventloopLagQuantile,
180
+ "p99",
181
+ hist.percentile(99) / NS_PER_SECOND,
182
+ );
183
+ callIfFn(
184
+ processMetricsNapi.jsSetEventloopLagQuantile,
185
+ "max",
186
+ hist.max / NS_PER_SECOND,
187
+ );
141
188
  hist.reset();
142
189
 
143
190
  // Event loop utilization delta over the scrape window.
144
191
  const nextElu = performance.eventLoopUtilization();
145
- const eluDelta = performance.eventLoopUtilization(nextElu, state.lastEventLoopUtilization);
192
+ const eluDelta = performance.eventLoopUtilization(
193
+ nextElu,
194
+ state.lastEventLoopUtilization,
195
+ );
146
196
  state.lastEventLoopUtilization = nextElu;
147
- callIfFn(napi.jsSetEventloopUtilization, eluDelta.utilization);
197
+ callIfFn(
198
+ processMetricsNapi.jsSetEventloopUtilization,
199
+ eluDelta.utilization,
200
+ );
148
201
 
149
202
  // CPU usage delta. `process.cpuUsage()` returns microseconds.
150
203
  const nextCpu = process.cpuUsage();
@@ -152,19 +205,27 @@ function collectAndPush(): void {
152
205
  const systemDeltaUs = nextCpu.system - state.lastCpuUsage.system;
153
206
  state.lastCpuUsage = nextCpu;
154
207
  if (userDeltaUs > 0) {
155
- callIfFn(napi.jsAddProcessCpuSeconds, "user", userDeltaUs / US_PER_SECOND);
208
+ callIfFn(
209
+ processMetricsNapi.jsAddProcessCpuSeconds,
210
+ "user",
211
+ userDeltaUs / US_PER_SECOND,
212
+ );
156
213
  }
157
214
  if (systemDeltaUs > 0) {
158
- callIfFn(napi.jsAddProcessCpuSeconds, "system", systemDeltaUs / US_PER_SECOND);
215
+ callIfFn(
216
+ processMetricsNapi.jsAddProcessCpuSeconds,
217
+ "system",
218
+ systemDeltaUs / US_PER_SECOND,
219
+ );
159
220
  }
160
221
 
161
222
  // Memory + heap.
162
223
  const mem = process.memoryUsage();
163
- callIfFn(napi.jsSetProcessResidentMemoryBytes, mem.rss);
164
- callIfFn(napi.jsSetHeapBytes, "used", mem.heapUsed);
165
- callIfFn(napi.jsSetHeapBytes, "total", mem.heapTotal);
224
+ callIfFn(processMetricsNapi.jsSetProcessResidentMemoryBytes, mem.rss);
225
+ callIfFn(processMetricsNapi.jsSetHeapBytes, "used", mem.heapUsed);
226
+ callIfFn(processMetricsNapi.jsSetHeapBytes, "total", mem.heapTotal);
166
227
  const heapLimit = getHeapStatistics().heap_size_limit;
167
- callIfFn(napi.jsSetHeapBytes, "limit", heapLimit);
228
+ callIfFn(processMetricsNapi.jsSetHeapBytes, "limit", heapLimit);
168
229
 
169
230
  // libuv active handles + requests. These are unstable Node internals
170
231
  // guarded behind underscore-prefixed names; if a future Node release
@@ -175,9 +236,15 @@ function collectAndPush(): void {
175
236
  _getActiveRequests?: () => unknown[];
176
237
  };
177
238
  if (typeof proc._getActiveHandles === "function") {
178
- callIfFn(napi.jsSetActiveHandles, proc._getActiveHandles().length);
239
+ callIfFn(
240
+ processMetricsNapi.jsSetActiveHandles,
241
+ proc._getActiveHandles().length,
242
+ );
179
243
  }
180
244
  if (typeof proc._getActiveRequests === "function") {
181
- callIfFn(napi.jsSetActiveRequests, proc._getActiveRequests().length);
245
+ callIfFn(
246
+ processMetricsNapi.jsSetActiveRequests,
247
+ proc._getActiveRequests().length,
248
+ );
182
249
  }
183
250
  }
@@ -1,5 +1,7 @@
1
+ import { stringifyError } from "@/common/utils";
1
2
  import type { SqliteNativeMetrics } from "@/common/database/config";
2
3
  import type { RegistryConfig } from "./config";
4
+ import { logger } from "./log";
3
5
 
4
6
  declare const handleBrand: unique symbol;
5
7
 
@@ -225,6 +227,22 @@ export interface RuntimeActorConfig {
225
227
  preloadMaxWorkflowBytes?: number;
226
228
  preloadMaxConnectionsBytes?: number;
227
229
  actions?: Array<{ name: string }>;
230
+ inspectorTabs?: Array<RuntimeInspectorTabEntry>;
231
+ }
232
+
233
+ export interface RuntimeInspectorTabEntry {
234
+ id: string;
235
+ /** Required for custom entries; omitted for built-in hides. */
236
+ label?: string;
237
+ /**
238
+ * Required for custom entries — absolute path to the source directory.
239
+ * Resolved on the TS side before being handed to the runtime.
240
+ */
241
+ source?: string;
242
+ /** Optional icon id for custom entries. */
243
+ icon?: string;
244
+ /** Set to true for built-in hide entries. */
245
+ hidden?: boolean;
228
246
  }
229
247
 
230
248
  export interface RuntimeServeConfig {
@@ -234,6 +252,8 @@ export interface RuntimeServeConfig {
234
252
  namespace: string;
235
253
  poolName: string;
236
254
  engineBinaryPath?: string;
255
+ engineHost?: string;
256
+ enginePort?: number;
237
257
  handleInspectorHttpInRuntime?: boolean;
238
258
  inspectorTestToken?: string;
239
259
  serverlessBasePath?: string;
@@ -257,9 +277,10 @@ export interface RuntimeServerlessResponseHead {
257
277
  headers: Record<string, string>;
258
278
  }
259
279
 
260
- export interface RuntimeRegistryDiagnostics {
261
- mode: string;
262
- envoyActiveActorCount?: number | null;
280
+ export interface RuntimeRegistryRouteResponse {
281
+ status: number;
282
+ headers: Record<string, string>;
283
+ body: RuntimeBytes;
263
284
  }
264
285
 
265
286
  export type RuntimeServerlessStreamEvent =
@@ -319,9 +340,15 @@ export interface CoreRuntime {
319
340
  cancelToken: CancellationTokenHandle,
320
341
  config: RuntimeServeConfig,
321
342
  ): Promise<RuntimeServerlessResponseHead>;
322
- registryDiagnostics?(
343
+ registryHealth?(
323
344
  registry: RegistryHandle,
324
- ): Promise<RuntimeRegistryDiagnostics>;
345
+ ): Promise<RuntimeRegistryRouteResponse>;
346
+ registryMetadata?(
347
+ registry: RegistryHandle,
348
+ ): Promise<RuntimeRegistryRouteResponse>;
349
+ registryMetrics?(
350
+ registry: RegistryHandle,
351
+ ): Promise<RuntimeRegistryRouteResponse>;
325
352
  createActorFactory(
326
353
  callbacks: object,
327
354
  config?: RuntimeActorConfig | undefined | null,
@@ -392,6 +419,9 @@ export interface CoreRuntime {
392
419
  ): void;
393
420
  actorWaitUntil(ctx: ActorContextHandle, promise: Promise<unknown>): void;
394
421
  actorWaitForTrackedShutdownWork(ctx: ActorContextHandle): Promise<boolean>;
422
+ actorWaitForTrackedShutdownWorkUnbounded(
423
+ ctx: ActorContextHandle,
424
+ ): Promise<void>;
395
425
  actorKeepAwake(ctx: ActorContextHandle, promise: Promise<unknown>): void;
396
426
  actorBeginKeepAwake(ctx: ActorContextHandle): number;
397
427
  actorEndKeepAwake(ctx: ActorContextHandle, regionId: number): void;
@@ -484,6 +514,7 @@ export interface CoreRuntime {
484
514
  ctx: ActorContextHandle,
485
515
  names: string[],
486
516
  options?: RuntimeQueueWaitOptions | undefined | null,
517
+ signal?: CancellationTokenHandle | undefined | null,
487
518
  ): Promise<void>;
488
519
  actorQueueEnqueueAndWait(
489
520
  ctx: ActorContextHandle,
@@ -570,9 +601,25 @@ export async function buildServeConfig(
570
601
  serverlessMaxStartPayloadBytes: config.serverless.maxStartPayloadBytes,
571
602
  };
572
603
 
573
- if (config.startEngine) {
604
+ // Always best-effort resolve the engine binary path and hand it to the core.
605
+ // The core alone decides whether to actually spawn a local engine, so JS must
606
+ // not duplicate that decision here. `loadEnginePath` throws when no binary is
607
+ // available (remote-only install, unsupported platform, optional deps
608
+ // skipped); in that case leave it unset and let the core report
609
+ // `engine.binary_unavailable` only if it actually needs one.
610
+ try {
574
611
  serveConfig.engineBinaryPath = await loadEnginePath();
612
+ } catch (error) {
613
+ // The engine binary could not be resolved. The core still decides whether
614
+ // it needs to spawn a local engine; if it does, it will fail with
615
+ // engine.binary_unavailable (auto-download is off in the napi runtime).
616
+ logger().warn({
617
+ msg: "could not resolve a local engine binary; if a local engine must be spawned it will fail with engine.binary_unavailable — set RIVET_ENGINE_BINARY_PATH or install the @rivetkit/engine-cli platform package",
618
+ error: stringifyError(error),
619
+ });
575
620
  }
621
+ serveConfig.engineHost = config.engineHost;
622
+ serveConfig.enginePort = config.enginePort;
576
623
  if (config.test?.enabled) {
577
624
  serveConfig.inspectorTestToken =
578
625
  process.env._RIVET_TEST_INSPECTOR_TOKEN ?? "token";
@@ -32,6 +32,7 @@ import type {
32
32
  RuntimeQueueNextBatchOptions,
33
33
  RuntimeQueueTryNextBatchOptions,
34
34
  RuntimeQueueWaitOptions,
35
+ RuntimeRegistryRouteResponse,
35
36
  RuntimeRequestSaveOpts,
36
37
  RuntimeServeConfig,
37
38
  RuntimeServerlessRequest,
@@ -270,8 +271,18 @@ export class WasmCoreRuntime implements CoreRuntime {
270
271
  await callWasm(() => asWasmRegistry(registry).shutdown());
271
272
  }
272
273
 
273
- async registryDiagnostics(): Promise<{ mode: string; envoyActiveActorCount: null }> {
274
- return { mode: "wasm", envoyActiveActorCount: null };
274
+ async registryHealth(): Promise<RuntimeRegistryRouteResponse> {
275
+ return {
276
+ status: 200,
277
+ headers: { "content-type": "application/json" },
278
+ body: new TextEncoder().encode(
279
+ JSON.stringify({
280
+ status: "ok",
281
+ runtime: "rivetkit",
282
+ version: "wasm",
283
+ }),
284
+ ),
285
+ };
275
286
  }
276
287
 
277
288
  async handleServerlessRequest(
@@ -508,6 +519,15 @@ export class WasmCoreRuntime implements CoreRuntime {
508
519
  );
509
520
  }
510
521
 
522
+ async actorWaitForTrackedShutdownWorkUnbounded(
523
+ ctx: ActorContextHandle,
524
+ ): Promise<void> {
525
+ await callHandle<Promise<void>>(
526
+ asWasmActorContext(ctx),
527
+ "waitForTrackedShutdownWorkUnbounded",
528
+ );
529
+ }
530
+
511
531
  actorKeepAwake(ctx: ActorContextHandle, promise: Promise<unknown>): void {
512
532
  const wasmCtx = asWasmActorContext(ctx);
513
533
  const regionId = callHandle<number>(wasmCtx, "beginKeepAwake");
@@ -753,9 +773,16 @@ export class WasmCoreRuntime implements CoreRuntime {
753
773
  ctx: ActorContextHandle,
754
774
  names: string[],
755
775
  options?: RuntimeQueueWaitOptions | undefined | null,
776
+ signal?: CancellationTokenHandle | undefined | null,
756
777
  ): Promise<void> {
757
778
  const queue = childHandle(asWasmActorContext(ctx), "queue");
758
- await callHandleAsync(queue, "waitForNamesAvailable", names, options);
779
+ await callHandleAsync(
780
+ queue,
781
+ "waitForNamesAvailable",
782
+ names,
783
+ options,
784
+ signal,
785
+ );
759
786
  }
760
787
 
761
788
  async actorQueueEnqueueAndWait(
package/src/serde.ts CHANGED
@@ -2,8 +2,8 @@ import * as cbor from "cbor-x";
2
2
  import invariant from "invariant";
3
3
  import type { VersionedDataHandler } from "vbare";
4
4
  import type { z } from "zod/v4";
5
+ import type { Encoding, JsonCompatValue } from "@/common/encoding";
5
6
  import { assertUnreachable } from "@/common/utils";
6
- import type { JsonCompatValue, Encoding } from "@/common/encoding";
7
7
  import {
8
8
  encodeJsonCompatValue,
9
9
  jsonParseCompat,
@@ -1,9 +1,9 @@
1
1
  import { convertRegistryConfigToClientConfig } from "@/client/config";
2
+ import { stringifyError } from "@/common/utils";
2
3
  import {
3
4
  getDatacenters,
4
5
  updateRunnerConfig,
5
6
  } from "@/engine-client/api-endpoints";
6
- import { stringifyError } from "@/common/utils";
7
7
  import type { RegistryConfig } from "@/registry/config";
8
8
  import { logger } from "@/registry/log";
9
9
 
@@ -16,11 +16,14 @@ function sleep(ms: number): Promise<void> {
16
16
 
17
17
  function configureTimeoutMs() {
18
18
  const value = process.env.RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS;
19
- if (value === undefined || value === "") return DEFAULT_CONFIGURE_TIMEOUT_MS;
19
+ if (value === undefined || value === "")
20
+ return DEFAULT_CONFIGURE_TIMEOUT_MS;
20
21
 
21
22
  const parsed = Number(value);
22
23
  if (!Number.isFinite(parsed) || parsed < 0) {
23
- throw new Error("RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS must be a finite non-negative number");
24
+ throw new Error(
25
+ "RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS must be a finite non-negative number",
26
+ );
24
27
  }
25
28
 
26
29
  return parsed;
@@ -40,13 +43,19 @@ export async function configureServerlessPool(
40
43
  attempts += 1;
41
44
  try {
42
45
  if (!config.namespace) {
43
- throw new Error("namespace is required for serverless configuration");
46
+ throw new Error(
47
+ "namespace is required for serverless configuration",
48
+ );
44
49
  }
45
50
  if (!config.endpoint) {
46
- throw new Error("endpoint is required for serverless configuration");
51
+ throw new Error(
52
+ "endpoint is required for serverless configuration",
53
+ );
47
54
  }
48
55
  if (!config.configurePool) {
49
- throw new Error("configurePool is required for serverless configuration");
56
+ throw new Error(
57
+ "configurePool is required for serverless configuration",
58
+ );
50
59
  }
51
60
 
52
61
  const customConfig = config.configurePool;
@@ -55,7 +64,9 @@ export async function configureServerlessPool(
55
64
  const poolName = customConfig.name ?? "default";
56
65
  const serverlessToken = config.token ?? config.publicToken;
57
66
  const headers = {
58
- ...(serverlessToken ? { "x-rivet-token": serverlessToken } : {}),
67
+ ...(serverlessToken
68
+ ? { "x-rivet-token": serverlessToken }
69
+ : {}),
59
70
  ...(customConfig.headers ?? {}),
60
71
  };
61
72
  const serverlessConfig = {
package/src/test/mod.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import pRetry from "p-retry";
2
2
  import type { TestContext } from "vitest";
3
- import { type Client, createClient } from "@/client/mod";
4
3
  import { convertRegistryConfigToClientConfig } from "@/client/config";
4
+ import { type Client, createClient } from "@/client/mod";
5
5
  import { getMetadata } from "@/engine-client/api-endpoints";
6
6
  import type { Registry } from "@/registry";
7
7
 
@@ -14,13 +14,16 @@ async function waitForRegistryReady(registry: Registry<any>): Promise<void> {
14
14
  registry.parseConfig(),
15
15
  );
16
16
 
17
- await pRetry(async () => {
18
- await getMetadata(clientConfig);
19
- }, {
20
- retries: 20,
21
- minTimeout: 50,
22
- maxTimeout: 250,
23
- });
17
+ await pRetry(
18
+ async () => {
19
+ await getMetadata(clientConfig);
20
+ },
21
+ {
22
+ retries: 20,
23
+ minTimeout: 50,
24
+ maxTimeout: 250,
25
+ },
26
+ );
24
27
  }
25
28
 
26
29
  export async function setupTest<A extends Registry<any>>(
@@ -1,4 +1,4 @@
1
- import { z } from "zod/v4";
1
+ import type { z } from "zod/v4";
2
2
 
3
3
  export interface ParsedEndpoint {
4
4
  endpoint: string;
@@ -22,6 +22,12 @@ export const getRivetTotalSlots = (): number | undefined => {
22
22
  };
23
23
  export const getRivetRunEngine = (): boolean =>
24
24
  getEnvUniversal("RIVET_RUN_ENGINE") === "1";
25
+ export const getRivetRunEngineHost = (): string | undefined =>
26
+ getEnvUniversal("RIVET_RUN_ENGINE_HOST");
27
+ export const getRivetRunEnginePort = (): number | undefined => {
28
+ const value = getEnvUniversal("RIVET_RUN_ENGINE_PORT");
29
+ return value !== undefined ? parseInt(value, 10) : undefined;
30
+ };
25
31
  export const getRivetRunEngineVersion = (): string | undefined =>
26
32
  getEnvUniversal("RIVET_RUN_ENGINE_VERSION");
27
33
  export const getRivetEnvoyKind = (): string | undefined =>
@@ -2,12 +2,12 @@ import { OpenAPIHono } from "@hono/zod-openapi";
2
2
  import type { Hono } from "hono";
3
3
  import { createMiddleware } from "hono/factory";
4
4
  import { cors } from "@/common/cors";
5
+ import { getLogger } from "@/common/log";
5
6
  import {
6
7
  handleRouteError,
7
8
  handleRouteNotFound,
8
9
  loggerMiddleware,
9
10
  } from "@/common/router";
10
- import { getLogger } from "@/common/log";
11
11
 
12
12
  export function logger() {
13
13
  return getLogger("router");
@@ -1,10 +1,9 @@
1
- import type { Hono } from "hono";
2
- import { detectRuntime, stringifyError, type Runtime } from "../utils";
3
- import { RegistryConfig } from "@/registry/config";
4
- import { logger } from "@/registry/log";
5
-
6
1
  // TODO: Go back to dynamic import for this
7
2
  import getPort from "get-port";
3
+ import type { Hono } from "hono";
4
+ import type { RegistryConfig } from "@/registry/config";
5
+ import { logger } from "@/registry/log";
6
+ import { detectRuntime, type Runtime, stringifyError } from "../utils";
8
7
 
9
8
  const DEFAULT_PORT = 6421;
10
9
  export type ServeStatic =
package/src/utils.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { stringifyError } from "@/common/utils";
2
1
  import type { Context as HonoContext, Handler as HonoHandler } from "hono";
3
- import { stringify as uuidstringify } from "uuid";
2
+ import { stringifyError } from "@/common/utils";
4
3
  import pkgJson from "../package.json" with { type: "json" };
5
4
  import { getLogger } from "./common/log";
6
5
  import { assertUnreachable } from "./common/utils";
@@ -1,41 +1,42 @@
1
1
  // @ts-nocheck
2
- import { RAW_STATE_SYMBOL, type RunContext } from "@/actor/config";
2
+
3
+ import type {
4
+ BranchConfig,
5
+ BranchOutput,
6
+ EntryKindType,
7
+ LoopConfig,
8
+ LoopResult,
9
+ StepConfig,
10
+ TryBlockConfig,
11
+ TryBlockResult,
12
+ TryStepConfig,
13
+ TryStepResult,
14
+ WorkflowContextInterface,
15
+ WorkflowQueueMessage,
16
+ } from "@rivetkit/workflow-engine";
3
17
  import type {
4
18
  QueueFilterName,
5
19
  QueueNextBatchOptions,
6
20
  QueueNextOptions,
7
21
  QueueResultMessageForName,
8
22
  } from "@/actor/config";
9
- import type { Client } from "@/client/client";
10
- import type { Registry } from "@/registry";
23
+ import { RAW_STATE_SYMBOL, type RunContext } from "@/actor/config";
11
24
  import type {
12
- BaseActorDefinition,
13
25
  AnyActorDefinition,
26
+ BaseActorDefinition,
14
27
  } from "@/actor/definition";
15
- import type {
16
- AnyDatabaseProvider,
17
- InferDatabaseClient,
18
- } from "@/common/database/config";
19
28
  import type {
20
29
  EventSchemaConfig,
21
30
  InferEventArgs,
22
31
  InferSchemaMap,
23
32
  QueueSchemaConfig,
24
33
  } from "@/actor/schema";
25
- import type { WorkflowContextInterface } from "@rivetkit/workflow-engine";
34
+ import type { Client } from "@/client/client";
26
35
  import type {
27
- BranchConfig,
28
- BranchOutput,
29
- EntryKindType,
30
- LoopConfig,
31
- LoopResult,
32
- StepConfig,
33
- TryBlockConfig,
34
- TryBlockResult,
35
- TryStepConfig,
36
- TryStepResult,
37
- WorkflowQueueMessage,
38
- } from "@rivetkit/workflow-engine";
36
+ AnyDatabaseProvider,
37
+ InferDatabaseClient,
38
+ } from "@/common/database/config";
39
+ import type { Registry } from "@/registry";
39
40
  import { WORKFLOW_GUARD_KV_KEY } from "./constants";
40
41
 
41
42
  type WorkflowActorQueueNextOptions<
@@ -80,7 +81,9 @@ type ActorWorkflowLoopConfig<
80
81
  TQueues
81
82
  >,
82
83
  state: S,
83
- ) => Promise<LoopResult<S, T> | (S extends undefined ? void : never)>;
84
+ ) => Promise<
85
+ LoopResult<S, T> | (S extends undefined ? undefined | void : never)
86
+ >;
84
87
  };
85
88
 
86
89
  type ActorWorkflowBranchConfig<
@@ -238,7 +241,7 @@ export class ActorWorkflowContext<
238
241
  }
239
242
 
240
243
  async step<T>(
241
- nameOrConfig: string | Parameters<WorkflowContextInterface["step"]>[0],
244
+ nameOrConfig: string | StepConfig<T>,
242
245
  run?: () => Promise<T>,
243
246
  ): Promise<T> {
244
247
  if (typeof nameOrConfig === "string") {
@@ -260,9 +263,7 @@ export class ActorWorkflowContext<
260
263
  }
261
264
 
262
265
  async tryStep<T>(
263
- nameOrConfig:
264
- | string
265
- | Parameters<WorkflowContextInterface["tryStep"]>[0],
266
+ nameOrConfig: string | TryStepConfig<T>,
266
267
  run?: () => Promise<T>,
267
268
  ): Promise<TryStepResult<T>> {
268
269
  if (typeof nameOrConfig === "string") {
@@ -329,13 +330,13 @@ export class ActorWorkflowContext<
329
330
  TEvents,
330
331
  TQueues
331
332
  >,
332
- ) => Promise<LoopResult<undefined, T> | void>,
333
+ ) => Promise<LoopResult<undefined, T> | undefined | void>,
333
334
  ): Promise<T>;
334
335
  async loop<T>(
335
336
  name: string,
336
337
  run: (
337
338
  ctx: WorkflowContextInterface,
338
- ) => Promise<LoopResult<undefined, T> | void>,
339
+ ) => Promise<LoopResult<undefined, T> | undefined | void>,
339
340
  ): Promise<T>;
340
341
  async loop<S, T>(
341
342
  config: ActorWorkflowLoopConfig<
@@ -379,7 +380,7 @@ export class ActorWorkflowContext<
379
380
  TEvents,
380
381
  TQueues
381
382
  >,
382
- ) => Promise<LoopResult<undefined, any> | void>,
383
+ ) => Promise<LoopResult<undefined, any> | undefined | void>,
383
384
  ): Promise<any> {
384
385
  if (typeof nameOrConfig === "string") {
385
386
  if (!run) {
@@ -1,10 +1,5 @@
1
1
  // @ts-nocheck
2
- import type { RunContext } from "@/actor/config";
3
- import type {
4
- AnyActorInstance,
5
- AnyStaticActorInstance,
6
- } from "@/actor/definition";
7
- import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
2
+
8
3
  import type {
9
4
  EngineDriver,
10
5
  KVEntry,
@@ -12,6 +7,9 @@ import type {
12
7
  Message,
13
8
  WorkflowMessageDriver,
14
9
  } from "@rivetkit/workflow-engine";
10
+ import type { RunContext } from "@/actor/config";
11
+ import type { AnyStaticActorInstance } from "@/actor/definition";
12
+ import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
15
13
 
16
14
  const WORKFLOW_STORAGE_PREFIX = workflowStoragePrefix();
17
15