rivetkit 2.0.9 → 2.0.11

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 (123) hide show
  1. package/dist/tsup/{chunk-F2YZNUPU.js → chunk-3JUN3IEH.js} +3 -3
  2. package/dist/tsup/{chunk-DL7TPF63.cjs → chunk-5ABUOI3V.cjs} +7 -7
  3. package/dist/tsup/{chunk-DL7TPF63.cjs.map → chunk-5ABUOI3V.cjs.map} +1 -1
  4. package/dist/tsup/{chunk-SDXTJDDR.cjs → chunk-5JZPEJVJ.cjs} +58 -14
  5. package/dist/tsup/chunk-5JZPEJVJ.cjs.map +1 -0
  6. package/dist/tsup/{chunk-SOC4HWCG.cjs → chunk-6PORXHSQ.cjs} +92 -39
  7. package/dist/tsup/chunk-6PORXHSQ.cjs.map +1 -0
  8. package/dist/tsup/{chunk-QGRYH6TU.cjs → chunk-765F7ILI.cjs} +7 -6
  9. package/dist/tsup/chunk-765F7ILI.cjs.map +1 -0
  10. package/dist/tsup/{chunk-DLPIL3VC.js → chunk-7DCESQ4O.js} +2 -2
  11. package/dist/tsup/{chunk-R7OP5N25.js → chunk-AZI2T6UF.js} +53 -9
  12. package/dist/tsup/chunk-AZI2T6UF.js.map +1 -0
  13. package/dist/tsup/{chunk-A44TWAS5.cjs → chunk-GGIW54I2.cjs} +6 -6
  14. package/dist/tsup/{chunk-A44TWAS5.cjs.map → chunk-GGIW54I2.cjs.map} +1 -1
  15. package/dist/tsup/{chunk-7OMMIAWP.cjs → chunk-HDCLOVOE.cjs} +17 -12
  16. package/dist/tsup/chunk-HDCLOVOE.cjs.map +1 -0
  17. package/dist/tsup/{chunk-2MJYYF2Q.cjs → chunk-I6AVFIVY.cjs} +12 -12
  18. package/dist/tsup/{chunk-2MJYYF2Q.cjs.map → chunk-I6AVFIVY.cjs.map} +1 -1
  19. package/dist/tsup/{chunk-WBSPHV5V.js → chunk-JTWD6ZT2.js} +2 -2
  20. package/dist/tsup/{chunk-4YV6RDZL.cjs → chunk-LXFOO25H.cjs} +722 -359
  21. package/dist/tsup/chunk-LXFOO25H.cjs.map +1 -0
  22. package/dist/tsup/{chunk-YR2VY4XS.js → chunk-MIP4PYTD.js} +5 -4
  23. package/dist/tsup/chunk-MIP4PYTD.js.map +1 -0
  24. package/dist/tsup/{chunk-KHZ2QSQ4.js → chunk-MT5ES4XD.js} +32 -10
  25. package/dist/tsup/chunk-MT5ES4XD.js.map +1 -0
  26. package/dist/tsup/{chunk-U2IXX6DY.cjs → chunk-NLYAKGML.cjs} +5 -6
  27. package/dist/tsup/chunk-NLYAKGML.cjs.map +1 -0
  28. package/dist/tsup/{chunk-FZP2IBIX.js → chunk-NOXYAPM2.js} +603 -240
  29. package/dist/tsup/chunk-NOXYAPM2.js.map +1 -0
  30. package/dist/tsup/{chunk-E63WU5PL.js → chunk-NQFIZSTR.js} +5 -6
  31. package/dist/tsup/chunk-NQFIZSTR.js.map +1 -0
  32. package/dist/tsup/{chunk-4PSLOAXR.cjs → chunk-O7BIBANW.cjs} +226 -204
  33. package/dist/tsup/chunk-O7BIBANW.cjs.map +1 -0
  34. package/dist/tsup/{chunk-VVCL5DXN.js → chunk-OHSP4BUE.js} +97 -44
  35. package/dist/tsup/{chunk-VVCL5DXN.js.map → chunk-OHSP4BUE.js.map} +1 -1
  36. package/dist/tsup/{chunk-APHV6WXU.js → chunk-SBUJ3KIM.js} +2 -2
  37. package/dist/tsup/{chunk-DZZQG7VH.cjs → chunk-WYTLLIJM.cjs} +3 -3
  38. package/dist/tsup/{chunk-DZZQG7VH.cjs.map → chunk-WYTLLIJM.cjs.map} +1 -1
  39. package/dist/tsup/{chunk-WRSWUDFA.js → chunk-XO7VX4MN.js} +14 -9
  40. package/dist/tsup/chunk-XO7VX4MN.js.map +1 -0
  41. package/dist/tsup/client/mod.cjs +9 -9
  42. package/dist/tsup/client/mod.d.cts +2 -2
  43. package/dist/tsup/client/mod.d.ts +2 -2
  44. package/dist/tsup/client/mod.js +8 -8
  45. package/dist/tsup/common/log.cjs +3 -3
  46. package/dist/tsup/common/log.js +2 -2
  47. package/dist/tsup/common/websocket.cjs +4 -4
  48. package/dist/tsup/common/websocket.js +3 -3
  49. package/dist/tsup/{conn-CEh3WKbA.d.cts → conn-CT_8ZBT_.d.cts} +204 -199
  50. package/dist/tsup/{conn-Bt8rkUzm.d.ts → conn-d5F0M95s.d.ts} +204 -199
  51. package/dist/tsup/driver-helpers/mod.cjs +5 -5
  52. package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
  53. package/dist/tsup/driver-helpers/mod.d.cts +1 -1
  54. package/dist/tsup/driver-helpers/mod.d.ts +1 -1
  55. package/dist/tsup/driver-helpers/mod.js +6 -6
  56. package/dist/tsup/driver-test-suite/mod.cjs +117 -103
  57. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  58. package/dist/tsup/driver-test-suite/mod.d.cts +3 -2
  59. package/dist/tsup/driver-test-suite/mod.d.ts +3 -2
  60. package/dist/tsup/driver-test-suite/mod.js +62 -48
  61. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  62. package/dist/tsup/inspector/mod.cjs +6 -6
  63. package/dist/tsup/inspector/mod.d.cts +6 -6
  64. package/dist/tsup/inspector/mod.d.ts +6 -6
  65. package/dist/tsup/inspector/mod.js +5 -5
  66. package/dist/tsup/mod.cjs +10 -10
  67. package/dist/tsup/mod.d.cts +8 -39
  68. package/dist/tsup/mod.d.ts +8 -39
  69. package/dist/tsup/mod.js +9 -9
  70. package/dist/tsup/test/mod.cjs +11 -11
  71. package/dist/tsup/test/mod.d.cts +1 -1
  72. package/dist/tsup/test/mod.d.ts +1 -1
  73. package/dist/tsup/test/mod.js +10 -10
  74. package/dist/tsup/utils.cjs +2 -2
  75. package/dist/tsup/utils.d.cts +2 -1
  76. package/dist/tsup/utils.d.ts +2 -1
  77. package/dist/tsup/utils.js +1 -1
  78. package/package.json +4 -5
  79. package/src/actor/driver.ts +2 -2
  80. package/src/actor/protocol/serde.ts +75 -3
  81. package/src/actor/router-endpoints.ts +6 -6
  82. package/src/actor/router.ts +2 -2
  83. package/src/client/actor-conn.ts +24 -3
  84. package/src/client/config.ts +19 -26
  85. package/src/driver-helpers/mod.ts +4 -1
  86. package/src/driver-test-suite/mod.ts +66 -44
  87. package/src/driver-test-suite/utils.ts +4 -1
  88. package/src/drivers/default.ts +11 -9
  89. package/src/drivers/engine/actor-driver.ts +42 -39
  90. package/src/drivers/engine/config.ts +9 -22
  91. package/src/drivers/engine/mod.ts +9 -8
  92. package/src/drivers/file-system/global-state.ts +4 -4
  93. package/src/engine-process/log.ts +5 -0
  94. package/src/engine-process/mod.ts +316 -0
  95. package/src/inspector/utils.ts +6 -4
  96. package/src/manager/driver.ts +2 -2
  97. package/src/manager/gateway.ts +29 -11
  98. package/src/manager/router-schema.ts +20 -0
  99. package/src/manager/router.ts +116 -29
  100. package/src/registry/mod.ts +168 -113
  101. package/src/registry/run-config.ts +116 -47
  102. package/src/registry/serve.ts +3 -1
  103. package/src/serde.ts +3 -3
  104. package/src/test/config.ts +2 -2
  105. package/src/test/mod.ts +6 -3
  106. package/src/utils.ts +2 -0
  107. package/dist/tsup/chunk-4PSLOAXR.cjs.map +0 -1
  108. package/dist/tsup/chunk-4YV6RDZL.cjs.map +0 -1
  109. package/dist/tsup/chunk-7OMMIAWP.cjs.map +0 -1
  110. package/dist/tsup/chunk-E63WU5PL.js.map +0 -1
  111. package/dist/tsup/chunk-FZP2IBIX.js.map +0 -1
  112. package/dist/tsup/chunk-KHZ2QSQ4.js.map +0 -1
  113. package/dist/tsup/chunk-QGRYH6TU.cjs.map +0 -1
  114. package/dist/tsup/chunk-R7OP5N25.js.map +0 -1
  115. package/dist/tsup/chunk-SDXTJDDR.cjs.map +0 -1
  116. package/dist/tsup/chunk-SOC4HWCG.cjs.map +0 -1
  117. package/dist/tsup/chunk-U2IXX6DY.cjs.map +0 -1
  118. package/dist/tsup/chunk-WRSWUDFA.js.map +0 -1
  119. package/dist/tsup/chunk-YR2VY4XS.js.map +0 -1
  120. /package/dist/tsup/{chunk-F2YZNUPU.js.map → chunk-3JUN3IEH.js.map} +0 -0
  121. /package/dist/tsup/{chunk-DLPIL3VC.js.map → chunk-7DCESQ4O.js.map} +0 -0
  122. /package/dist/tsup/{chunk-WBSPHV5V.js.map → chunk-JTWD6ZT2.js.map} +0 -0
  123. /package/dist/tsup/{chunk-APHV6WXU.js.map → chunk-SBUJ3KIM.js.map} +0 -0
