rivetkit 2.0.9 → 2.0.10

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-APHV6WXU.js → chunk-346X2XU4.js} +2 -2
  2. package/dist/tsup/{chunk-DLPIL3VC.js → chunk-7E5K3375.js} +2 -2
  3. package/dist/tsup/{chunk-SOC4HWCG.cjs → chunk-CA3X5M6H.cjs} +92 -39
  4. package/dist/tsup/{chunk-VVCL5DXN.js.map → chunk-CA3X5M6H.cjs.map} +1 -1
  5. package/dist/tsup/{chunk-2MJYYF2Q.cjs → chunk-DVPXSB4B.cjs} +12 -12
  6. package/dist/tsup/{chunk-2MJYYF2Q.cjs.map → chunk-DVPXSB4B.cjs.map} +1 -1
  7. package/dist/tsup/{chunk-U2IXX6DY.cjs → chunk-GIFHYL7A.cjs} +5 -6
  8. package/dist/tsup/chunk-GIFHYL7A.cjs.map +1 -0
  9. package/dist/tsup/{chunk-KHZ2QSQ4.js → chunk-H7E2UU23.js} +32 -10
  10. package/dist/tsup/chunk-H7E2UU23.js.map +1 -0
  11. package/dist/tsup/{chunk-E63WU5PL.js → chunk-HI55LHM3.js} +5 -6
  12. package/dist/tsup/chunk-HI55LHM3.js.map +1 -0
  13. package/dist/tsup/{chunk-SDXTJDDR.cjs → chunk-I3FB346I.cjs} +58 -14
  14. package/dist/tsup/chunk-I3FB346I.cjs.map +1 -0
  15. package/dist/tsup/{chunk-WBSPHV5V.js → chunk-KGDZYQYE.js} +2 -2
  16. package/dist/tsup/{chunk-A44TWAS5.cjs → chunk-KH5WFDUK.cjs} +6 -6
  17. package/dist/tsup/{chunk-A44TWAS5.cjs.map → chunk-KH5WFDUK.cjs.map} +1 -1
  18. package/dist/tsup/{chunk-YR2VY4XS.js → chunk-KL4V2ULR.js} +5 -4
  19. package/dist/tsup/chunk-KL4V2ULR.js.map +1 -0
  20. package/dist/tsup/{chunk-R7OP5N25.js → chunk-MLQIYKAZ.js} +53 -9
  21. package/dist/tsup/chunk-MLQIYKAZ.js.map +1 -0
  22. package/dist/tsup/{chunk-F2YZNUPU.js → chunk-N3A5GYJU.js} +3 -3
  23. package/dist/tsup/{chunk-4YV6RDZL.cjs → chunk-PDFL7FBL.cjs} +698 -358
  24. package/dist/tsup/chunk-PDFL7FBL.cjs.map +1 -0
  25. package/dist/tsup/{chunk-DZZQG7VH.cjs → chunk-PPLR53PP.cjs} +3 -3
  26. package/dist/tsup/{chunk-DZZQG7VH.cjs.map → chunk-PPLR53PP.cjs.map} +1 -1
  27. package/dist/tsup/{chunk-7OMMIAWP.cjs → chunk-PSCDCEXM.cjs} +17 -12
  28. package/dist/tsup/chunk-PSCDCEXM.cjs.map +1 -0
  29. package/dist/tsup/{chunk-VVCL5DXN.js → chunk-QRFXXTLG.js} +96 -43
  30. package/dist/tsup/chunk-QRFXXTLG.js.map +1 -0
  31. package/dist/tsup/{chunk-WRSWUDFA.js → chunk-R2S45MO6.js} +14 -9
  32. package/dist/tsup/chunk-R2S45MO6.js.map +1 -0
  33. package/dist/tsup/{chunk-QGRYH6TU.cjs → chunk-SIWYIRXP.cjs} +7 -6
  34. package/dist/tsup/chunk-SIWYIRXP.cjs.map +1 -0
  35. package/dist/tsup/{chunk-FZP2IBIX.js → chunk-VJRXZPTT.js} +579 -239
  36. package/dist/tsup/chunk-VJRXZPTT.js.map +1 -0
  37. package/dist/tsup/{chunk-4PSLOAXR.cjs → chunk-VZMXAZKC.cjs} +226 -204
  38. package/dist/tsup/chunk-VZMXAZKC.cjs.map +1 -0
  39. package/dist/tsup/{chunk-DL7TPF63.cjs → chunk-YKVTF7MP.cjs} +7 -7
  40. package/dist/tsup/{chunk-DL7TPF63.cjs.map → chunk-YKVTF7MP.cjs.map} +1 -1
  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-Cc9WHuN4.d.cts} +196 -191
  50. package/dist/tsup/{conn-Bt8rkUzm.d.ts → conn-DfPG71FA.d.ts} +196 -191
  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 +116 -102
  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 +61 -47
  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 +18 -25
  85. package/src/driver-helpers/mod.ts +4 -1
  86. package/src/driver-test-suite/mod.ts +65 -43
  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 +40 -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 +105 -23
  100. package/src/registry/mod.ts +145 -119
  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-APHV6WXU.js.map → chunk-346X2XU4.js.map} +0 -0
  121. /package/dist/tsup/{chunk-DLPIL3VC.js.map → chunk-7E5K3375.js.map} +0 -0
  122. /package/dist/tsup/{chunk-WBSPHV5V.js.map → chunk-KGDZYQYE.js.map} +0 -0
  123. /package/dist/tsup/{chunk-F2YZNUPU.js.map → chunk-N3A5GYJU.js.map} +0 -0