@@ -11,9 +11,9 @@ import { createMiddleware } from "hono/factory";
11
11
  import { streamSSE } from "hono/streaming";
12
12
  import invariant from "invariant";
13
13
  import { z } from "zod";
14
- import { ActorNotFound, Unsupported } from "@/actor/errors";
14
+ import { ActorNotFound, InvalidRequest, Unsupported } from "@/actor/errors";
15
15
  import { serializeActorKey } from "@/actor/keys";
16
- import type { Encoding, Transport } from "@/client/mod";
16
+ import type { Client, Encoding, Transport } from "@/client/mod";
17
17
  import {
18
18
  WS_PROTOCOL_ACTOR,
19
19
  WS_PROTOCOL_CONN_ID,
@@ -28,7 +28,12 @@ import {
28
28
  handleRouteNotFound,
29
29
  loggerMiddleware,
30
30
  } from "@/common/router";
31
- import { deconstructError, noopNext, stringifyError } from "@/common/utils";
31
+ import {
32
+ assertUnreachable,
33
+ deconstructError,
34
+ noopNext,
35
+ stringifyError,
36
+ } from "@/common/utils";
32
37
  import { type ActorDriver, HEADER_ACTOR_ID } from "@/driver-helpers/mod";
33
38
  import type {
34
39
  TestInlineDriverCallRequest,
@@ -50,11 +55,14 @@ import {
50
55
  type Actor as ApiActor,
51
56
  } from "@/manager-api/actors";
52
57
  import { RivetIdSchema } from "@/manager-api/common";
58
+ import type { AnyClient } from "@/mod";
53
59
  import type { RegistryConfig } from "@/registry/config";
54
- import type { RunConfig } from "@/registry/run-config";
60
+ import type { DriverConfig, RunnerConfig } from "@/registry/run-config";
61
+ import { VERSION } from "@/utils";
55
62
  import type { ActorOutput, ManagerDriver } from "./driver";
56
63
  import { actorGateway, createTestWebSocketProxy } from "./gateway";
57
64
  import { logger } from "./log";
65
+ import { ServerlessStartHeadersSchema } from "./router-schema";
58
66
 
59
67
  function buildOpenApiResponses<T>(schema: T) {
60
68
  return {
@@ -77,9 +85,10 @@ function buildOpenApiResponses<T>(schema: T) {
77
85
 
78
86
  export function createManagerRouter(
79
87
  registryConfig: RegistryConfig,
80
- runConfig: RunConfig,
88
+ runConfig: RunnerConfig,
81
89
  managerDriver: ManagerDriver,
82
- serverlessActorDriverBuilder: (() => ActorDriver) | undefined,
90
+ driverConfig: DriverConfig,
91
+ client: AnyClient,
83
92
  ): { router: Hono; openapi: OpenAPIHono } {
84
93
  const router = new OpenAPIHono({ strict: false }).basePath(
85
94
  runConfig.basePath,
@@ -87,10 +96,38 @@ export function createManagerRouter(
87
96
 
88
97
  router.use("*", loggerMiddleware(logger()));
89
98
 
90
- if (serverlessActorDriverBuilder) {
91
- addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router);
92
- } else {
99
+ // HACK: Add Sec-WebSocket-Protocol header to fix KIT-339
100
+ //
101
+ // Some Deno WebSocket providers do not auto-set the protocol, which
102
+ // will cause some WebSocket clients to fail
103
+ router.use(
104
+ "*",
105
+ createMiddleware(async (c, next) => {
106
+ const upgrade = c.req.header("upgrade");
107
+ const isWebSocket = upgrade?.toLowerCase() === "websocket";
108
+ const isGet = c.req.method === "GET";
109
+
110
+ if (isGet && isWebSocket) {
111
+ c.header("Sec-WebSocket-Protocol", "rivet");
112
+ }
113
+
114
+ await next();
115
+ }),
116
+ );
117
+
118
+ if (runConfig.runnerKind === "serverless") {
119
+ addServerlessRoutes(
120
+ driverConfig,
121
+ registryConfig,
122
+ runConfig,
123
+ managerDriver,
124
+ client,
125
+ router,
126
+ );
127
+ } else if (runConfig.runnerKind === "normal") {
93
128
  addManagerRoutes(registryConfig, runConfig, managerDriver, router);
129
+ } else {
130
+ assertUnreachable(runConfig.runnerKind);
94
131
  }
95
132
 
96
133
  // Error handling
@@ -101,11 +138,11 @@ export function createManagerRouter(
101
138
  }
102
139
 
103
140
  function addServerlessRoutes(
104
- runConfig: RunConfig,
105
- serverlessActorDriverBuilder: (
106
- token: string | undefined,
107
- totalSlots: number | undefined,
108
- ) => ActorDriver,
141
+ driverConfig: DriverConfig,
142
+ registryConfig: RegistryConfig,
143
+ runConfig: RunnerConfig,
144
+ managerDriver: ManagerDriver,
145
+ client: AnyClient,
109
146
  router: OpenAPIHono,
110
147
  ) {
111
148
  // Apply CORS
@@ -120,28 +157,68 @@ function addServerlessRoutes(
120
157
 
121
158
  // Serverless start endpoint
122
159
  router.get("/start", async (c) => {
123
- const token = c.req.header("x-rivet-token");
124
- let totalSlots: number | undefined = parseInt(
125
- c.req.header("x-rivetkit-total-slots") as any,
126
- );
127
- if (isNaN(totalSlots)) totalSlots = undefined;
160
+ // Parse headers
161
+ const parseResult = ServerlessStartHeadersSchema.safeParse({
162
+ endpoint: c.req.header("x-rivet-endpoint"),
163
+ token: c.req.header("x-rivet-token") ?? undefined,
164
+ totalSlots: c.req.header("x-rivet-total-slots"),
165
+ runnerName: c.req.header("x-rivet-runner-name"),
166
+ namespace: c.req.header("x-rivet-namespace-id"),
167
+ });
168
+ if (!parseResult.success) {
169
+ throw new InvalidRequest(
170
+ parseResult.error.issues[0]?.message ??
171
+ "invalid serverless start headers",
172
+ );
173
+ }
174
+ const { endpoint, token, totalSlots, runnerName, namespace } =
175
+ parseResult.data;
176
+
177
+ logger().debug({
178
+ msg: "received serverless runner start request",
179
+ endpoint,
180
+ totalSlots,
181
+ runnerName,
182
+ namespace,
183
+ });
128
184
 
129
- const actorDriver = serverlessActorDriverBuilder(token, totalSlots);
185
+ // Override config
186
+ //
187
+ // We can't do a structuredClone here since this holds functions
188
+ const newRunConfig = Object.assign({}, runConfig);
189
+ newRunConfig.endpoint = endpoint;
190
+ newRunConfig.token = token;
191
+ newRunConfig.totalSlots = totalSlots;
192
+ newRunConfig.runnerName = runnerName;
193
+ newRunConfig.namespace = namespace;
194
+
195
+ // Create new actor driver with updated config
196
+ const actorDriver = driverConfig.actor(
197
+ registryConfig,
198
+ newRunConfig,
199
+ managerDriver,
200
+ client,
201
+ );
130
202
  invariant(
131
203
  actorDriver.serverlessHandleStart,
132
204
  "missing serverlessHandleStart on ActorDriver",
133
205
  );
206
+
134
207
  return await actorDriver.serverlessHandleStart(c);
135
208
  });
136
209
 
137
210
  router.get("/health", (c) => {
138
- return c.text("ok");
211
+ return c.json({
212
+ status: "ok",
213
+ runtime: "rivetkit",
214
+ version: VERSION,
215
+ });
139
216
  });
140
217
  }
141
218
 
142
219
  function addManagerRoutes(
143
220
  registryConfig: RegistryConfig,
144
- runConfig: RunConfig,
221
+ runConfig: RunnerConfig,
145
222
  managerDriver: ManagerDriver,
146
223
  router: OpenAPIHono,
147
224
  ) {
@@ -244,7 +321,9 @@ function addManagerRoutes(
244
321
  }
245
322
 
246
323
  return c.json<ActorsListResponse>({
247
- actors: actors.map(createApiActor),
324
+ actors: actors.map((actor) =>
325
+ createApiActor(actor, runConfig.runnerName),
326
+ ),
248
327
  });
249
328
  });
250
329
  }
@@ -278,7 +357,7 @@ function addManagerRoutes(
278
357
 
279
358
  if (existingActor) {
280
359
  return c.json<ActorsGetOrCreateResponse>({
281
- actor: createApiActor(existingActor),
360
+ actor: createApiActor(existingActor, runConfig.runnerName),
282
361
  created: false,
283
362
  });
284
363
  }
@@ -295,7 +374,7 @@ function addManagerRoutes(
295
374
  });
296
375
 
297
376
  return c.json<ActorsGetOrCreateResponse>({
298
- actor: createApiActor(newActor),
377
+ actor: createApiActor(newActor, runConfig.runnerName),
299
378
  created: true,
300
379
  });
301
380
  });
@@ -333,7 +412,7 @@ function addManagerRoutes(
333
412
  });
334
413
 
335
414
  // Transform ActorOutput to match ActorSchema
336
- const actor = createApiActor(actorOutput);
415
+ const actor = createApiActor(actorOutput, runConfig.runnerName);
337
416
 
338
417
  return c.json<ActorsCreateResponse>({ actor });
339
418
  });
@@ -564,7 +643,12 @@ function addManagerRoutes(
564
643
  }
565
644
 
566
645
  router.get("/health", (c) => {
567
- return c.text("ok");
646
+ return c.json({
647
+ status: "ok",
648
+ rivetkit: {
649
+ version: VERSION,
650
+ },
651
+ });
568
652
  });
569
653
 
570
654
  managerDriver.modifyManagerRouter?.(
@@ -573,13 +657,16 @@ function addManagerRoutes(
573
657
  );
574
658
  }
575
659
 
576
- function createApiActor(actor: ActorOutput): ApiActor {
660
+ function createApiActor(
661
+ actor: ActorOutput,
662
+ runnerName: string = "default",
663
+ ): ApiActor {
577
664
  return {
578
665
  actor_id: actor.actorId,
579
666
  name: actor.name,
580
667
  key: serializeActorKey(actor.key),
581
668
  namespace_id: "default", // Assert default namespace
582
- runner_name_selector: "rivetkit", // Assert rivetkit runner
669
+ runner_name_selector: runnerName,
583
670
  create_ts: Date.now(),
584
671
  connectable_ts: null,
585
672
  destroy_ts: null,
@@ -1,7 +1,9 @@
1
+ import invariant from "invariant";
1
2
  import { type Client, createClientWithDriver } from "@/client/client";
2
3
  import { configureBaseLogger, configureDefaultLogger } from "@/common/log";
3
4
  import type { ActorDriver } from "@/driver-helpers/mod";
4
5
  import { chooseDefaultDriver } from "@/drivers/default";
6
+ import { ENGINE_ENDPOINT, ensureEngineProcess } from "@/engine-process/mod";
5
7
  import {
6
8
  configureInspectorAccessToken,
7
9
  getInspectorUrl,
@@ -18,12 +20,16 @@ import {
18
20
  import { logger } from "./log";
19
21
  import {
20
22
  type DriverConfig,
21
- type RunConfig,
22
- type RunConfigInput,
23
- RunConfigSchema,
23
+ type RunnerConfig,
24
+ type RunnerConfigInput,
25
+ RunnerConfigSchema,
24
26
  } from "./run-config";
25
27
  import { crossPlatformServe } from "./serve";
26
28
 
29
+ export type ServerlessActorDriverBuilder = (
30
+ updateConfig: (config: RunnerConfig) => void,
31
+ ) => ActorDriver;
32
+
27
33
  interface ServerOutput<A extends Registry<any>> {
28
34
  /** Client to communicate with the actors. */
29
35
  client: Client<A>;
@@ -45,8 +51,49 @@ export class Registry<A extends RegistryActors> {
45
51
  /**
46
52
  * Runs the registry for a server.
47
53
  */
48
- public start(inputConfig?: RunConfigInput): ServerOutput<this> {
49
- const config = RunConfigSchema.parse(inputConfig);
54
+ public start(inputConfig?: RunnerConfigInput): ServerOutput<this> {
55
+ const config = RunnerConfigSchema.parse(inputConfig);
56
+
57
+ // Validate autoConfigureServerless is only used with serverless runner
58
+ if (config.autoConfigureServerless && config.runnerKind !== "serverless") {
59
+ throw new Error(
60
+ "autoConfigureServerless can only be configured when runnerKind is 'serverless'",
61
+ );
62
+ }
63
+
64
+ // Promise for any async operations we need to wait to complete
65
+ const readyPromises = [];
66
+
67
+ // Start engine
68
+ if (config.runEngine) {
69
+ logger().debug({
70
+ msg: "run engine requested",
71
+ version: config.runEngineVersion,
72
+ });
73
+
74
+ // Set config to point to the engine
75
+ invariant(
76
+ config.endpoint === undefined,
77
+ "cannot specify 'endpoint' with 'runEngine'",
78
+ );
79
+ config.endpoint = ENGINE_ENDPOINT;
80
+ config.disableActorDriver = true;
81
+
82
+ // Start the engine
83
+ const engineProcessPromise = ensureEngineProcess({
84
+ version: config.runEngineVersion,
85
+ });
86
+
87
+ // Chain ready promise
88
+ readyPromises.push(engineProcessPromise);
89
+ }
90
+
91
+ // Configure for serverless
92
+ if (config.runnerKind === "serverless") {
93
+ config.defaultServerPort = 8080;
94
+ config.overrideServerAddress = config.endpoint;
95
+ config.disableActorDriver = true;
96
+ }
50
97
 
51
98
  // Configure logger
52
99
  if (config.logging?.baseLogger) {
@@ -61,14 +108,18 @@ export class Registry<A extends RegistryActors> {
61
108
  // Choose the driver based on configuration
62
109
  const driver = chooseDefaultDriver(config);
63
110
 
64
- // TODO: Find cleaner way of disabling by default
111
+ // Set defaults based on the driver
65
112
  if (driver.name === "engine") {
66
113
  config.inspector.enabled = { manager: false, actor: true };
67
- config.disableServer = true;
114
+
115
+ // We need to leave the default server enabled for dev
116
+ if (config.runnerKind !== "serverless") {
117
+ config.disableDefaultServer = true;
118
+ }
68
119
  }
69
120
  if (driver.name === "cloudflare-workers") {
70
121
  config.inspector.enabled = { manager: false, actor: true };
71
- config.disableServer = true;
122
+ config.disableDefaultServer = true;
72
123
  config.disableActorDriver = true;
73
124
  config.noWelcome = true;
74
125
  }
@@ -102,7 +153,15 @@ export class Registry<A extends RegistryActors> {
102
153
  const displayInfo = managerDriver.displayInformation();
103
154
  console.log();
104
155
  console.log(` RivetKit ${pkg.version} (${displayInfo.name})`);
105
- console.log(` - Endpoint: http://127.0.0.1:6420`);
156
+ if (!config.disableDefaultServer) {
157
+ console.log(` - Endpoint: ${config.endpoint}`);
158
+ } else if (config.overrideServerAddress) {
159
+ console.log(` - Endpoint: ${config.overrideServerAddress}`);
160
+ }
161
+ if (config.runEngine) {
162
+ const padding = " ".repeat(Math.max(0, 13 - "Engine".length));
163
+ console.log(` - Engine:${padding}v${config.runEngineVersion}`);
164
+ }
106
165
  for (const [k, v] of Object.entries(displayInfo.properties)) {
107
166
  const padding = " ".repeat(Math.max(0, 13 - k.length));
108
167
  console.log(` - ${k}:${padding}${v}`);
@@ -116,27 +175,32 @@ export class Registry<A extends RegistryActors> {
116
175
  // HACK: We need to find a better way to let the driver itself decide when to start the actor driver
117
176
  // Create runner
118
177
  //
119
- // Even though we do not use the return value, this is required to start the code that will handle incoming actors
178
+ // Even though we do not use the returned ActorDriver, this is required to start the code that will handle incoming actors
120
179
  if (!config.disableActorDriver) {
121
- const _actorDriver = driver.actor(
122
- this.#config,
123
- config,
124
- managerDriver,
125
- client,
126
- );
180
+ Promise.all(readyPromises).then(async () => {
181
+ driver.actor(this.#config, config, managerDriver, client);
182
+ });
183
+ }
184
+
185
+ // Configure serverless runner if enabled when actor driver is disabled
186
+ if (config.runnerKind === "serverless" && config.autoConfigureServerless) {
187
+ Promise.all(readyPromises).then(async () => {
188
+ await configureServerlessRunner(config);
189
+ });
127
190
  }
128
191
 
129
192
  const { router: hono } = createManagerRouter(
130
193
  this.#config,
131
194
  config,
132
195
  managerDriver,
133
- undefined,
196
+ driver,
197
+ client,
134
198
  );
135
199
 
136
200
  // Start server
137
- if (!config.disableServer) {
201
+ if (!config.disableDefaultServer) {
138
202
  (async () => {
139
- const out = await crossPlatformServe(hono, undefined);
203
+ const out = await crossPlatformServe(config, hono, undefined);
140
204
  upgradeWebSocket = out.upgradeWebSocket;
141
205
  })();
142
206
  }
@@ -146,116 +210,107 @@ export class Registry<A extends RegistryActors> {
146
210
  fetch: hono.fetch.bind(hono),
147
211
  };
148
212
  }
213
+ }
149
214
 
150
- public startServerless(inputConfig?: RunConfigInput): ServerOutput<this> {
151
- const config = RunConfigSchema.parse(inputConfig);
152
-
153
- // Configure logger
154
- if (config.logging?.baseLogger) {
155
- // Use provided base logger
156
- configureBaseLogger(config.logging.baseLogger);
157
- } else {
158
- // Configure default logger with log level from config
159
- // getPinoLevel will handle env variable priority
160
- configureDefaultLogger(config.logging?.level);
215
+ async function configureServerlessRunner(config: RunnerConfig): Promise<void> {
216
+ try {
217
+ // Ensure we have required config values
218
+ if (!config.runnerName) {
219
+ throw new Error("runnerName is required for serverless configuration");
161
220
  }
162
-
163
- // Choose the driver based on configuration
164
- const driver = chooseDefaultDriver(config);
165
-
166
- // TODO: Find cleaner way of disabling by default
167
- if (driver.name === "engine") {
168
- config.inspector.enabled = false;
169
- config.disableServer = true;
170
- config.disableActorDriver = true;
221
+ if (!config.namespace) {
222
+ throw new Error("namespace is required for serverless configuration");
171
223
  }
172
- if (driver.name === "cloudflare-workers") {
173
- config.inspector.enabled = false;
174
- config.disableServer = true;
175
- config.disableActorDriver = true;
176
- config.noWelcome = true;
224
+ if (!config.endpoint) {
225
+ throw new Error("endpoint is required for serverless configuration");
177
226
  }
178
227
 
179
- // Configure getUpgradeWebSocket lazily so we can assign it in crossPlatformServe
180
- let upgradeWebSocket: any;
181
- if (!config.getUpgradeWebSocket) {
182
- config.getUpgradeWebSocket = () => upgradeWebSocket!;
183
- }
228
+ // Prepare the configuration
229
+ const customConfig =
230
+ typeof config.autoConfigureServerless === "object"
231
+ ? config.autoConfigureServerless
232
+ : {};
184
233
 
185
- // Create router
186
- const managerDriver = driver.manager(this.#config, config);
234
+ // Make the request to fetch all datacenters
235
+ const dcsUrl = `${config.endpoint}/datacenters`;
187
236
 
188
- // Create client
189
- const client = createClientWithDriver<this>(managerDriver, config);
237
+ logger().debug({
238
+ msg: "fetching datacenters",
239
+ url: dcsUrl,
240
+ });
190
241
 
191
- const driverLog = managerDriver.extraStartupLog?.() ?? {};
192
- logger().info({
193
- msg: "rivetkit ready",
194
- driver: driver.name,
195
- definitions: Object.keys(this.#config.use).length,
196
- ...driverLog,
242
+ const dcsResponse = await fetch(dcsUrl, {
243
+ headers: {
244
+ ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
245
+ },
197
246
  });
198
- if (config.inspector?.enabled && managerDriver.inspector) {
199
- logger().info({ msg: "inspector ready", url: getInspectorUrl(config) });
200
- }
201
247
 
202
- // Print welcome information
203
- if (!config.noWelcome) {
204
- const displayInfo = managerDriver.displayInformation();
205
- console.log();
206
- console.log(` RivetKit ${pkg.version} (${displayInfo.name})`);
207
- console.log(` - Endpoint: http://127.0.0.1:6420`);
208
- for (const [k, v] of Object.entries(displayInfo.properties)) {
209
- const padding = " ".repeat(Math.max(0, 13 - k.length));
210
- console.log(` - ${k}:${padding}${v}`);
211
- }
212
- if (config.inspector?.enabled && managerDriver.inspector) {
213
- console.log(` - Inspector: ${getInspectorUrl(config)}`);
214
- }
215
- console.log();
248
+ if (!dcsResponse.ok) {
249
+ const errorText = await dcsResponse.text();
250
+ throw new Error(
251
+ `failed to configure serverless runner: ${dcsResponse.status} ${dcsResponse.statusText} - ${errorText}`,
252
+ );
216
253
  }
217
254
 
218
- let serverlessActorDriverBuilder:
219
- | ((token?: string, totalSlots?: number) => ActorDriver)
220
- | undefined = (
221
- token: string | undefined,
222
- totalSlots: number | undefined,
223
- ) => {
224
- // Override config
225
- if (token) config.token = token;
226
- if (totalSlots) config.totalSlots = totalSlots;
227
-
228
- return driver.actor(this.#config, config, managerDriver, client);
255
+ const dcsRes = (await dcsResponse.json()) as {
256
+ datacenters: { name: string }[];
229
257
  };
230
258
 
231
- // HACK: We need to find a better way to let the driver itself decide when to start the actor driver
232
- // Create runner
233
- //
234
- // Even though we do not use the return value, this is required to start the code that will handle incoming actors
235
- if (!config.disableActorDriver) {
236
- const _actorDriver = serverlessActorDriverBuilder();
237
- serverlessActorDriverBuilder = undefined;
238
- }
239
-
240
- const { router: hono } = createManagerRouter(
241
- this.#config,
242
- config,
243
- managerDriver,
244
- serverlessActorDriverBuilder,
259
+ // Build the request body
260
+ const serverlessConfig = {
261
+ serverless: {
262
+ url:
263
+ customConfig.url ||
264
+ `http://localhost:${config.defaultServerPort}/start`,
265
+ headers: customConfig.headers || {},
266
+ max_runners: customConfig.maxRunners ?? 100,
267
+ min_runners: customConfig.minRunners ?? 0,
268
+ request_lifespan: customConfig.requestLifespan ?? 15 * 60,
269
+ runners_margin: customConfig.runnersMargin ?? 0,
270
+ slots_per_runner:
271
+ customConfig.slotsPerRunner ?? config.totalSlots ?? 1000,
272
+ },
273
+ };
274
+ const requestBody = Object.fromEntries(
275
+ dcsRes.datacenters.map((dc) => [dc.name, serverlessConfig]),
245
276
  );
246
277
 
247
- // Start server
248
- if (!config.disableServer) {
249
- (async () => {
250
- const out = await crossPlatformServe(hono, undefined);
251
- upgradeWebSocket = out.upgradeWebSocket;
252
- })();
278
+ // Make the request to configure the serverless runner
279
+ const configUrl = `${config.endpoint}/runner-configs/${config.runnerName}?namespace=${config.namespace}`;
280
+
281
+ logger().debug({
282
+ msg: "configuring serverless runner",
283
+ url: configUrl,
284
+ config: serverlessConfig.serverless,
285
+ });
286
+
287
+ const response = await fetch(configUrl, {
288
+ method: "PUT",
289
+ headers: {
290
+ "Content-Type": "application/json",
291
+ ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
292
+ },
293
+ body: JSON.stringify(requestBody),
294
+ });
295
+
296
+ if (!response.ok) {
297
+ const errorText = await response.text();
298
+ throw new Error(
299
+ `failed to configure serverless runner: ${response.status} ${response.statusText} - ${errorText}`,
300
+ );
253
301
  }
254
302
 
255
- return {
256
- client,
257
- fetch: hono.fetch.bind(hono),
258
- };
303
+ logger().info({
304
+ msg: "serverless runner configured successfully",
305
+ runnerName: config.runnerName,
306
+ namespace: config.namespace,
307
+ });
308
+ } catch (error) {
309
+ logger().error({
310
+ msg: "failed to configure serverless runner",
311
+ error,
312
+ });
313
+ throw error;
259
314
  }
260
315
  }
261
316
 
@@ -269,8 +324,8 @@ export function setup<A extends RegistryActors>(
269
324
  export type {
270
325
  RegistryConfig,
271
326
  RegistryActors,
272
- RunConfig,
273
- RunConfigInput,
327
+ RunnerConfig as RunConfig,
328
+ RunnerConfigInput as RunConfigInput,
274
329
  DriverConfig,
275
330
  };
276
331
  export { RegistryConfigSchema };