@@ -4,7 +4,7 @@ import {
4
4
  inspectorLogger,
5
5
  isInspectorEnabled,
6
6
  secureInspector
7
- } from "./chunk-YR2VY4XS.js";
7
+ } from "./chunk-KL4V2ULR.js";
8
8
  import {
9
9
  ActorDefinition,
10
10
  RemoteManagerDriver,
@@ -12,23 +12,24 @@ import {
12
12
  createClientWithDriver,
13
13
  deserializeActorKey,
14
14
  generateConnSocketId,
15
+ getEndpoint,
15
16
  lookupInRegistry,
16
17
  serializeActorKey
17
- } from "./chunk-KHZ2QSQ4.js";
18
+ } from "./chunk-H7E2UU23.js";
18
19
  import {
19
20
  CreateActorSchema
20
- } from "./chunk-WBSPHV5V.js";
21
+ } from "./chunk-KGDZYQYE.js";
21
22
  import {
22
23
  ActionContext,
23
24
  HTTP_ACTION_REQUEST_VERSIONED,
24
25
  HTTP_ACTION_RESPONSE_VERSIONED,
25
26
  HTTP_RESPONSE_ERROR_VERSIONED,
26
- RunConfigSchema,
27
+ RunnerConfigSchema,
27
28
  TO_SERVER_VERSIONED,
28
29
  createVersionedDataHandler,
29
30
  parseMessage,
30
31
  serializeEmptyPersistData
31
- } from "./chunk-VVCL5DXN.js";
32
+ } from "./chunk-QRFXXTLG.js";
32
33
  import {
33
34
  EncodingSchema,
34
35
  HEADER_ACTOR_ID,
@@ -54,22 +55,23 @@ import {
54
55
  generateRandomString,
55
56
  loggerWithoutContext,
56
57
  serializeWithEncoding
57
- } from "./chunk-R7OP5N25.js";
58
+ } from "./chunk-MLQIYKAZ.js";
58
59
  import {
59
60
  configureBaseLogger,
60
61
  configureDefaultLogger,
61
62
  getLogger
62
- } from "./chunk-DLPIL3VC.js";
63
+ } from "./chunk-7E5K3375.js";
63
64
  import {
65
+ VERSION,
66
+ assertUnreachable,
64
67
  bufferToArrayBuffer,
65
68
  deconstructError,
66
- getEnvUniversal,
67
69
  noopNext,
68
70
  package_default,
69
71
  promiseWithResolvers,
70
72
  setLongTimeout,
71
73
  stringifyError
72
- } from "./chunk-E63WU5PL.js";
74
+ } from "./chunk-HI55LHM3.js";
73
75
  import {
74
76
  ActorAlreadyExists,
75
77
  ConnNotFound,
@@ -77,6 +79,7 @@ import {
77
79
  InternalError,
78
80
  InvalidEncoding,
79
81
  InvalidParams,
82
+ InvalidRequest,
80
83
  MissingActorHeader,
81
84
  Unsupported,
82
85
  UserError,
@@ -746,13 +749,13 @@ async function handleConnectionClose(c, _runConfig, actorDriver, connId, connTok
746
749
  await conn.disconnect("Connection closed by client request");
747
750
  return c.json({});
748
751
  }
749
- async function handleRawWebSocketHandler(req, path3, actorDriver, actorId) {
752
+ async function handleRawWebSocketHandler(req, path4, actorDriver, actorId) {
750
753
  const actor2 = await actorDriver.loadActor(actorId);
751
754
  return {
752
755
  onOpen: (_evt, ws) => {
753
756
  const adapter = new HonoWebSocketAdapter(ws);
754
757
  ws.__adapter = adapter;
755
- const url = new URL(path3, "http://actor");
758
+ const url = new URL(path4, "http://actor");
756
759
  const pathname = url.pathname.replace(/^\/raw\/websocket\/?/, "") || "/";
757
760
  const normalizedPath = (pathname.startsWith("/") ? pathname : "/" + pathname) + url.search;
758
761
  let newRequest;
@@ -765,7 +768,7 @@ async function handleRawWebSocketHandler(req, path3, actorDriver, actorId) {
765
768
  }
766
769
  actor2.rLog.debug({
767
770
  msg: "rewriting websocket url",
768
- from: path3,
771
+ from: path4,
769
772
  to: newRequest.url,
770
773
  pathname: url.pathname,
771
774
  search: url.search,
@@ -828,17 +831,17 @@ import * as cbor2 from "cbor-x";
828
831
  function logger2() {
829
832
  return getLogger("router");
830
833
  }
831
- function loggerMiddleware(logger7) {
834
+ function loggerMiddleware(logger8) {
832
835
  return async (c, next) => {
833
836
  const method = c.req.method;
834
- const path3 = c.req.path;
837
+ const path4 = c.req.path;
835
838
  const startTime = Date.now();
836
839
  await next();
837
840
  const duration = Date.now() - startTime;
838
- logger7.debug({
841
+ logger8.debug({
839
842
  msg: "http request",
840
843
  method,
841
- path: path3,
844
+ path: path4,
842
845
  status: c.res.status,
843
846
  dt: `${duration}ms`,
844
847
  reqSize: c.req.header("content-length"),
@@ -1434,7 +1437,6 @@ var EngineActorDriver = class {
1434
1437
  #runConfig;
1435
1438
  #managerDriver;
1436
1439
  #inlineClient;
1437
- #config;
1438
1440
  #runner;
1439
1441
  #actors = /* @__PURE__ */ new Map();
1440
1442
  #actorRouter;
@@ -1443,27 +1445,29 @@ var EngineActorDriver = class {
1443
1445
  #alarmTimeout;
1444
1446
  #runnerStarted = Promise.withResolvers();
1445
1447
  #runnerStopped = Promise.withResolvers();
1446
- constructor(registryConfig, runConfig, managerDriver, inlineClient, config2) {
1448
+ constructor(registryConfig, runConfig, managerDriver, inlineClient) {
1447
1449
  this.#registryConfig = registryConfig;
1448
1450
  this.#runConfig = runConfig;
1449
1451
  this.#managerDriver = managerDriver;
1450
1452
  this.#inlineClient = inlineClient;
1451
- this.#config = config2;
1453
+ const token = runConfig.token ?? runConfig.token;
1454
+ if (token && runConfig.inspector && runConfig.inspector.enabled) {
1455
+ runConfig.inspector.token = () => token;
1456
+ }
1452
1457
  this.#actorRouter = createActorRouter(
1453
1458
  runConfig,
1454
1459
  this,
1455
1460
  registryConfig.test.enabled
1456
1461
  );
1457
1462
  let hasDisconnected = false;
1458
- const runnerConfig = {
1463
+ const engineRunnerConfig = {
1459
1464
  version: this.#version,
1460
- endpoint: config2.endpoint,
1461
- token: runConfig.token ?? config2.token,
1462
- pegboardEndpoint: config2.pegboardEndpoint,
1463
- namespace: config2.namespace,
1464
- totalSlots: runConfig.totalSlots ?? config2.totalSlots,
1465
- runnerName: config2.runnerName,
1466
- runnerKey: config2.runnerKey,
1465
+ endpoint: getEndpoint(runConfig),
1466
+ token,
1467
+ namespace: runConfig.namespace ?? runConfig.namespace,
1468
+ totalSlots: runConfig.totalSlots ?? runConfig.totalSlots,
1469
+ runnerName: runConfig.runnerName ?? runConfig.runnerName,
1470
+ runnerKey: runConfig.runnerKey,
1467
1471
  metadata: {
1468
1472
  inspectorToken: this.#runConfig.inspector.token()
1469
1473
  },
@@ -1477,14 +1481,14 @@ var EngineActorDriver = class {
1477
1481
  if (hasDisconnected) {
1478
1482
  logger4().info({
1479
1483
  msg: "runner reconnected",
1480
- namespace: this.#config.namespace,
1481
- runnerName: this.#config.runnerName
1484
+ namespace: this.#runConfig.namespace,
1485
+ runnerName: this.#runConfig.runnerName
1482
1486
  });
1483
1487
  } else {
1484
1488
  logger4().debug({
1485
1489
  msg: "runner connected",
1486
- namespace: this.#config.namespace,
1487
- runnerName: this.#config.runnerName
1490
+ namespace: this.#runConfig.namespace,
1491
+ runnerName: this.#runConfig.runnerName
1488
1492
  });
1489
1493
  }
1490
1494
  this.#runnerStarted.resolve(void 0);
@@ -1492,8 +1496,8 @@ var EngineActorDriver = class {
1492
1496
  onDisconnected: () => {
1493
1497
  logger4().warn({
1494
1498
  msg: "runner disconnected",
1495
- namespace: this.#config.namespace,
1496
- runnerName: this.#config.runnerName
1499
+ namespace: this.#runConfig.namespace,
1500
+ runnerName: this.#runConfig.runnerName
1497
1501
  });
1498
1502
  hasDisconnected = true;
1499
1503
  },
@@ -1506,13 +1510,13 @@ var EngineActorDriver = class {
1506
1510
  onActorStop: this.#runnerOnActorStop.bind(this),
1507
1511
  logger: getLogger("engine-runner")
1508
1512
  };
1509
- this.#runner = new Runner(runnerConfig);
1513
+ this.#runner = new Runner(engineRunnerConfig);
1510
1514
  this.#runner.start();
1511
1515
  logger4().debug({
1512
1516
  msg: "engine runner started",
1513
- endpoint: config2.endpoint,
1514
- namespace: config2.namespace,
1515
- runnerName: config2.runnerName
1517
+ endpoint: runConfig.endpoint,
1518
+ namespace: runConfig.namespace,
1519
+ runnerName: runConfig.runnerName
1516
1520
  });
1517
1521
  }
1518
1522
  async #loadActorHandler(actorId) {
@@ -1564,18 +1568,18 @@ var EngineActorDriver = class {
1564
1568
  return void 0;
1565
1569
  }
1566
1570
  // Runner lifecycle callbacks
1567
- async #runnerOnActorStart(actorId, generation, config2) {
1571
+ async #runnerOnActorStart(actorId, generation, runConfig) {
1568
1572
  var _a;
1569
1573
  logger4().debug({
1570
1574
  msg: "runner actor starting",
1571
1575
  actorId,
1572
- name: config2.name,
1573
- key: config2.key,
1576
+ name: runConfig.name,
1577
+ key: runConfig.key,
1574
1578
  generation
1575
1579
  });
1576
1580
  let input;
1577
- if (config2.input) {
1578
- input = cbor3.decode(config2.input);
1581
+ if (runConfig.input) {
1582
+ input = cbor3.decode(runConfig.input);
1579
1583
  }
1580
1584
  let handler = this.#actors.get(actorId);
1581
1585
  if (!handler) {
@@ -1585,14 +1589,10 @@ var EngineActorDriver = class {
1585
1589
  };
1586
1590
  this.#actors.set(actorId, handler);
1587
1591
  }
1588
- const name = config2.name;
1589
- invariant3(config2.key, "actor should have a key");
1590
- const key = deserializeActorKey(config2.key);
1591
- const definition = lookupInRegistry(
1592
- this.#registryConfig,
1593
- config2.name
1594
- // TODO: Remove cast
1595
- );
1592
+ const name = runConfig.name;
1593
+ invariant3(runConfig.key, "actor should have a key");
1594
+ const key = deserializeActorKey(runConfig.key);
1595
+ const definition = lookupInRegistry(this.#registryConfig, runConfig.name);
1596
1596
  handler.actor = definition.instantiate();
1597
1597
  await handler.actor.start(
1598
1598
  this,
@@ -1720,33 +1720,14 @@ var EngineActorDriver = class {
1720
1720
  return streamSSE2(c, async (stream) => {
1721
1721
  const payload = this.#runner.getServerlessInitPacket();
1722
1722
  invariant3(payload, "runnerId not set");
1723
- stream.writeSSE({ data: payload });
1723
+ await stream.writeSSE({ data: payload });
1724
1724
  return this.#runnerStopped.promise;
1725
1725
  });
1726
1726
  }
1727
1727
  };
1728
1728
 
1729
- // src/drivers/engine/config.ts
1730
- import { z as z2 } from "zod";
1731
- var ConfigSchema = z2.object({
1732
- app: z2.custom().optional(),
1733
- endpoint: z2.string().default(
1734
- () => getEnvUniversal("RIVET_ENGINE") ?? "http://localhost:6420"
1735
- ),
1736
- token: z2.string().optional().transform((val) => val ?? getEnvUniversal("RIVET_TOKEN")),
1737
- pegboardEndpoint: z2.string().optional(),
1738
- namespace: z2.string().default(() => getEnvUniversal("RIVET_NAMESPACE") ?? "default"),
1739
- runnerName: z2.string().default(() => getEnvUniversal("RIVET_RUNNER") ?? "rivetkit"),
1740
- // TODO: Automatically attempt to determine key by common env vars (e.g. k8s pod name)
1741
- runnerKey: z2.string().default(
1742
- () => getEnvUniversal("RIVET_RUNNER_KEY") ?? crypto.randomUUID()
1743
- ),
1744
- totalSlots: z2.number().default(1e5)
1745
- }).default({});
1746
-
1747
1729
  // src/drivers/engine/mod.ts
1748
- function createEngineDriver(inputConfig) {
1749
- const config2 = ConfigSchema.parse(inputConfig);
1730
+ function createEngineDriver() {
1750
1731
  return {
1751
1732
  name: "engine",
1752
1733
  manager: (_registryConfig, runConfig) => {
@@ -1757,8 +1738,7 @@ function createEngineDriver(inputConfig) {
1757
1738
  registryConfig,
1758
1739
  runConfig,
1759
1740
  managerDriver,
1760
- inlineClient,
1761
- config2
1741
+ inlineClient
1762
1742
  );
1763
1743
  }
1764
1744
  };
@@ -1949,9 +1929,9 @@ function getStoragePath(customPath) {
1949
1929
  const dirHash = createHashForPath(pathToHash);
1950
1930
  return path.join(dataPath, dirHash);
1951
1931
  }
1952
- async function pathExists(path3) {
1932
+ async function pathExists(path4) {
1953
1933
  try {
1954
- await fs.access(path3);
1934
+ await fs.access(path4);
1955
1935
  return true;
1956
1936
  } catch {
1957
1937
  return false;
@@ -2584,8 +2564,8 @@ var FileSystemManagerDriver = class {
2584
2564
  actorId
2585
2565
  });
2586
2566
  }
2587
- async openWebSocket(path3, actorId, encoding, params, connId, connToken) {
2588
- const pathOnly = path3.split("?")[0];
2567
+ async openWebSocket(path4, actorId, encoding, params, connId, connToken) {
2568
+ const pathOnly = path4.split("?")[0];
2589
2569
  const normalizedPath = pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
2590
2570
  if (normalizedPath === PATH_CONNECT_WEBSOCKET) {
2591
2571
  const wsHandler = await handleWebSocketConnect(
@@ -2602,13 +2582,13 @@ var FileSystemManagerDriver = class {
2602
2582
  } else if (normalizedPath.startsWith(PATH_RAW_WEBSOCKET_PREFIX) || normalizedPath === "/raw/websocket") {
2603
2583
  const wsHandler = await handleRawWebSocketHandler(
2604
2584
  void 0,
2605
- path3,
2585
+ path4,
2606
2586
  this.#actorDriver,
2607
2587
  actorId
2608
2588
  );
2609
2589
  return new InlineWebSocketAdapter2(wsHandler);
2610
2590
  } else {
2611
- throw new Error(`Unreachable path: ${path3}`);
2591
+ throw new Error(`Unreachable path: ${path4}`);
2612
2592
  }
2613
2593
  }
2614
2594
  async proxyRequest(c, actorRequest, actorId) {
@@ -2616,11 +2596,11 @@ var FileSystemManagerDriver = class {
2616
2596
  actorId
2617
2597
  });
2618
2598
  }
2619
- async proxyWebSocket(c, path3, actorId, encoding, connParams, connId, connToken) {
2599
+ async proxyWebSocket(c, path4, actorId, encoding, connParams, connId, connToken) {
2620
2600
  var _a, _b;
2621
2601
  const upgradeWebSocket = (_b = (_a = this.#runConfig).getUpgradeWebSocket) == null ? void 0 : _b.call(_a);
2622
2602
  invariant5(upgradeWebSocket, "missing getUpgradeWebSocket");
2623
- const pathOnly = path3.split("?")[0];
2603
+ const pathOnly = path4.split("?")[0];
2624
2604
  const normalizedPath = pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
2625
2605
  if (normalizedPath === PATH_CONNECT_WEBSOCKET) {
2626
2606
  const wsHandler = await handleWebSocketConnect(
@@ -2637,13 +2617,13 @@ var FileSystemManagerDriver = class {
2637
2617
  } else if (normalizedPath.startsWith(PATH_RAW_WEBSOCKET_PREFIX) || normalizedPath === "/raw/websocket") {
2638
2618
  const wsHandler = await handleRawWebSocketHandler(
2639
2619
  c.req.raw,
2640
- path3,
2620
+ path4,
2641
2621
  this.#actorDriver,
2642
2622
  actorId
2643
2623
  );
2644
2624
  return upgradeWebSocket(() => wsHandler)(c, noopNext());
2645
2625
  } else {
2646
- throw new Error(`Unreachable path: ${path3}`);
2626
+ throw new Error(`Unreachable path: ${path4}`);
2647
2627
  }
2648
2628
  }
2649
2629
  async getForId({ actorId }) {
@@ -2753,30 +2733,284 @@ function createMemoryDriver() {
2753
2733
  return createFileSystemOrMemoryDriver(false);
2754
2734
  }
2755
2735
 
2736
+ // src/registry/mod.ts
2737
+ import invariant7 from "invariant";
2738
+
2756
2739
  // src/drivers/default.ts
2757
2740
  function chooseDefaultDriver(runConfig) {
2758
2741
  if (runConfig.endpoint && runConfig.driver) {
2759
2742
  throw new UserError(
2760
- "Cannot specify both 'engine' and 'driver' in configuration"
2743
+ "Cannot specify both 'endpoint' and 'driver' in configuration"
2744
+ );
2745
+ }
2746
+ if (runConfig.runnerKind === "serverless" && !runConfig.endpoint) {
2747
+ throw new UserError(
2748
+ "Cannot use 'serverless' runnerKind without the 'endpoint' config set."
2761
2749
  );
2762
2750
  }
2763
2751
  if (runConfig.driver) {
2764
2752
  return runConfig.driver;
2765
2753
  }
2766
- if (runConfig.endpoint) {
2754
+ if (runConfig.endpoint || runConfig.token) {
2767
2755
  loggerWithoutContext().debug({
2768
2756
  msg: "using rivet engine driver",
2769
2757
  endpoint: runConfig.endpoint
2770
2758
  });
2771
- return createEngineDriver({
2772
- endpoint: runConfig.endpoint,
2773
- token: runConfig.token
2774
- });
2759
+ return createEngineDriver();
2775
2760
  }
2776
2761
  loggerWithoutContext().debug({ msg: "using default file system driver" });
2777
2762
  return createFileSystemOrMemoryDriver(true);
2778
2763
  }
2779
2764
 
2765
+ // src/engine-process/mod.ts
2766
+ import { spawn } from "child_process";
2767
+ import { createWriteStream } from "fs";
2768
+ import * as fs3 from "fs/promises";
2769
+ import * as path3 from "path";
2770
+ import { pipeline } from "stream/promises";
2771
+
2772
+ // src/engine-process/log.ts
2773
+ function logger6() {
2774
+ return getLogger("engine-process");
2775
+ }
2776
+
2777
+ // src/engine-process/mod.ts
2778
+ var ENGINE_PORT = 6420;
2779
+ var ENGINE_ENDPOINT = `http://localhost:${ENGINE_PORT}`;
2780
+ var ENGINE_BASE_URL = "https://releases.rivet.gg/engine";
2781
+ var ENGINE_BINARY_NAME = "rivet-engine";
2782
+ async function ensureEngineProcess(options) {
2783
+ logger6().debug({ msg: "ensuring engine process", version: options.version });
2784
+ const storageRoot = getStoragePath();
2785
+ const binDir = path3.join(storageRoot, "bin");
2786
+ const varDir = path3.join(storageRoot, "var");
2787
+ const logsDir = path3.join(varDir, "logs", "rivet-engine");
2788
+ await ensureDirectoryExists(binDir);
2789
+ await ensureDirectoryExists(varDir);
2790
+ await ensureDirectoryExists(logsDir);
2791
+ const executableName = process.platform === "win32" ? `${ENGINE_BINARY_NAME}-${options.version}.exe` : `${ENGINE_BINARY_NAME}-${options.version}`;
2792
+ const binaryPath = path3.join(binDir, executableName);
2793
+ await downloadEngineBinaryIfNeeded(binaryPath, options.version, varDir);
2794
+ if (await isEngineRunning()) {
2795
+ try {
2796
+ await waitForEngineHealth();
2797
+ logger6().debug({
2798
+ msg: "engine already running and healthy",
2799
+ version: options.version
2800
+ });
2801
+ return;
2802
+ } catch (error) {
2803
+ logger6().warn({
2804
+ msg: "existing engine process not healthy, cannot restart automatically",
2805
+ error
2806
+ });
2807
+ throw new Error(
2808
+ "Engine process exists but is not healthy. Please manually stop the process on port 6420 and retry."
2809
+ );
2810
+ }
2811
+ }
2812
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-").replace(/\./g, "-");
2813
+ const stdoutLogPath = path3.join(logsDir, `engine-${timestamp}-stdout.log`);
2814
+ const stderrLogPath = path3.join(logsDir, `engine-${timestamp}-stderr.log`);
2815
+ const stdoutStream = createWriteStream(stdoutLogPath, { flags: "a" });
2816
+ const stderrStream = createWriteStream(stderrLogPath, { flags: "a" });
2817
+ logger6().debug({
2818
+ msg: "creating engine log files",
2819
+ stdout: stdoutLogPath,
2820
+ stderr: stderrLogPath
2821
+ });
2822
+ const child = spawn(binaryPath, ["start"], {
2823
+ cwd: path3.dirname(binaryPath),
2824
+ stdio: ["inherit", "pipe", "pipe"],
2825
+ env: {
2826
+ ...process.env
2827
+ }
2828
+ });
2829
+ if (!child.pid) {
2830
+ throw new Error("failed to spawn rivet engine process");
2831
+ }
2832
+ if (child.stdout) {
2833
+ child.stdout.pipe(stdoutStream);
2834
+ }
2835
+ if (child.stderr) {
2836
+ child.stderr.pipe(stderrStream);
2837
+ }
2838
+ logger6().debug({
2839
+ msg: "spawned engine process",
2840
+ pid: child.pid,
2841
+ cwd: path3.dirname(binaryPath)
2842
+ });
2843
+ child.once("exit", (code, signal) => {
2844
+ logger6().warn({
2845
+ msg: "engine process exited",
2846
+ code,
2847
+ signal
2848
+ });
2849
+ stdoutStream.end();
2850
+ stderrStream.end();
2851
+ });
2852
+ child.once("error", (error) => {
2853
+ logger6().error({
2854
+ msg: "engine process failed",
2855
+ error
2856
+ });
2857
+ stdoutStream.end();
2858
+ stderrStream.end();
2859
+ });
2860
+ await waitForEngineHealth();
2861
+ logger6().info({
2862
+ msg: "engine process started",
2863
+ pid: child.pid,
2864
+ version: options.version,
2865
+ logs: {
2866
+ stdout: stdoutLogPath,
2867
+ stderr: stderrLogPath
2868
+ }
2869
+ });
2870
+ }
2871
+ async function downloadEngineBinaryIfNeeded(binaryPath, version, varDir) {
2872
+ const binaryExists = await fileExists(binaryPath);
2873
+ if (binaryExists) {
2874
+ logger6().debug({
2875
+ msg: "engine binary already cached",
2876
+ version,
2877
+ path: binaryPath
2878
+ });
2879
+ return;
2880
+ }
2881
+ const { targetTriplet, extension } = resolveTargetTriplet();
2882
+ const remoteFile = `${ENGINE_BINARY_NAME}-${targetTriplet}${extension}`;
2883
+ const downloadUrl = `${ENGINE_BASE_URL}/${version}/${remoteFile}`;
2884
+ logger6().info({
2885
+ msg: "downloading engine binary",
2886
+ url: downloadUrl,
2887
+ path: binaryPath,
2888
+ version
2889
+ });
2890
+ const response = await fetch(downloadUrl);
2891
+ if (!response.ok || !response.body) {
2892
+ throw new Error(
2893
+ `failed to download rivet engine binary from ${downloadUrl}: ${response.status} ${response.statusText}`
2894
+ );
2895
+ }
2896
+ const tempPath = `${binaryPath}.${process.pid}.tmp`;
2897
+ await pipeline(response.body, createWriteStream(tempPath));
2898
+ if (process.platform !== "win32") {
2899
+ await fs3.chmod(tempPath, 493);
2900
+ }
2901
+ await fs3.rename(tempPath, binaryPath);
2902
+ logger6().debug({
2903
+ msg: "engine binary download complete",
2904
+ version,
2905
+ path: binaryPath
2906
+ });
2907
+ logger6().info({
2908
+ msg: "engine binary downloaded",
2909
+ version,
2910
+ path: binaryPath
2911
+ });
2912
+ }
2913
+ function resolveTargetTriplet() {
2914
+ return resolveTargetTripletFor(process.platform, process.arch);
2915
+ }
2916
+ function resolveTargetTripletFor(platform, arch) {
2917
+ switch (platform) {
2918
+ case "darwin":
2919
+ if (arch === "arm64") {
2920
+ return { targetTriplet: "aarch64-apple-darwin", extension: "" };
2921
+ }
2922
+ if (arch === "x64") {
2923
+ return { targetTriplet: "x86_64-apple-darwin", extension: "" };
2924
+ }
2925
+ break;
2926
+ case "linux":
2927
+ if (arch === "x64") {
2928
+ return { targetTriplet: "x86_64-unknown-linux-musl", extension: "" };
2929
+ }
2930
+ break;
2931
+ case "win32":
2932
+ if (arch === "x64") {
2933
+ return { targetTriplet: "x86_64-pc-windows-gnu", extension: ".exe" };
2934
+ }
2935
+ break;
2936
+ }
2937
+ throw new Error(
2938
+ `unsupported platform for rivet engine binary: ${platform}/${arch}`
2939
+ );
2940
+ }
2941
+ async function isEngineRunning() {
2942
+ return await checkIfEngineAlreadyRunningOnPort(ENGINE_PORT);
2943
+ }
2944
+ async function checkIfEngineAlreadyRunningOnPort(port) {
2945
+ let response;
2946
+ try {
2947
+ response = await fetch(`http://localhost:${port}/health`);
2948
+ } catch (err) {
2949
+ return false;
2950
+ }
2951
+ if (response.ok) {
2952
+ const health = await response.json();
2953
+ if (health.runtime === "engine") {
2954
+ logger6().debug({
2955
+ msg: "rivet engine already running on port",
2956
+ port
2957
+ });
2958
+ return true;
2959
+ } else if (health.runtime === "rivetkit") {
2960
+ logger6().error({
2961
+ msg: "another rivetkit process is already running on port",
2962
+ port
2963
+ });
2964
+ throw new Error(
2965
+ "RivetKit process already running on port 6420, stop that process and restart this."
2966
+ );
2967
+ } else {
2968
+ throw new Error(
2969
+ "Unknown process running on port 6420, cannot identify what it is."
2970
+ );
2971
+ }
2972
+ }
2973
+ return false;
2974
+ }
2975
+ async function fileExists(filePath) {
2976
+ try {
2977
+ await fs3.access(filePath);
2978
+ return true;
2979
+ } catch {
2980
+ return false;
2981
+ }
2982
+ }
2983
+ var HEALTH_MAX_WAIT = 1e4;
2984
+ var HEALTH_INTERVAL = 100;
2985
+ async function waitForEngineHealth() {
2986
+ const maxRetries = Math.ceil(HEALTH_MAX_WAIT / HEALTH_INTERVAL);
2987
+ logger6().debug({ msg: "waiting for engine health check" });
2988
+ for (let i = 0; i < maxRetries; i++) {
2989
+ try {
2990
+ const response = await fetch(`${ENGINE_ENDPOINT}/health`);
2991
+ if (response.ok) {
2992
+ logger6().debug({ msg: "engine health check passed" });
2993
+ return;
2994
+ }
2995
+ } catch (error) {
2996
+ if (i === maxRetries - 1) {
2997
+ throw new Error(
2998
+ `engine health check failed after ${maxRetries} retries: ${error}`
2999
+ );
3000
+ }
3001
+ }
3002
+ if (i < maxRetries - 1) {
3003
+ logger6().trace({
3004
+ msg: "engine not ready, retrying",
3005
+ attempt: i + 1,
3006
+ maxRetries
3007
+ });
3008
+ await new Promise((resolve) => setTimeout(resolve, HEALTH_INTERVAL));
3009
+ }
3010
+ }
3011
+ throw new Error(`engine health check failed after ${maxRetries} retries`);
3012
+ }
3013
+
2780
3014
  // src/manager/router.ts
2781
3015
  import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
2782
3016
  import * as cbor4 from "cbor-x";
@@ -2784,66 +3018,79 @@ import {
2784
3018
  Hono as Hono3
2785
3019
  } from "hono";
2786
3020
  import { cors as corsMiddleware } from "hono/cors";
3021
+ import { createMiddleware } from "hono/factory";
2787
3022
  import invariant6 from "invariant";
2788
3023
  import { z as z5 } from "zod";
2789
3024
 
2790
3025
  // src/manager-api/actors.ts
2791
- import { z as z4 } from "zod";
3026
+ import { z as z3 } from "zod";
2792
3027
 
2793
3028
  // src/manager-api/common.ts
2794
- import { z as z3 } from "zod";
2795
- var RivetIdSchema = z3.string();
3029
+ import { z as z2 } from "zod";
3030
+ var RivetIdSchema = z2.string();
2796
3031
 
2797
3032
  // src/manager-api/actors.ts
2798
- var ActorSchema = z4.object({
3033
+ var ActorSchema = z3.object({
2799
3034
  actor_id: RivetIdSchema,
2800
- name: z4.string(),
2801
- key: z4.string(),
3035
+ name: z3.string(),
3036
+ key: z3.string(),
2802
3037
  namespace_id: RivetIdSchema,
2803
- runner_name_selector: z4.string(),
2804
- create_ts: z4.number(),
2805
- connectable_ts: z4.number().nullable().optional(),
2806
- destroy_ts: z4.number().nullable().optional(),
2807
- sleep_ts: z4.number().nullable().optional(),
2808
- start_ts: z4.number().nullable().optional()
3038
+ runner_name_selector: z3.string(),
3039
+ create_ts: z3.number(),
3040
+ connectable_ts: z3.number().nullable().optional(),
3041
+ destroy_ts: z3.number().nullable().optional(),
3042
+ sleep_ts: z3.number().nullable().optional(),
3043
+ start_ts: z3.number().nullable().optional()
2809
3044
  });
2810
- var ActorsListResponseSchema = z4.object({
2811
- actors: z4.array(ActorSchema)
3045
+ var ActorsListResponseSchema = z3.object({
3046
+ actors: z3.array(ActorSchema)
2812
3047
  });
2813
- var ActorsCreateRequestSchema = z4.object({
2814
- name: z4.string(),
2815
- runner_name_selector: z4.string(),
2816
- crash_policy: z4.string(),
2817
- key: z4.string().nullable().optional(),
2818
- input: z4.string().nullable().optional()
3048
+ var ActorsCreateRequestSchema = z3.object({
3049
+ name: z3.string(),
3050
+ runner_name_selector: z3.string(),
3051
+ crash_policy: z3.string(),
3052
+ key: z3.string().nullable().optional(),
3053
+ input: z3.string().nullable().optional()
2819
3054
  });
2820
- var ActorsCreateResponseSchema = z4.object({
3055
+ var ActorsCreateResponseSchema = z3.object({
2821
3056
  actor: ActorSchema
2822
3057
  });
2823
- var ActorsGetOrCreateRequestSchema = z4.object({
2824
- name: z4.string(),
2825
- key: z4.string(),
2826
- runner_name_selector: z4.string(),
2827
- crash_policy: z4.string(),
2828
- input: z4.string().nullable().optional()
3058
+ var ActorsGetOrCreateRequestSchema = z3.object({
3059
+ name: z3.string(),
3060
+ key: z3.string(),
3061
+ runner_name_selector: z3.string(),
3062
+ crash_policy: z3.string(),
3063
+ input: z3.string().nullable().optional()
2829
3064
  });
2830
- var ActorsGetOrCreateResponseSchema = z4.object({
3065
+ var ActorsGetOrCreateResponseSchema = z3.object({
2831
3066
  actor: ActorSchema,
2832
- created: z4.boolean()
3067
+ created: z3.boolean()
2833
3068
  });
2834
- var ActorsDeleteResponseSchema = z4.object({});
3069
+ var ActorsDeleteResponseSchema = z3.object({});
2835
3070
 
2836
3071
  // src/manager/gateway.ts
2837
3072
  async function actorGateway(runConfig, managerDriver, c, next) {
2838
3073
  if (c.req.path.startsWith("/.test/")) {
2839
3074
  return next();
2840
3075
  }
3076
+ let strippedPath = c.req.path;
3077
+ if (runConfig.basePath && strippedPath.startsWith(runConfig.basePath)) {
3078
+ strippedPath = strippedPath.slice(runConfig.basePath.length);
3079
+ if (!strippedPath.startsWith("/")) {
3080
+ strippedPath = "/" + strippedPath;
3081
+ }
3082
+ }
2841
3083
  if (c.req.header("upgrade") === "websocket") {
2842
- return await handleWebSocketGateway(runConfig, managerDriver, c);
3084
+ return await handleWebSocketGateway(
3085
+ runConfig,
3086
+ managerDriver,
3087
+ c,
3088
+ strippedPath
3089
+ );
2843
3090
  }
2844
- return await handleHttpGateway(managerDriver, c, next);
3091
+ return await handleHttpGateway(managerDriver, c, next, strippedPath);
2845
3092
  }
2846
- async function handleWebSocketGateway(runConfig, managerDriver, c) {
3093
+ async function handleWebSocketGateway(runConfig, managerDriver, c, strippedPath) {
2847
3094
  var _a;
2848
3095
  const upgradeWebSocket = (_a = runConfig.getUpgradeWebSocket) == null ? void 0 : _a.call(runConfig);
2849
3096
  if (!upgradeWebSocket) {
@@ -2885,12 +3132,12 @@ async function handleWebSocketGateway(runConfig, managerDriver, c) {
2885
3132
  logger().debug({
2886
3133
  msg: "proxying websocket to actor",
2887
3134
  actorId,
2888
- path: c.req.path,
3135
+ path: strippedPath,
2889
3136
  encoding: encodingRaw
2890
3137
  });
2891
3138
  const encoding = encodingRaw || "json";
2892
3139
  const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : void 0;
2893
- const pathWithQuery = c.req.url.includes("?") ? c.req.path + c.req.url.substring(c.req.url.indexOf("?")) : c.req.path;
3140
+ const pathWithQuery = c.req.url.includes("?") ? strippedPath + c.req.url.substring(c.req.url.indexOf("?")) : strippedPath;
2894
3141
  return await managerDriver.proxyWebSocket(
2895
3142
  c,
2896
3143
  pathWithQuery,
@@ -2902,7 +3149,7 @@ async function handleWebSocketGateway(runConfig, managerDriver, c) {
2902
3149
  connTokenRaw
2903
3150
  );
2904
3151
  }
2905
- async function handleHttpGateway(managerDriver, c, next) {
3152
+ async function handleHttpGateway(managerDriver, c, next, strippedPath) {
2906
3153
  const target = c.req.header(HEADER_RIVET_TARGET);
2907
3154
  const actorId = c.req.header(HEADER_RIVET_ACTOR);
2908
3155
  if (target !== "actor") {
@@ -2914,19 +3161,20 @@ async function handleHttpGateway(managerDriver, c, next) {
2914
3161
  logger().debug({
2915
3162
  msg: "proxying request to actor",
2916
3163
  actorId,
2917
- path: c.req.path,
3164
+ path: strippedPath,
2918
3165
  method: c.req.method
2919
3166
  });
2920
3167
  const proxyHeaders = new Headers(c.req.raw.headers);
2921
3168
  proxyHeaders.delete(HEADER_RIVET_TARGET);
2922
3169
  proxyHeaders.delete(HEADER_RIVET_ACTOR);
2923
3170
  const url = new URL(c.req.url);
2924
- const proxyUrl = new URL(`http://actor${url.pathname}${url.search}`);
3171
+ const proxyUrl = new URL(`http://actor${strippedPath}${url.search}`);
2925
3172
  const proxyRequest = new Request(proxyUrl, {
2926
3173
  method: c.req.raw.method,
2927
3174
  headers: proxyHeaders,
2928
3175
  body: c.req.raw.body,
2929
- signal: c.req.raw.signal
3176
+ signal: c.req.raw.signal,
3177
+ duplex: "half"
2930
3178
  });
2931
3179
  return await managerDriver.proxyRequest(c, proxyRequest, actorId);
2932
3180
  }
@@ -3102,6 +3350,22 @@ async function createTestWebSocketProxy(clientWsPromise) {
3102
3350
  };
3103
3351
  }
3104
3352
 
3353
+ // src/manager/router-schema.ts
3354
+ import { z as z4 } from "zod";
3355
+ var ServerlessStartHeadersSchema = z4.object({
3356
+ endpoint: z4.string({ required_error: "x-rivet-endpoint header is required" }),
3357
+ token: z4.string({ invalid_type_error: "x-rivet-token header must be a string" }).optional(),
3358
+ totalSlots: z4.coerce.number({
3359
+ invalid_type_error: "x-rivet-total-slots header must be a number"
3360
+ }).int("x-rivet-total-slots header must be an integer").gte(1, "x-rivet-total-slots header must be positive"),
3361
+ runnerName: z4.string({
3362
+ required_error: "x-rivet-runner-name header is required"
3363
+ }),
3364
+ namespace: z4.string({
3365
+ required_error: "x-rivet-namespace-id header is required"
3366
+ })
3367
+ });
3368
+
3105
3369
  // src/manager/router.ts
3106
3370
  function buildOpenApiResponses(schema) {
3107
3371
  return {
@@ -3121,21 +3385,42 @@ function buildOpenApiResponses(schema) {
3121
3385
  }
3122
3386
  };
3123
3387
  }
3124
- function createManagerRouter(registryConfig, runConfig, managerDriver, serverlessActorDriverBuilder) {
3388
+ function createManagerRouter(registryConfig, runConfig, managerDriver, driverConfig, client) {
3125
3389
  const router = new OpenAPIHono({ strict: false }).basePath(
3126
3390
  runConfig.basePath
3127
3391
  );
3128
3392
  router.use("*", loggerMiddleware(logger()));
3129
- if (serverlessActorDriverBuilder) {
3130
- addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router);
3131
- } else {
3393
+ router.use(
3394
+ "*",
3395
+ createMiddleware(async (c, next) => {
3396
+ const upgrade = c.req.header("upgrade");
3397
+ const isWebSocket = (upgrade == null ? void 0 : upgrade.toLowerCase()) === "websocket";
3398
+ const isGet = c.req.method === "GET";
3399
+ if (isGet && isWebSocket) {
3400
+ c.header("Sec-WebSocket-Protocol", "rivet");
3401
+ }
3402
+ await next();
3403
+ })
3404
+ );
3405
+ if (runConfig.runnerKind === "serverless") {
3406
+ addServerlessRoutes(
3407
+ driverConfig,
3408
+ registryConfig,
3409
+ runConfig,
3410
+ managerDriver,
3411
+ client,
3412
+ router
3413
+ );
3414
+ } else if (runConfig.runnerKind === "normal") {
3132
3415
  addManagerRoutes(registryConfig, runConfig, managerDriver, router);
3416
+ } else {
3417
+ assertUnreachable(runConfig.runnerKind);
3133
3418
  }
3134
3419
  router.notFound(handleRouteNotFound);
3135
3420
  router.onError(handleRouteError);
3136
3421
  return { router, openapi: router };
3137
3422
  }
3138
- function addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router) {
3423
+ function addServerlessRoutes(driverConfig, registryConfig, runConfig, managerDriver, client, router) {
3139
3424
  if (runConfig.cors) router.use("*", corsMiddleware(runConfig.cors));
3140
3425
  router.get("/", (c) => {
3141
3426
  return c.text(
@@ -3143,12 +3428,39 @@ function addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router) {
3143
3428
  );
3144
3429
  });
3145
3430
  router.get("/start", async (c) => {
3146
- const token = c.req.header("x-rivet-token");
3147
- let totalSlots = parseInt(
3148
- c.req.header("x-rivetkit-total-slots")
3431
+ var _a;
3432
+ const parseResult = ServerlessStartHeadersSchema.safeParse({
3433
+ endpoint: c.req.header("x-rivet-endpoint"),
3434
+ token: c.req.header("x-rivet-token") ?? void 0,
3435
+ totalSlots: c.req.header("x-rivet-total-slots"),
3436
+ runnerName: c.req.header("x-rivet-runner-name"),
3437
+ namespace: c.req.header("x-rivet-namespace-id")
3438
+ });
3439
+ if (!parseResult.success) {
3440
+ throw new InvalidRequest(
3441
+ ((_a = parseResult.error.issues[0]) == null ? void 0 : _a.message) ?? "invalid serverless start headers"
3442
+ );
3443
+ }
3444
+ const { endpoint, token, totalSlots, runnerName, namespace } = parseResult.data;
3445
+ logger().debug({
3446
+ msg: "received serverless runner start request",
3447
+ endpoint,
3448
+ totalSlots,
3449
+ runnerName,
3450
+ namespace
3451
+ });
3452
+ const newRunConfig = Object.assign({}, runConfig);
3453
+ newRunConfig.endpoint = endpoint;
3454
+ newRunConfig.token = token;
3455
+ newRunConfig.totalSlots = totalSlots;
3456
+ newRunConfig.runnerName = runnerName;
3457
+ newRunConfig.namespace = namespace;
3458
+ const actorDriver = driverConfig.actor(
3459
+ registryConfig,
3460
+ newRunConfig,
3461
+ managerDriver,
3462
+ client
3149
3463
  );
3150
- if (isNaN(totalSlots)) totalSlots = void 0;
3151
- const actorDriver = serverlessActorDriverBuilder(token, totalSlots);
3152
3464
  invariant6(
3153
3465
  actorDriver.serverlessHandleStart,
3154
3466
  "missing serverlessHandleStart on ActorDriver"
@@ -3156,7 +3468,11 @@ function addServerlessRoutes(runConfig, serverlessActorDriverBuilder, router) {
3156
3468
  return await actorDriver.serverlessHandleStart(c);
3157
3469
  });
3158
3470
  router.get("/health", (c) => {
3159
- return c.text("ok");
3471
+ return c.json({
3472
+ status: "ok",
3473
+ runtime: "rivetkit",
3474
+ version: VERSION
3475
+ });
3160
3476
  });
3161
3477
  }
3162
3478
  function addManagerRoutes(registryConfig, runConfig, managerDriver, router) {
@@ -3344,7 +3660,7 @@ function addManagerRoutes(registryConfig, runConfig, managerDriver, router) {
3344
3660
  let actorId = "";
3345
3661
  let encoding = "bare";
3346
3662
  let transport = "websocket";
3347
- let path3 = "";
3663
+ let path4 = "";
3348
3664
  let params;
3349
3665
  let connId;
3350
3666
  let connToken;
@@ -3360,7 +3676,7 @@ function addManagerRoutes(registryConfig, runConfig, managerDriver, router) {
3360
3676
  WS_PROTOCOL_TRANSPORT.length
3361
3677
  );
3362
3678
  } else if (protocol.startsWith(WS_PROTOCOL_PATH)) {
3363
- path3 = decodeURIComponent(
3679
+ path4 = decodeURIComponent(
3364
3680
  protocol.substring(WS_PROTOCOL_PATH.length)
3365
3681
  );
3366
3682
  } else if (protocol.startsWith(WS_PROTOCOL_CONN_PARAMS)) {
@@ -3380,10 +3696,10 @@ function addManagerRoutes(registryConfig, runConfig, managerDriver, router) {
3380
3696
  params,
3381
3697
  encodingKind: encoding,
3382
3698
  transport,
3383
- path: path3
3699
+ path: path4
3384
3700
  });
3385
3701
  const clientWsPromise = managerDriver.openWebSocket(
3386
- path3,
3702
+ path4,
3387
3703
  actorId,
3388
3704
  encoding,
3389
3705
  params,
@@ -3472,7 +3788,12 @@ function addManagerRoutes(registryConfig, runConfig, managerDriver, router) {
3472
3788
  });
3473
3789
  }
3474
3790
  router.get("/health", (c) => {
3475
- return c.text("ok");
3791
+ return c.json({
3792
+ status: "ok",
3793
+ rivetkit: {
3794
+ version: VERSION
3795
+ }
3796
+ });
3476
3797
  });
3477
3798
  (_a = managerDriver.modifyManagerRouter) == null ? void 0 : _a.call(
3478
3799
  managerDriver,
@@ -3517,13 +3838,13 @@ var RegistryConfigSchema = z6.object({
3517
3838
  });
3518
3839
 
3519
3840
  // src/registry/log.ts
3520
- function logger6() {
3841
+ function logger7() {
3521
3842
  return getLogger("registry");
3522
3843
  }
3523
3844
 
3524
3845
  // src/registry/serve.ts
3525
3846
  import { Hono as Hono4 } from "hono";
3526
- async function crossPlatformServe(rivetKitRouter, userRouter) {
3847
+ async function crossPlatformServe(runConfig, rivetKitRouter, userRouter) {
3527
3848
  const app = userRouter ?? new Hono4();
3528
3849
  let serve;
3529
3850
  try {
@@ -3533,7 +3854,7 @@ async function crossPlatformServe(rivetKitRouter, userRouter) {
3533
3854
  );
3534
3855
  serve = dep.serve;
3535
3856
  } catch (err) {
3536
- logger6().error(
3857
+ logger7().error(
3537
3858
  "failed to import @hono/node-server. please run 'npm install @hono/node-server @hono/node-ws'"
3538
3859
  );
3539
3860
  process.exit(1);
@@ -3547,7 +3868,7 @@ async function crossPlatformServe(rivetKitRouter, userRouter) {
3547
3868
  );
3548
3869
  createNodeWebSocket = dep.createNodeWebSocket;
3549
3870
  } catch (err) {
3550
- logger6().error(
3871
+ logger7().error(
3551
3872
  "failed to import @hono/node-ws. please run 'npm install @hono/node-server @hono/node-ws'"
3552
3873
  );
3553
3874
  process.exit(1);
@@ -3555,10 +3876,10 @@ async function crossPlatformServe(rivetKitRouter, userRouter) {
3555
3876
  const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({
3556
3877
  app
3557
3878
  });
3558
- const port = 6420;
3879
+ const port = runConfig.defaultServerPort;
3559
3880
  const server = serve(
3560
3881
  { fetch: app.fetch, port },
3561
- () => logger6().info({ msg: "server listening", port })
3882
+ () => logger7().info({ msg: "server listening", port })
3562
3883
  );
3563
3884
  injectWebSocket(server);
3564
3885
  return { upgradeWebSocket };
@@ -3578,7 +3899,33 @@ var Registry = class {
3578
3899
  */
3579
3900
  start(inputConfig) {
3580
3901
  var _a, _b, _c;
3581
- const config2 = RunConfigSchema.parse(inputConfig);
3902
+ const config2 = RunnerConfigSchema.parse(inputConfig);
3903
+ if (config2.autoConfigureServerless && config2.runnerKind !== "serverless") {
3904
+ throw new Error(
3905
+ "autoConfigureServerless can only be configured when runnerKind is 'serverless'"
3906
+ );
3907
+ }
3908
+ const readyPromises = [];
3909
+ if (config2.runEngine) {
3910
+ logger7().debug({
3911
+ msg: "run engine requested",
3912
+ version: config2.runEngineVersion
3913
+ });
3914
+ invariant7(
3915
+ config2.endpoint === void 0,
3916
+ "cannot specify 'endpoint' with 'runEngine'"
3917
+ );
3918
+ config2.endpoint = ENGINE_ENDPOINT;
3919
+ config2.disableActorDriver = true;
3920
+ const engineProcessPromise = ensureEngineProcess({
3921
+ version: config2.runEngineVersion
3922
+ });
3923
+ readyPromises.push(engineProcessPromise);
3924
+ }
3925
+ if (config2.runnerKind === "serverless") {
3926
+ config2.defaultServerPort = 8080;
3927
+ config2.overrideServerAddress = config2.endpoint;
3928
+ }
3582
3929
  if ((_a = config2.logging) == null ? void 0 : _a.baseLogger) {
3583
3930
  configureBaseLogger(config2.logging.baseLogger);
3584
3931
  } else {
@@ -3587,11 +3934,13 @@ var Registry = class {
3587
3934
  const driver = chooseDefaultDriver(config2);
3588
3935
  if (driver.name === "engine") {
3589
3936
  config2.inspector.enabled = { manager: false, actor: true };
3590
- config2.disableServer = true;
3937
+ if (config2.runnerKind !== "serverless") {
3938
+ config2.disableDefaultServer = true;
3939
+ }
3591
3940
  }
3592
3941
  if (driver.name === "cloudflare-workers") {
3593
3942
  config2.inspector.enabled = { manager: false, actor: true };
3594
- config2.disableServer = true;
3943
+ config2.disableDefaultServer = true;
3595
3944
  config2.disableActorDriver = true;
3596
3945
  config2.noWelcome = true;
3597
3946
  }
@@ -3603,20 +3952,28 @@ var Registry = class {
3603
3952
  configureInspectorAccessToken(config2, managerDriver);
3604
3953
  const client = createClientWithDriver(managerDriver, config2);
3605
3954
  const driverLog = ((_c = managerDriver.extraStartupLog) == null ? void 0 : _c.call(managerDriver)) ?? {};
3606
- logger6().info({
3955
+ logger7().info({
3607
3956
  msg: "rivetkit ready",
3608
3957
  driver: driver.name,
3609
3958
  definitions: Object.keys(this.#config.use).length,
3610
3959
  ...driverLog
3611
3960
  });
3612
3961
  if (isInspectorEnabled(config2, "manager") && managerDriver.inspector) {
3613
- logger6().info({ msg: "inspector ready", url: getInspectorUrl(config2) });
3962
+ logger7().info({ msg: "inspector ready", url: getInspectorUrl(config2) });
3614
3963
  }
3615
3964
  if (!config2.noWelcome) {
3616
3965
  const displayInfo = managerDriver.displayInformation();
3617
3966
  console.log();
3618
3967
  console.log(` RivetKit ${package_default.version} (${displayInfo.name})`);
3619
- console.log(` - Endpoint: http://127.0.0.1:6420`);
3968
+ if (!config2.disableDefaultServer) {
3969
+ console.log(` - Endpoint: ${config2.endpoint}`);
3970
+ } else if (config2.overrideServerAddress) {
3971
+ console.log(` - Endpoint: ${config2.overrideServerAddress}`);
3972
+ }
3973
+ if (config2.runEngine) {
3974
+ const padding = " ".repeat(Math.max(0, 13 - "Engine".length));
3975
+ console.log(` - Engine:${padding}v${config2.runEngineVersion}`);
3976
+ }
3620
3977
  for (const [k, v] of Object.entries(displayInfo.properties)) {
3621
3978
  const padding = " ".repeat(Math.max(0, 13 - k.length));
3622
3979
  console.log(` - ${k}:${padding}${v}`);
@@ -3627,22 +3984,25 @@ var Registry = class {
3627
3984
  console.log();
3628
3985
  }
3629
3986
  if (!config2.disableActorDriver) {
3630
- const _actorDriver = driver.actor(
3631
- this.#config,
3632
- config2,
3633
- managerDriver,
3634
- client
3635
- );
3987
+ Promise.all(readyPromises).then(async () => {
3988
+ driver.actor(this.#config, config2, managerDriver, client);
3989
+ });
3990
+ }
3991
+ if (config2.runnerKind === "serverless" && config2.autoConfigureServerless) {
3992
+ Promise.all(readyPromises).then(async () => {
3993
+ await configureServerlessRunner(config2);
3994
+ });
3636
3995
  }
3637
3996
  const { router: hono } = createManagerRouter(
3638
3997
  this.#config,
3639
3998
  config2,
3640
3999
  managerDriver,
3641
- void 0
4000
+ driver,
4001
+ client
3642
4002
  );
3643
- if (!config2.disableServer) {
4003
+ if (!config2.disableDefaultServer) {
3644
4004
  (async () => {
3645
- const out = await crossPlatformServe(hono, void 0);
4005
+ const out = await crossPlatformServe(config2, hono, void 0);
3646
4006
  upgradeWebSocket = out.upgradeWebSocket;
3647
4007
  })();
3648
4008
  }
@@ -3651,83 +4011,63 @@ var Registry = class {
3651
4011
  fetch: hono.fetch.bind(hono)
3652
4012
  };
3653
4013
  }
3654
- startServerless(inputConfig) {
3655
- var _a, _b, _c, _d, _e;
3656
- const config2 = RunConfigSchema.parse(inputConfig);
3657
- if ((_a = config2.logging) == null ? void 0 : _a.baseLogger) {
3658
- configureBaseLogger(config2.logging.baseLogger);
3659
- } else {
3660
- configureDefaultLogger((_b = config2.logging) == null ? void 0 : _b.level);
3661
- }
3662
- const driver = chooseDefaultDriver(config2);
3663
- if (driver.name === "engine") {
3664
- config2.inspector.enabled = false;
3665
- config2.disableServer = true;
3666
- config2.disableActorDriver = true;
3667
- }
3668
- if (driver.name === "cloudflare-workers") {
3669
- config2.inspector.enabled = false;
3670
- config2.disableServer = true;
3671
- config2.disableActorDriver = true;
3672
- config2.noWelcome = true;
3673
- }
3674
- let upgradeWebSocket;
3675
- if (!config2.getUpgradeWebSocket) {
3676
- config2.getUpgradeWebSocket = () => upgradeWebSocket;
3677
- }
3678
- const managerDriver = driver.manager(this.#config, config2);
3679
- const client = createClientWithDriver(managerDriver, config2);
3680
- const driverLog = ((_c = managerDriver.extraStartupLog) == null ? void 0 : _c.call(managerDriver)) ?? {};
3681
- logger6().info({
3682
- msg: "rivetkit ready",
3683
- driver: driver.name,
3684
- definitions: Object.keys(this.#config.use).length,
3685
- ...driverLog
3686
- });
3687
- if (((_d = config2.inspector) == null ? void 0 : _d.enabled) && managerDriver.inspector) {
3688
- logger6().info({ msg: "inspector ready", url: getInspectorUrl(config2) });
3689
- }
3690
- if (!config2.noWelcome) {
3691
- const displayInfo = managerDriver.displayInformation();
3692
- console.log();
3693
- console.log(` RivetKit ${package_default.version} (${displayInfo.name})`);
3694
- console.log(` - Endpoint: http://127.0.0.1:6420`);
3695
- for (const [k, v] of Object.entries(displayInfo.properties)) {
3696
- const padding = " ".repeat(Math.max(0, 13 - k.length));
3697
- console.log(` - ${k}:${padding}${v}`);
3698
- }
3699
- if (((_e = config2.inspector) == null ? void 0 : _e.enabled) && managerDriver.inspector) {
3700
- console.log(` - Inspector: ${getInspectorUrl(config2)}`);
4014
+ };
4015
+ async function configureServerlessRunner(config2) {
4016
+ try {
4017
+ if (!config2.runnerName) {
4018
+ throw new Error("runnerName is required for serverless configuration");
4019
+ }
4020
+ if (!config2.namespace) {
4021
+ throw new Error("namespace is required for serverless configuration");
4022
+ }
4023
+ if (!config2.endpoint) {
4024
+ throw new Error("endpoint is required for serverless configuration");
4025
+ }
4026
+ const customConfig = typeof config2.autoConfigureServerless === "object" ? config2.autoConfigureServerless : {};
4027
+ const requestBody = {
4028
+ serverless: {
4029
+ url: customConfig.url || `http://localhost:${config2.defaultServerPort}/start`,
4030
+ headers: customConfig.headers || {},
4031
+ max_runners: customConfig.maxRunners ?? 100,
4032
+ min_runners: customConfig.minRunners ?? 0,
4033
+ request_lifespan: customConfig.requestLifespan ?? 15 * 60,
4034
+ runners_margin: customConfig.runnersMargin ?? 0,
4035
+ slots_per_runner: customConfig.slotsPerRunner ?? config2.totalSlots ?? 1e3
3701
4036
  }
3702
- console.log();
3703
- }
3704
- let serverlessActorDriverBuilder = (token, totalSlots) => {
3705
- if (token) config2.token = token;
3706
- if (totalSlots) config2.totalSlots = totalSlots;
3707
- return driver.actor(this.#config, config2, managerDriver, client);
3708
4037
  };
3709
- if (!config2.disableActorDriver) {
3710
- const _actorDriver = serverlessActorDriverBuilder();
3711
- serverlessActorDriverBuilder = void 0;
3712
- }
3713
- const { router: hono } = createManagerRouter(
3714
- this.#config,
3715
- config2,
3716
- managerDriver,
3717
- serverlessActorDriverBuilder
3718
- );
3719
- if (!config2.disableServer) {
3720
- (async () => {
3721
- const out = await crossPlatformServe(hono, void 0);
3722
- upgradeWebSocket = out.upgradeWebSocket;
3723
- })();
4038
+ const configUrl = `${config2.endpoint}/runner-configs/${config2.runnerName}?namespace=${config2.namespace}`;
4039
+ logger7().debug({
4040
+ msg: "configuring serverless runner",
4041
+ url: configUrl,
4042
+ config: requestBody.serverless
4043
+ });
4044
+ const response = await fetch(configUrl, {
4045
+ method: "PUT",
4046
+ headers: {
4047
+ "Content-Type": "application/json",
4048
+ ...config2.token ? { Authorization: `Bearer ${config2.token}` } : {}
4049
+ },
4050
+ body: JSON.stringify(requestBody)
4051
+ });
4052
+ if (!response.ok) {
4053
+ const errorText = await response.text();
4054
+ throw new Error(
4055
+ `failed to configure serverless runner: ${response.status} ${response.statusText} - ${errorText}`
4056
+ );
3724
4057
  }
3725
- return {
3726
- client,
3727
- fetch: hono.fetch.bind(hono)
3728
- };
4058
+ logger7().info({
4059
+ msg: "serverless runner configured successfully",
4060
+ runnerName: config2.runnerName,
4061
+ namespace: config2.namespace
4062
+ });
4063
+ } catch (error) {
4064
+ logger7().error({
4065
+ msg: "failed to configure serverless runner",
4066
+ error
4067
+ });
4068
+ throw error;
3729
4069
  }
3730
- };
4070
+ }
3731
4071
  function setup(input) {
3732
4072
  const config2 = RegistryConfigSchema.parse(input);
3733
4073
  return new Registry(config2);
@@ -3749,4 +4089,4 @@ export {
3749
4089
  setup
3750
4090
  };
3751
4091
  //! These configs configs hold anything that's not platform-specific about running actors.
3752
- //# sourceMappingURL=chunk-FZP2IBIX.js.map
4092
+ //# sourceMappingURL=chunk-VJRXZPTT.js.map