rivetkit 2.0.39 → 2.0.41
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.
- package/dist/schemas/actor-persist/v1.js +167 -0
- package/dist/schemas/actor-persist/v2.js +200 -0
- package/dist/schemas/actor-persist/v3.js +200 -0
- package/dist/schemas/client-protocol/v1.js +301 -0
- package/dist/schemas/client-protocol/v2.js +299 -0
- package/dist/schemas/file-system-driver/v1.js +76 -0
- package/dist/schemas/file-system-driver/v2.js +103 -0
- package/dist/schemas/file-system-driver/v3.js +122 -0
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/{chunk-OJZRCEIA.js → chunk-4J5EFV3E.js} +5 -5
- package/dist/tsup/{chunk-7E3RWMR6.cjs → chunk-4UHJ3ADW.cjs} +173 -107
- package/dist/tsup/chunk-4UHJ3ADW.cjs.map +1 -0
- package/dist/tsup/{chunk-BQ36VTSB.js → chunk-7KIR3QLO.js} +86 -20
- package/dist/tsup/{chunk-BQ36VTSB.js.map → chunk-7KIR3QLO.js.map} +1 -1
- package/dist/tsup/{chunk-KMYFL3OL.cjs → chunk-B5UXC4QV.cjs} +75 -64
- package/dist/tsup/chunk-B5UXC4QV.cjs.map +1 -0
- package/dist/tsup/{chunk-C64FV764.cjs → chunk-DSNSFYDL.cjs} +3 -3
- package/dist/tsup/chunk-DSNSFYDL.cjs.map +1 -0
- package/dist/tsup/chunk-GBENOENJ.cjs.map +1 -1
- package/dist/tsup/{chunk-DY4H3ASE.cjs → chunk-GTQKDCM4.cjs} +46 -46
- package/dist/tsup/chunk-GTQKDCM4.cjs.map +1 -0
- package/dist/tsup/chunk-KDFWJKMJ.cjs.map +1 -1
- package/dist/tsup/{chunk-CDK6DRO2.js → chunk-LMG4QMDO.js} +2 -2
- package/dist/tsup/{chunk-CDK6DRO2.js.map → chunk-LMG4QMDO.js.map} +1 -1
- package/dist/tsup/{chunk-T7IPDBWH.js → chunk-NRP2OHSW.js} +4 -4
- package/dist/tsup/{chunk-PVKUXMOA.js → chunk-OXN6EZUB.js} +19 -8
- package/dist/tsup/chunk-OXN6EZUB.js.map +1 -0
- package/dist/tsup/{chunk-MZPYVTVG.cjs → chunk-QDVKDX7G.cjs} +9 -9
- package/dist/tsup/chunk-QDVKDX7G.cjs.map +1 -0
- package/dist/tsup/{chunk-X72X7I7T.cjs → chunk-S6F7EKC7.cjs} +2 -2
- package/dist/tsup/chunk-S6F7EKC7.cjs.map +1 -0
- package/dist/tsup/chunk-SNAUKDDK.cjs.map +1 -1
- package/dist/tsup/{chunk-XU74APB4.js → chunk-UGOCTUBG.js} +6 -5
- package/dist/tsup/chunk-UGOCTUBG.js.map +1 -0
- package/dist/tsup/{chunk-UAX5E3EU.cjs → chunk-WYZLRPQM.cjs} +250 -249
- package/dist/tsup/chunk-WYZLRPQM.cjs.map +1 -0
- package/dist/tsup/{chunk-PHCD25XO.js → chunk-Y7ZDTLD2.js} +2 -2
- package/dist/tsup/client/mod.cjs +5 -5
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +2 -2
- package/dist/tsup/client/mod.d.ts +2 -2
- package/dist/tsup/client/mod.js +4 -4
- package/dist/tsup/common/log.cjs +2 -2
- package/dist/tsup/common/log.cjs.map +1 -1
- package/dist/tsup/common/log.d.cts +2 -2
- package/dist/tsup/common/log.d.ts +2 -2
- package/dist/tsup/common/log.js +1 -1
- package/dist/tsup/common/websocket.cjs +3 -3
- package/dist/tsup/common/websocket.cjs.map +1 -1
- package/dist/tsup/common/websocket.js +2 -2
- package/dist/tsup/{config-BuBlMs6C.d.cts → config-COyis_uH.d.cts} +22 -10
- package/dist/tsup/{config-CBwo4ooA.d.ts → config-D43N-CFi.d.ts} +22 -10
- package/dist/tsup/{driver-CPXmh8f8.d.cts → driver-Bt7B-qMd.d.cts} +1 -1
- package/dist/tsup/{driver-DxWa6HUO.d.ts → driver-KyM2v645.d.ts} +1 -1
- package/dist/tsup/driver-helpers/mod.cjs +3 -3
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +2 -2
- package/dist/tsup/driver-helpers/mod.d.ts +2 -2
- package/dist/tsup/driver-helpers/mod.js +2 -2
- package/dist/tsup/driver-test-suite/mod.cjs +62 -34
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +2 -2
- package/dist/tsup/driver-test-suite/mod.d.ts +2 -2
- package/dist/tsup/driver-test-suite/mod.js +35 -7
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/mod.cjs +7 -7
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +4 -4
- package/dist/tsup/mod.d.ts +4 -4
- package/dist/tsup/mod.js +6 -6
- package/dist/tsup/test/mod.cjs +7 -7
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +1 -1
- package/dist/tsup/test/mod.d.ts +1 -1
- package/dist/tsup/test/mod.js +6 -6
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.js +1 -1
- package/package.json +2 -2
- package/src/actor/instance/schedule-manager.ts +2 -1
- package/src/actor/router-websocket-endpoints.test.ts +54 -0
- package/src/actor/router-websocket-endpoints.ts +9 -4
- package/src/common/router.ts +2 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +40 -0
- package/src/engine-process/mod.ts +69 -7
- package/src/registry/config/index.ts +7 -0
- package/src/registry/config/serverless.ts +2 -0
- package/src/registry/serve.ts +9 -5
- package/src/remote-manager-driver/api-endpoints.ts +2 -0
- package/src/serverless/configure.ts +3 -0
- package/dist/tsup/chunk-7E3RWMR6.cjs.map +0 -1
- package/dist/tsup/chunk-C64FV764.cjs.map +0 -1
- package/dist/tsup/chunk-DY4H3ASE.cjs.map +0 -1
- package/dist/tsup/chunk-KMYFL3OL.cjs.map +0 -1
- package/dist/tsup/chunk-MZPYVTVG.cjs.map +0 -1
- package/dist/tsup/chunk-PVKUXMOA.js.map +0 -1
- package/dist/tsup/chunk-UAX5E3EU.cjs.map +0 -1
- package/dist/tsup/chunk-X72X7I7T.cjs.map +0 -1
- package/dist/tsup/chunk-XU74APB4.js.map +0 -1
- /package/dist/tsup/{chunk-OJZRCEIA.js.map → chunk-4J5EFV3E.js.map} +0 -0
- /package/dist/tsup/{chunk-T7IPDBWH.js.map → chunk-NRP2OHSW.js.map} +0 -0
- /package/dist/tsup/{chunk-PHCD25XO.js.map → chunk-Y7ZDTLD2.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkS6F7EKC7cjs = require('./chunk-S6F7EKC7.cjs');
|
|
4
4
|
|
|
5
5
|
// src/client/log.ts
|
|
6
6
|
function logger() {
|
|
7
|
-
return
|
|
7
|
+
return _chunkS6F7EKC7cjs.getLogger.call(void 0, "actor-client");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
// src/common/websocket.ts
|
|
@@ -46,4 +46,4 @@ async function importWebSocket() {
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
exports.logger = logger; exports.importWebSocket = importWebSocket;
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-DSNSFYDL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-DSNSFYDL.cjs","../../src/client/log.ts","../../src/common/websocket.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;ACFO,SAAS,MAAA,CAAA,EAAS;AACxB,EAAA,OAAO,yCAAA,cAAwB,CAAA;AAChC;ADIA;AACA;AENA,IAAI,iBAAA,EAAqD,IAAA;AAEzD,MAAA,SAAsB,eAAA,CAAA,EAA6C;AAElE,EAAA,GAAA,CAAI,iBAAA,IAAqB,IAAA,EAAM;AAC9B,IAAA,OAAO,gBAAA;AAAA,EACR;AAGA,EAAA,iBAAA,EAAA,CAAoB,MAAA,CAAA,EAAA,GAAY;AAC/B,IAAA,IAAI,UAAA;AAEJ,IAAA,GAAA,CAAI,OAAO,UAAA,IAAc,WAAA,EAAa;AAErC,MAAA,WAAA,EAAa,SAAA;AAAA,IACd,EAAA,KAAO;AAEN,MAAA,IAAI;AACH,QAAA,MAAM,WAAA,EAAa,IAAA;AACnB,QAAA,MAAM,GAAA,EAAK,MAAM,4DAAA;AAAA;AAAA,UAAiC;AAAA,QAAA,GAAA;AAClD,QAAA,WAAA,EAAa,EAAA,CAAG,OAAA;AAChB,QAAA,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,0BAA0B,CAAA;AAAA,MAC1C,EAAA,UAAQ;AAEP,QAAA,WAAA,EAAa,MAAM,cAAc;AAAA,UAChC,WAAA,CAAA,EAAc;AACb,YAAA,MAAM,IAAI,KAAA;AAAA,cACT;AAAA,YACD,CAAA;AAAA,UACD;AAAA,QACD,CAAA;AACA,QAAA,MAAA,CAAO,CAAA,CAAE,KAAA,CAAM,sBAAsB,CAAA;AAAA,MACtC;AAAA,IACD;AAEA,IAAA,OAAO,UAAA;AAAA,EACR,CAAA,CAAA,CAAG,CAAA;AAEH,EAAA,OAAO,gBAAA;AACR;AFCA;AACA;AACE;AACA;AACF,mEAAC","file":"/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-DSNSFYDL.cjs","sourcesContent":[null,"import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"actor-client\");\n}\n","import { logger } from \"@/client/log\";\n\n// Global singleton promise that will be reused for subsequent calls\nlet webSocketPromise: Promise<typeof WebSocket> | null = null;\n\nexport async function importWebSocket(): Promise<typeof WebSocket> {\n\t// Return existing promise if we already started loading\n\tif (webSocketPromise !== null) {\n\t\treturn webSocketPromise;\n\t}\n\n\t// Create and store the promise\n\twebSocketPromise = (async () => {\n\t\tlet _WebSocket: typeof WebSocket;\n\n\t\tif (typeof WebSocket !== \"undefined\") {\n\t\t\t// Browser environment\n\t\t\t_WebSocket = WebSocket as unknown as typeof WebSocket;\n\t\t} else {\n\t\t\t// Node.js environment\n\t\t\ttry {\n\t\t\t\tconst moduleName = \"ws\";\n\t\t\t\tconst ws = await import(/* webpackIgnore: true */ moduleName);\n\t\t\t\t_WebSocket = ws.default as unknown as typeof WebSocket;\n\t\t\t\tlogger().debug(\"using websocket from npm\");\n\t\t\t} catch {\n\t\t\t\t// WS not available\n\t\t\t\t_WebSocket = class MockWebSocket {\n\t\t\t\t\tconstructor() {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'WebSocket support requires installing the \"ws\" peer dependency.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} as unknown as typeof WebSocket;\n\t\t\t\tlogger().debug(\"using mock websocket\");\n\t\t\t}\n\t\t}\n\n\t\treturn _WebSocket;\n\t})();\n\n\treturn webSocketPromise;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/
|
|
1
|
+
{"version":3,"sources":["/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-GBENOENJ.cjs","../../../../../node_modules/.pnpm/tsup@8.5.0_@microsoft+api-extractor@7.53.2_@types+node@22.18.1__jiti@1.21.7_postcss@8.5_c79886ed8b8686a56716e83246c37f4b/node_modules/tsup/assets/cjs_shims.js"],"names":[],"mappings":"AAAA;ACKA,IAAM,iBAAA,EAAmB,CAAA,EAAA,GACvB,OAAO,SAAA,IAAa,YAAA,EAChB,IAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAI8B;ADR4B;AACA;AACA;AACA","file":"/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-GBENOENJ.cjs","sourcesContent":[null,"// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkWYZLRPQMcjs = require('./chunk-WYZLRPQM.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
@@ -16,7 +16,7 @@ var _chunkUAX5E3EUcjs = require('./chunk-UAX5E3EU.cjs');
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
var
|
|
19
|
+
var _chunkB5UXC4QVcjs = require('./chunk-B5UXC4QV.cjs');
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ var _chunkKMYFL3OLcjs = require('./chunk-KMYFL3OL.cjs');
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
var
|
|
29
|
+
var _chunkS6F7EKC7cjs = require('./chunk-S6F7EKC7.cjs');
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
@@ -41,7 +41,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
41
41
|
const router = new (0, _hono.Hono)({
|
|
42
42
|
strict: false
|
|
43
43
|
});
|
|
44
|
-
router.use("*",
|
|
44
|
+
router.use("*", _chunkB5UXC4QVcjs.loggerMiddleware.call(void 0, _chunkB5UXC4QVcjs.loggerWithoutContext.call(void 0, )));
|
|
45
45
|
router.use("*", async (c, next) => {
|
|
46
46
|
const actor = await actorDriver.loadActor(c.env.actorId);
|
|
47
47
|
actor.beginHonoHttpRequest();
|
|
@@ -62,7 +62,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
62
62
|
router.get("/metadata", async (c) => {
|
|
63
63
|
return c.json({
|
|
64
64
|
runtime: "rivetkit",
|
|
65
|
-
version:
|
|
65
|
+
version: _chunkS6F7EKC7cjs.VERSION
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
68
|
if (isTest) {
|
|
@@ -77,8 +77,8 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
77
77
|
if (!conn) {
|
|
78
78
|
return c.text(`Connection not found: ${connId}`, 404);
|
|
79
79
|
}
|
|
80
|
-
if ((_a = conn[
|
|
81
|
-
conn[
|
|
80
|
+
if ((_a = conn[_chunkB5UXC4QVcjs.CONN_DRIVER_SYMBOL]) == null ? void 0 : _a.terminate) {
|
|
81
|
+
conn[_chunkB5UXC4QVcjs.CONN_DRIVER_SYMBOL].terminate(actor, conn);
|
|
82
82
|
}
|
|
83
83
|
return c.json({ success: true });
|
|
84
84
|
});
|
|
@@ -86,7 +86,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
86
86
|
if (getUpgradeWebSocket) {
|
|
87
87
|
router.on(
|
|
88
88
|
"GET",
|
|
89
|
-
[
|
|
89
|
+
[_chunkB5UXC4QVcjs.PATH_CONNECT, `${_chunkB5UXC4QVcjs.PATH_WEBSOCKET_PREFIX}*`, _chunkB5UXC4QVcjs.PATH_INSPECTOR_CONNECT],
|
|
90
90
|
async (c) => {
|
|
91
91
|
const upgradeWebSocket = getUpgradeWebSocket();
|
|
92
92
|
if (upgradeWebSocket) {
|
|
@@ -94,8 +94,8 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
94
94
|
const protocols = c2.req.header(
|
|
95
95
|
"sec-websocket-protocol"
|
|
96
96
|
);
|
|
97
|
-
const { encoding, connParams } =
|
|
98
|
-
return await
|
|
97
|
+
const { encoding, connParams } = _chunkB5UXC4QVcjs.parseWebSocketProtocols.call(void 0, protocols);
|
|
98
|
+
return await _chunkB5UXC4QVcjs.routeWebSocket.call(void 0,
|
|
99
99
|
c2.req.raw,
|
|
100
100
|
c2.req.path,
|
|
101
101
|
c2.req.header(),
|
|
@@ -109,7 +109,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
109
109
|
false,
|
|
110
110
|
false
|
|
111
111
|
);
|
|
112
|
-
})(c,
|
|
112
|
+
})(c, _chunkS6F7EKC7cjs.noopNext.call(void 0, ));
|
|
113
113
|
} else {
|
|
114
114
|
return c.text(
|
|
115
115
|
"WebSockets are not enabled for this driver.",
|
|
@@ -121,7 +121,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
121
121
|
}
|
|
122
122
|
router.post("/action/:action", async (c) => {
|
|
123
123
|
const actionName = c.req.param("action");
|
|
124
|
-
return
|
|
124
|
+
return _chunkB5UXC4QVcjs.handleAction.call(void 0, c, config4, actorDriver, actionName, c.env.actorId);
|
|
125
125
|
});
|
|
126
126
|
router.all("/request/*", async (c) => {
|
|
127
127
|
const url = new URL(c.req.url);
|
|
@@ -133,20 +133,20 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
133
133
|
body: c.req.raw.body,
|
|
134
134
|
duplex: "half"
|
|
135
135
|
});
|
|
136
|
-
|
|
136
|
+
_chunkB5UXC4QVcjs.loggerWithoutContext.call(void 0, ).debug({
|
|
137
137
|
msg: "rewriting http url",
|
|
138
138
|
from: c.req.url,
|
|
139
139
|
to: correctedRequest.url
|
|
140
140
|
});
|
|
141
|
-
return await
|
|
141
|
+
return await _chunkB5UXC4QVcjs.handleRawRequest.call(void 0,
|
|
142
142
|
c,
|
|
143
143
|
correctedRequest,
|
|
144
144
|
actorDriver,
|
|
145
145
|
c.env.actorId
|
|
146
146
|
);
|
|
147
147
|
});
|
|
148
|
-
router.notFound(
|
|
149
|
-
router.onError(
|
|
148
|
+
router.notFound(_chunkB5UXC4QVcjs.handleRouteNotFound);
|
|
149
|
+
router.onError(_chunkB5UXC4QVcjs.handleRouteError);
|
|
150
150
|
return router;
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -154,7 +154,7 @@ function createActorRouter(config4, actorDriver, getUpgradeWebSocket, isTest) {
|
|
|
154
154
|
var _ws = require('hono/ws');
|
|
155
155
|
var _virtualwebsocket = require('@rivetkit/virtual-websocket');
|
|
156
156
|
function logger() {
|
|
157
|
-
return
|
|
157
|
+
return _chunkS6F7EKC7cjs.getLogger.call(void 0, "inline-websocket-adapter");
|
|
158
158
|
}
|
|
159
159
|
var InlineWebSocketAdapter = class {
|
|
160
160
|
#handler;
|
|
@@ -743,7 +743,7 @@ var v1ToV2 = (v1State) => {
|
|
|
743
743
|
if (v1State.persistedData) {
|
|
744
744
|
const key = new Uint8Array([1]);
|
|
745
745
|
kvStorage.push({
|
|
746
|
-
key:
|
|
746
|
+
key: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key),
|
|
747
747
|
value: v1State.persistedData
|
|
748
748
|
});
|
|
749
749
|
}
|
|
@@ -849,7 +849,7 @@ var ACTOR_ALARM_VERSIONED = _vbare.createVersionedDataHandler.call(void 0, {
|
|
|
849
849
|
|
|
850
850
|
// src/drivers/file-system/log.ts
|
|
851
851
|
function logger2() {
|
|
852
|
-
return
|
|
852
|
+
return _chunkS6F7EKC7cjs.getLogger.call(void 0, "driver-fs");
|
|
853
853
|
}
|
|
854
854
|
|
|
855
855
|
// src/drivers/file-system/utils.ts
|
|
@@ -1044,11 +1044,11 @@ var FileSystemGlobalState = class {
|
|
|
1044
1044
|
entry.generation = crypto.randomUUID();
|
|
1045
1045
|
}
|
|
1046
1046
|
const kvStorage = [];
|
|
1047
|
-
const initialKvState =
|
|
1047
|
+
const initialKvState = _chunkB5UXC4QVcjs.getInitialActorKvState.call(void 0, input);
|
|
1048
1048
|
for (const [key2, value] of initialKvState) {
|
|
1049
1049
|
kvStorage.push({
|
|
1050
|
-
key:
|
|
1051
|
-
value:
|
|
1050
|
+
key: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key2),
|
|
1051
|
+
value: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, value)
|
|
1052
1052
|
});
|
|
1053
1053
|
}
|
|
1054
1054
|
entry.state = {
|
|
@@ -1118,11 +1118,11 @@ var FileSystemGlobalState = class {
|
|
|
1118
1118
|
entry.generation = crypto.randomUUID();
|
|
1119
1119
|
}
|
|
1120
1120
|
const kvStorage = [];
|
|
1121
|
-
const initialKvState =
|
|
1121
|
+
const initialKvState = _chunkB5UXC4QVcjs.getInitialActorKvState.call(void 0, input);
|
|
1122
1122
|
for (const [key2, value] of initialKvState) {
|
|
1123
1123
|
kvStorage.push({
|
|
1124
|
-
key:
|
|
1125
|
-
value:
|
|
1124
|
+
key: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key2),
|
|
1125
|
+
value: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, value)
|
|
1126
1126
|
});
|
|
1127
1127
|
}
|
|
1128
1128
|
entry.state = {
|
|
@@ -1201,7 +1201,7 @@ var FileSystemGlobalState = class {
|
|
|
1201
1201
|
logger2().error({
|
|
1202
1202
|
msg: "failed to delete actor state file",
|
|
1203
1203
|
actorId,
|
|
1204
|
-
error:
|
|
1204
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1205
1205
|
});
|
|
1206
1206
|
}
|
|
1207
1207
|
}
|
|
@@ -1215,7 +1215,7 @@ var FileSystemGlobalState = class {
|
|
|
1215
1215
|
logger2().error({
|
|
1216
1216
|
msg: "failed to delete actor database file",
|
|
1217
1217
|
actorId,
|
|
1218
|
-
error:
|
|
1218
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1219
1219
|
});
|
|
1220
1220
|
}
|
|
1221
1221
|
}
|
|
@@ -1229,7 +1229,7 @@ var FileSystemGlobalState = class {
|
|
|
1229
1229
|
logger2().error({
|
|
1230
1230
|
msg: "failed to delete actor alarm file",
|
|
1231
1231
|
actorId,
|
|
1232
|
-
error:
|
|
1232
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1233
1233
|
});
|
|
1234
1234
|
}
|
|
1235
1235
|
}
|
|
@@ -1406,9 +1406,9 @@ var FileSystemGlobalState = class {
|
|
|
1406
1406
|
if (entry.actor) {
|
|
1407
1407
|
return entry.actor;
|
|
1408
1408
|
}
|
|
1409
|
-
entry.startPromise =
|
|
1409
|
+
entry.startPromise = _chunkS6F7EKC7cjs.promiseWithResolvers.call(void 0, );
|
|
1410
1410
|
try {
|
|
1411
|
-
const definition =
|
|
1411
|
+
const definition = _chunkWYZLRPQMcjs.lookupInRegistry.call(void 0,
|
|
1412
1412
|
config4,
|
|
1413
1413
|
entry.state.name
|
|
1414
1414
|
);
|
|
@@ -1488,7 +1488,7 @@ var FileSystemGlobalState = class {
|
|
|
1488
1488
|
logger2().error({
|
|
1489
1489
|
msg: "failed to read alarm file",
|
|
1490
1490
|
file,
|
|
1491
|
-
error:
|
|
1491
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1492
1492
|
});
|
|
1493
1493
|
}
|
|
1494
1494
|
}
|
|
@@ -1518,7 +1518,7 @@ var FileSystemGlobalState = class {
|
|
|
1518
1518
|
(_a = entry.alarmTimeout) == null ? void 0 : _a.abort();
|
|
1519
1519
|
entry.alarmTimestamp = timestamp;
|
|
1520
1520
|
const delay = Math.max(0, timestamp - Date.now());
|
|
1521
|
-
entry.alarmTimeout =
|
|
1521
|
+
entry.alarmTimeout = _chunkS6F7EKC7cjs.setLongTimeout.call(void 0, async () => {
|
|
1522
1522
|
entry.alarmTimestamp = void 0;
|
|
1523
1523
|
if (this.#persist) {
|
|
1524
1524
|
try {
|
|
@@ -1529,7 +1529,7 @@ var FileSystemGlobalState = class {
|
|
|
1529
1529
|
logger2().debug({
|
|
1530
1530
|
msg: "failed to remove alarm file",
|
|
1531
1531
|
actorId,
|
|
1532
|
-
error:
|
|
1532
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1533
1533
|
});
|
|
1534
1534
|
}
|
|
1535
1535
|
}
|
|
@@ -1555,7 +1555,7 @@ var FileSystemGlobalState = class {
|
|
|
1555
1555
|
logger2().error({
|
|
1556
1556
|
msg: "failed to handle alarm",
|
|
1557
1557
|
actorId,
|
|
1558
|
-
error:
|
|
1558
|
+
error: _chunkS6F7EKC7cjs.stringifyError.call(void 0, err)
|
|
1559
1559
|
});
|
|
1560
1560
|
}
|
|
1561
1561
|
}, delay);
|
|
@@ -1611,17 +1611,17 @@ var FileSystemGlobalState = class {
|
|
|
1611
1611
|
const newKvStorage = [...entry.state.kvStorage];
|
|
1612
1612
|
for (const [key, value] of entries) {
|
|
1613
1613
|
const existingIndex = newKvStorage.findIndex(
|
|
1614
|
-
(e) =>
|
|
1614
|
+
(e) => _chunkS6F7EKC7cjs.arrayBuffersEqual.call(void 0, e.key, _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key))
|
|
1615
1615
|
);
|
|
1616
1616
|
if (existingIndex >= 0) {
|
|
1617
1617
|
newKvStorage[existingIndex] = {
|
|
1618
|
-
key:
|
|
1619
|
-
value:
|
|
1618
|
+
key: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key),
|
|
1619
|
+
value: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, value)
|
|
1620
1620
|
};
|
|
1621
1621
|
} else {
|
|
1622
1622
|
newKvStorage.push({
|
|
1623
|
-
key:
|
|
1624
|
-
value:
|
|
1623
|
+
key: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key),
|
|
1624
|
+
value: _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, value)
|
|
1625
1625
|
});
|
|
1626
1626
|
}
|
|
1627
1627
|
}
|
|
@@ -1646,7 +1646,7 @@ var FileSystemGlobalState = class {
|
|
|
1646
1646
|
const results = [];
|
|
1647
1647
|
for (const key of keys) {
|
|
1648
1648
|
const foundEntry = entry.state.kvStorage.find(
|
|
1649
|
-
(e) =>
|
|
1649
|
+
(e) => _chunkS6F7EKC7cjs.arrayBuffersEqual.call(void 0, e.key, _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key))
|
|
1650
1650
|
);
|
|
1651
1651
|
if (foundEntry) {
|
|
1652
1652
|
results.push(new Uint8Array(foundEntry.value));
|
|
@@ -1671,7 +1671,7 @@ var FileSystemGlobalState = class {
|
|
|
1671
1671
|
const newKvStorage = [...entry.state.kvStorage];
|
|
1672
1672
|
for (const key of keys) {
|
|
1673
1673
|
const indexToDelete = newKvStorage.findIndex(
|
|
1674
|
-
(e) =>
|
|
1674
|
+
(e) => _chunkS6F7EKC7cjs.arrayBuffersEqual.call(void 0, e.key, _chunkS6F7EKC7cjs.bufferToArrayBuffer.call(void 0, key))
|
|
1675
1675
|
);
|
|
1676
1676
|
if (indexToDelete >= 0) {
|
|
1677
1677
|
newKvStorage.splice(indexToDelete, 1);
|
|
@@ -1728,7 +1728,7 @@ var FileSystemManagerDriver = class {
|
|
|
1728
1728
|
this.#config = config4;
|
|
1729
1729
|
this.#state = state;
|
|
1730
1730
|
this.#driverConfig = driverConfig;
|
|
1731
|
-
const inlineClient =
|
|
1731
|
+
const inlineClient = _chunkWYZLRPQMcjs.createClientWithDriver.call(void 0, this);
|
|
1732
1732
|
this.#actorDriver = this.#driverConfig.actor(
|
|
1733
1733
|
config4,
|
|
1734
1734
|
this,
|
|
@@ -1753,7 +1753,7 @@ var FileSystemManagerDriver = class {
|
|
|
1753
1753
|
method: "GET"
|
|
1754
1754
|
});
|
|
1755
1755
|
const pathOnly = normalizedPath.split("?")[0];
|
|
1756
|
-
const wsHandler = await
|
|
1756
|
+
const wsHandler = await _chunkB5UXC4QVcjs.routeWebSocket.call(void 0,
|
|
1757
1757
|
fakeRequest,
|
|
1758
1758
|
pathOnly,
|
|
1759
1759
|
{},
|
|
@@ -1780,7 +1780,7 @@ var FileSystemManagerDriver = class {
|
|
|
1780
1780
|
_invariant2.default.call(void 0, upgradeWebSocket, "missing getUpgradeWebSocket");
|
|
1781
1781
|
const pathOnly = path.split("?")[0];
|
|
1782
1782
|
const normalizedPath = pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
|
|
1783
|
-
const wsHandler = await
|
|
1783
|
+
const wsHandler = await _chunkB5UXC4QVcjs.routeWebSocket.call(void 0,
|
|
1784
1784
|
// TODO: Create new request with new path
|
|
1785
1785
|
c.req.raw,
|
|
1786
1786
|
normalizedPath,
|
|
@@ -1795,7 +1795,7 @@ var FileSystemManagerDriver = class {
|
|
|
1795
1795
|
false,
|
|
1796
1796
|
false
|
|
1797
1797
|
);
|
|
1798
|
-
return upgradeWebSocket(() => wsHandler)(c,
|
|
1798
|
+
return upgradeWebSocket(() => wsHandler)(c, _chunkS6F7EKC7cjs.noopNext.call(void 0, ));
|
|
1799
1799
|
}
|
|
1800
1800
|
async buildGatewayUrl(actorId) {
|
|
1801
1801
|
const port = _nullishCoalesce(this.#config.managerPort, () => ( 6420));
|
|
@@ -1946,4 +1946,4 @@ function createMemoryDriver() {
|
|
|
1946
1946
|
|
|
1947
1947
|
|
|
1948
1948
|
exports.createActorRouter = createActorRouter; exports.InlineWebSocketAdapter = InlineWebSocketAdapter; exports.importNodeDependencies = importNodeDependencies; exports.getNodeCrypto = getNodeCrypto; exports.getNodeFsSync = getNodeFsSync; exports.getNodeFs = getNodeFs; exports.getNodePath = getNodePath; exports.getNodeChildProcess = getNodeChildProcess; exports.getNodeStream = getNodeStream; exports.getStoragePath = getStoragePath; exports.ensureDirectoryExists = ensureDirectoryExists; exports.createFileSystemOrMemoryDriver = createFileSystemOrMemoryDriver; exports.createFileSystemDriver = createFileSystemDriver; exports.createMemoryDriver = createMemoryDriver;
|
|
1949
|
-
//# sourceMappingURL=chunk-
|
|
1949
|
+
//# sourceMappingURL=chunk-GTQKDCM4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-GTQKDCM4.cjs","../../src/actor/router.ts","../../src/common/inline-websocket-adapter.ts","../../src/utils/node.ts","../../src/drivers/file-system/actor.ts","../../src/drivers/file-system/global-state.ts","../../src/schemas/file-system-driver/versioned.ts","../schemas/file-system-driver/v1.ts","../schemas/file-system-driver/v2.ts","../schemas/file-system-driver/v3.ts","../../src/drivers/file-system/log.ts","../../src/drivers/file-system/utils.ts","../../src/drivers/file-system/manager.ts","../../src/drivers/file-system/mod.ts"],"names":["config"],"mappings":"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","file":"/Users/nathan/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-GTQKDCM4.cjs","sourcesContent":[null,"import { Hono } from \"hono\";\nimport {\n\ttype ActionOpts,\n\ttype ActionOutput,\n\ttype ConnsMessageOpts,\n\thandleAction,\n\thandleRawRequest,\n} from \"@/actor/router-endpoints\";\nimport {\n\tPATH_CONNECT,\n\tPATH_INSPECTOR_CONNECT,\n\tPATH_WEBSOCKET_PREFIX,\n} from \"@/common/actor-router-consts\";\nimport {\n\thandleRouteError,\n\thandleRouteNotFound,\n\tloggerMiddleware,\n} from \"@/common/router\";\nimport { noopNext } from \"@/common/utils\";\n\nimport type { RegistryConfig } from \"@/registry/config\";\nimport { type GetUpgradeWebSocket, VERSION } from \"@/utils\";\nimport { CONN_DRIVER_SYMBOL } from \"./conn/mod\";\nimport type { ActorDriver } from \"./driver\";\nimport { loggerWithoutContext } from \"./log\";\nimport {\n\tparseWebSocketProtocols,\n\trouteWebSocket,\n} from \"./router-websocket-endpoints\";\n\nexport type { ActionOpts, ActionOutput, ConnsMessageOpts };\n\ninterface ActorRouterBindings {\n\tactorId: string;\n}\n\nexport type ActorRouter = Hono<{ Bindings: ActorRouterBindings }>;\n\nexport interface MetadataResponse {\n\truntime: string;\n\tversion: string;\n}\n\n/**\n * Creates a router that runs on the partitioned instance.\n *\n * You only need to pass `getUpgradeWebSocket` if this router is exposed\n * directly publicly. Usually WebSockets are routed manually in the\n * ManagerDriver instead of via Hono. The only platform that uses this\n * currently is Cloudflare Workers.\n */\nexport function createActorRouter(\n\tconfig: RegistryConfig,\n\tactorDriver: ActorDriver,\n\tgetUpgradeWebSocket: GetUpgradeWebSocket | undefined,\n\tisTest: boolean,\n): ActorRouter {\n\tconst router = new Hono<{ Bindings: ActorRouterBindings }>({\n\t\tstrict: false,\n\t});\n\n\trouter.use(\"*\", loggerMiddleware(loggerWithoutContext()));\n\n\t// Track all HTTP requests to prevent actor from sleeping during active requests\n\trouter.use(\"*\", async (c, next) => {\n\t\tconst actor = await actorDriver.loadActor(c.env.actorId);\n\t\tactor.beginHonoHttpRequest();\n\t\ttry {\n\t\t\tawait next();\n\t\t} finally {\n\t\t\tactor.endHonoHttpRequest();\n\t\t}\n\t});\n\n\trouter.get(\"/\", (c) => {\n\t\treturn c.text(\n\t\t\t\"This is an RivetKit actor.\\n\\nLearn more at https://rivetkit.org\",\n\t\t);\n\t});\n\n\trouter.get(\"/health\", (c) => {\n\t\treturn c.text(\"ok\");\n\t});\n\n\trouter.get(\"/metadata\", async (c) => {\n\t\treturn c.json({\n\t\t\truntime: \"rivetkit\",\n\t\t\tversion: VERSION,\n\t\t} satisfies MetadataResponse);\n\t});\n\n\tif (isTest) {\n\t\t// Test endpoint to force disconnect a connection non-cleanly\n\t\trouter.post(\"/.test/force-disconnect\", async (c) => {\n\t\t\tconst connId = c.req.query(\"conn\");\n\n\t\t\tif (!connId) {\n\t\t\t\treturn c.text(\"Missing conn query parameter\", 400);\n\t\t\t}\n\n\t\t\tconst actor = await actorDriver.loadActor(c.env.actorId);\n\t\t\tconst conn = actor.connectionManager.getConnForId(connId);\n\n\t\t\tif (!conn) {\n\t\t\t\treturn c.text(`Connection not found: ${connId}`, 404);\n\t\t\t}\n\n\t\t\t// Force close the connection without clean shutdown\n\t\t\tif (conn[CONN_DRIVER_SYMBOL]?.terminate) {\n\t\t\t\tconn[CONN_DRIVER_SYMBOL].terminate(actor, conn);\n\t\t\t}\n\n\t\t\treturn c.json({ success: true });\n\t\t});\n\t}\n\n\t// Route all WebSocket paths using the same handler\n\t//\n\t// All WebSockets use a separate underlying router in routeWebSocket since\n\t// WebSockets also need to be routed from ManagerDriver.proxyWebSocket and\n\t// ManagerDriver.openWebSocket.\n\tif (getUpgradeWebSocket) {\n\t\trouter.on(\n\t\t\t\"GET\",\n\t\t\t[PATH_CONNECT, `${PATH_WEBSOCKET_PREFIX}*`, PATH_INSPECTOR_CONNECT],\n\t\t\tasync (c) => {\n\t\t\t\tconst upgradeWebSocket = getUpgradeWebSocket();\n\t\t\t\tif (upgradeWebSocket) {\n\t\t\t\t\treturn upgradeWebSocket(async (c) => {\n\t\t\t\t\t\tconst protocols = c.req.header(\n\t\t\t\t\t\t\t\"sec-websocket-protocol\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst { encoding, connParams } =\n\t\t\t\t\t\t\tparseWebSocketProtocols(protocols);\n\n\t\t\t\t\t\treturn await routeWebSocket(\n\t\t\t\t\t\t\tc.req.raw,\n\t\t\t\t\t\t\tc.req.path,\n\t\t\t\t\t\t\tc.req.header(),\n\t\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t\tactorDriver,\n\t\t\t\t\t\t\tc.env.actorId,\n\t\t\t\t\t\t\tencoding,\n\t\t\t\t\t\t\tconnParams,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t);\n\t\t\t\t\t})(c, noopNext());\n\t\t\t\t} else {\n\t\t\t\t\treturn c.text(\n\t\t\t\t\t\t\"WebSockets are not enabled for this driver.\",\n\t\t\t\t\t\t400,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\trouter.post(\"/action/:action\", async (c) => {\n\t\tconst actionName = c.req.param(\"action\");\n\n\t\treturn handleAction(c, config, actorDriver, actionName, c.env.actorId);\n\t});\n\n\trouter.all(\"/request/*\", async (c) => {\n\t\t// TODO: This is not a clean way of doing this since `/http/` might exist mid-path\n\t\t// Strip the /http prefix from the URL to get the original path\n\t\tconst url = new URL(c.req.url);\n\t\tconst originalPath = url.pathname.replace(/^\\/request/, \"\") || \"/\";\n\n\t\t// Create a new request with the corrected URL\n\t\tconst correctedUrl = new URL(originalPath + url.search, url.origin);\n\t\tconst correctedRequest = new Request(correctedUrl, {\n\t\t\tmethod: c.req.method,\n\t\t\theaders: c.req.raw.headers,\n\t\t\tbody: c.req.raw.body,\n\t\t\tduplex: \"half\",\n\t\t} as RequestInit);\n\n\t\tloggerWithoutContext().debug({\n\t\t\tmsg: \"rewriting http url\",\n\t\t\tfrom: c.req.url,\n\t\t\tto: correctedRequest.url,\n\t\t});\n\n\t\treturn await handleRawRequest(\n\t\t\tc,\n\t\t\tcorrectedRequest,\n\t\t\tactorDriver,\n\t\t\tc.env.actorId,\n\t\t);\n\t});\n\n\trouter.notFound(handleRouteNotFound);\n\trouter.onError(handleRouteError);\n\n\treturn router;\n}\n","import { WSContext } from \"hono/ws\";\nimport type { UpgradeWebSocketArgs } from \"@/actor/router-websocket-endpoints\";\nimport type { UniversalWebSocket } from \"@/common/websocket-interface\";\nimport { VirtualWebSocket } from \"@rivetkit/virtual-websocket\";\nimport { getLogger } from \"./log\";\n\nfunction logger() {\n\treturn getLogger(\"inline-websocket-adapter\");\n}\n\n/**\n * InlineWebSocketAdapter creates two linked WebSocket objects:\n * - clientWs: for the client/proxy side (returned from openWebSocket)\n * - actorWs: for the actor side (passed via wsContext.raw)\n *\n * Each side's send() triggers the OTHER side's message event.\n */\nexport class InlineWebSocketAdapter {\n\t#handler: UpgradeWebSocketArgs;\n\t#wsContext: WSContext;\n\t#readyState: 0 | 1 | 2 | 3 = 0;\n\n\t#clientWs: VirtualWebSocket;\n\t#actorWs: VirtualWebSocket;\n\n\tconstructor(handler: UpgradeWebSocketArgs) {\n\t\tthis.#handler = handler;\n\n\t\t// Create linked WebSocket pair\n\t\t// Client's send() -> handler.onMessage (for RPC) + Actor's message event (for raw WS)\n\t\t// Actor's send() -> Client's message event\n\t\tthis.#clientWs = new VirtualWebSocket({\n\t\t\tgetReadyState: () => this.#readyState,\n\t\t\tonSend: (data) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Call handler.onMessage for protocol-based connections (RPC)\n\t\t\t\t\tthis.#handler.onMessage({ data }, this.#wsContext);\n\t\t\t\t\t// Also trigger message event on actor's websocket for raw websocket handlers\n\t\t\t\t\tthis.#actorWs.triggerMessage(data);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.#handleError(err);\n\t\t\t\t\tthis.#close(1011, \"Internal error processing message\");\n\t\t\t\t}\n\t\t\t},\n\t\t\tonClose: (code, reason) => this.#close(code, reason),\n\t\t});\n\n\t\tthis.#actorWs = new VirtualWebSocket({\n\t\t\tgetReadyState: () => this.#readyState,\n\t\t\tonSend: (data) => this.#clientWs.triggerMessage(data),\n\t\t\tonClose: (code, reason) => this.#close(code, reason),\n\t\t});\n\n\t\t// Create WSContext with actorWs as raw\n\t\tthis.#wsContext = new WSContext({\n\t\t\traw: this.#actorWs,\n\t\t\tsend: (data: string | ArrayBuffer | Uint8Array) => {\n\t\t\t\tlogger().debug({ msg: \"WSContext.send called\" });\n\t\t\t\tthis.#clientWs.triggerMessage(data);\n\t\t\t},\n\t\t\tclose: (code?: number, reason?: string) => {\n\t\t\t\tlogger().debug({ msg: \"WSContext.close called\", code, reason });\n\t\t\t\tthis.#close(code || 1000, reason || \"\");\n\t\t\t},\n\t\t\treadyState: 1,\n\t\t});\n\n\t\t// Defer initialization to allow event listeners to be attached first\n\t\tsetTimeout(() => {\n\t\t\tthis.#initialize();\n\t\t}, 0);\n\t}\n\n\t/** Get the client-side WebSocket (for proxy/client code) */\n\tget clientWebSocket(): UniversalWebSocket {\n\t\treturn this.#clientWs;\n\t}\n\n\t/** Get the actor-side WebSocket (passed to actor via wsContext.raw) */\n\tget actorWebSocket(): UniversalWebSocket {\n\t\treturn this.#actorWs;\n\t}\n\n\tasync #initialize(): Promise<void> {\n\t\ttry {\n\t\t\tlogger().debug({ msg: \"websocket initializing\" });\n\n\t\t\tthis.#readyState = 1; // OPEN\n\n\t\t\tlogger().debug({ msg: \"calling handler.onOpen with WSContext\" });\n\t\t\tthis.#handler.onOpen(undefined, this.#wsContext);\n\n\t\t\t// Fire open event to both sides\n\t\t\tthis.#clientWs.triggerOpen();\n\t\t\tthis.#actorWs.triggerOpen();\n\t\t} catch (err) {\n\t\t\tthis.#handleError(err);\n\t\t\tthis.#close(1011, \"Internal error during initialization\");\n\t\t}\n\t}\n\n\t#handleError(err: unknown): void {\n\t\tlogger().error({\n\t\t\tmsg: \"error in websocket\",\n\t\t\terror: err,\n\t\t\terrorMessage: err instanceof Error ? err.message : String(err),\n\t\t\tstack: err instanceof Error ? err.stack : undefined,\n\t\t});\n\n\t\t// Call handler.onError\n\t\ttry {\n\t\t\tthis.#handler.onError(err, this.#wsContext);\n\t\t} catch (handlerErr) {\n\t\t\tlogger().error({ msg: \"error in onError handler\", error: handlerErr });\n\t\t}\n\n\t\t// Fire error event to both sides\n\t\tthis.#clientWs.triggerError(err);\n\t\tthis.#actorWs.triggerError(err);\n\t}\n\n\t#close(code: number, reason: string): void {\n\t\tif (this.#readyState === 3 || this.#readyState === 2) {\n\t\t\treturn;\n\t\t}\n\n\t\tlogger().debug({ msg: \"closing websocket\", code, reason });\n\n\t\tthis.#readyState = 2; // CLOSING\n\n\t\ttry {\n\t\t\tthis.#handler.onClose({ code, reason, wasClean: true }, this.#wsContext);\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"error closing websocket\", error: err });\n\t\t} finally {\n\t\t\tthis.#readyState = 3; // CLOSED\n\n\t\t\t// Fire close event to both sides\n\t\t\tthis.#clientWs.triggerClose(code, reason);\n\t\t\tthis.#actorWs.triggerClose(code, reason);\n\t\t}\n\t}\n}\n\n/**\n * Creates an InlineWebSocketAdapter and returns the client-side WebSocket.\n * This is the main entry point for creating inline WebSocket connections.\n */\nexport function createInlineWebSocket(\n\thandler: UpgradeWebSocketArgs,\n): UniversalWebSocket {\n\tconst adapter = new InlineWebSocketAdapter(handler);\n\treturn adapter.clientWebSocket;\n}\n","import { createRequire } from \"node:module\";\n\n// Global variables for Node.js modules.\n//\n// We use synchronous require() instead of async import() for Node.js module loading because:\n// 1. These modules are only needed in Node.js environments (not browser/edge)\n// 2. registry.start() cannot be async and needs immediate access to Node modules\n// 3. The setup process must be synchronous to avoid breaking the API\n//\n// Biome only allows imports of node modules in this file in order to ensure\n// we're forcing the use of dynamic imports.\nlet nodeCrypto: typeof import(\"node:crypto\") | undefined;\nlet nodeFsSync: typeof import(\"node:fs\") | undefined;\nlet nodeFs: typeof import(\"node:fs/promises\") | undefined;\nlet nodePath: typeof import(\"node:path\") | undefined;\nlet nodeOs: typeof import(\"node:os\") | undefined;\nlet nodeChildProcess: typeof import(\"node:child_process\") | undefined;\nlet nodeStream: typeof import(\"node:stream/promises\") | undefined;\n\nlet hasImportedDependencies = false;\n\n// Helper to get a require function that works in both CommonJS and ESM.\n// We use require() instead of await import() because registry.start() cannot\n// be async and needs immediate access to Node.js modules during setup.\nfunction getRequireFn() {\n\t// TODO: This causes issues in tsup\n\t// CommonJS context - use global require\n\t// if (typeof require !== \"undefined\") {\n\t// \tconsole.log(\"existing require\");\n\t// \treturn require;\n\t// }\n\n\t// ESM context - use createRequire with import.meta.url\n\treturn createRequire(import.meta.url);\n}\n\n/**\n * Dynamically imports all required Node.js dependencies. We do this early in a\n * single function call in order to surface errors early.\n *\n * This function is idempotent and will only import once.\n *\n * @throws Error if Node.js modules are not available (e.g., in browser/edge environments)\n */\nexport function importNodeDependencies(): void {\n\t// Check if already loaded\n\tif (hasImportedDependencies) return;\n\n\ttry {\n\t\t// Get a require function that works in both CommonJS and ESM\n\t\tconst requireFn = getRequireFn();\n\n\t\t// Use requireFn with webpack ignore comment to prevent bundling\n\t\tnodeCrypto = requireFn(/* webpackIgnore: true */ \"node:crypto\");\n\t\tnodeFsSync = requireFn(/* webpackIgnore: true */ \"node:fs\");\n\t\tnodeFs = requireFn(/* webpackIgnore: true */ \"node:fs/promises\");\n\t\tnodePath = requireFn(/* webpackIgnore: true */ \"node:path\");\n\t\tnodeOs = requireFn(/* webpackIgnore: true */ \"node:os\");\n\t\tnodeChildProcess = requireFn(\n\t\t\t/* webpackIgnore: true */ \"node:child_process\",\n\t\t);\n\t\tnodeStream = requireFn(\n\t\t\t/* webpackIgnore: true */ \"node:stream/promises\",\n\t\t);\n\n\t\thasImportedDependencies = true;\n\t} catch (err) {\n\t\tconsole.warn(\n\t\t\t\"Node.js modules not available, file system driver will not work\",\n\t\t\terr,\n\t\t);\n\t\tthrow err;\n\t}\n}\n\n/**\n * Gets the Node.js crypto module.\n * @throws Error if crypto module is not loaded\n */\nexport function getNodeCrypto(): typeof import(\"node:crypto\") {\n\tif (!nodeCrypto) {\n\t\tthrow new Error(\n\t\t\t\"Node crypto module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeCrypto;\n}\n\n/**\n * Gets the Node.js fs module.\n * @throws Error if fs module is not loaded\n */\nexport function getNodeFsSync(): typeof import(\"node:fs\") {\n\tif (!nodeFsSync) {\n\t\tthrow new Error(\n\t\t\t\"Node fs module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeFsSync;\n}\n\n/**\n * Gets the Node.js fs/promises module.\n * @throws Error if fs/promises module is not loaded\n */\nexport function getNodeFs(): typeof import(\"node:fs/promises\") {\n\tif (!nodeFs) {\n\t\tthrow new Error(\n\t\t\t\"Node fs/promises module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeFs;\n}\n\n/**\n * Gets the Node.js path module.\n * @throws Error if path module is not loaded\n */\nexport function getNodePath(): typeof import(\"node:path\") {\n\tif (!nodePath) {\n\t\tthrow new Error(\n\t\t\t\"Node path module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodePath;\n}\n\n/**\n * Gets the Node.js os module.\n * @throws Error if os module is not loaded\n */\nexport function getNodeOs(): typeof import(\"node:os\") {\n\tif (!nodeOs) {\n\t\tthrow new Error(\n\t\t\t\"Node os module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeOs;\n}\n\n/**\n * Gets the Node.js child_process module.\n * @throws Error if child_process module is not loaded\n */\nexport function getNodeChildProcess(): typeof import(\"node:child_process\") {\n\tif (!nodeChildProcess) {\n\t\tthrow new Error(\n\t\t\t\"Node child_process module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeChildProcess;\n}\n\n/**\n * Gets the Node.js stream/promises module.\n * @throws Error if stream/promises module is not loaded\n */\nexport function getNodeStream(): typeof import(\"node:stream/promises\") {\n\tif (!nodeStream) {\n\t\tthrow new Error(\n\t\t\t\"Node stream/promises module not loaded. Ensure importNodeDependencies() has been called.\",\n\t\t);\n\t}\n\treturn nodeStream;\n}\n","import type { AnyClient } from \"@/client/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { FileSystemGlobalState } from \"./global-state\";\nimport { RegistryConfig } from \"@/registry/config\";\n\nexport type ActorDriverContext = Record<never, never>;\n\n/**\n * File System implementation of the Actor Driver\n */\nexport class FileSystemActorDriver implements ActorDriver {\n\t#config: RegistryConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: AnyClient;\n\t#state: FileSystemGlobalState;\n\n\tconstructor(\n\t\tconfig: RegistryConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: AnyClient,\n\t\tstate: FileSystemGlobalState,\n\t) {\n\t\tthis.#config = config;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#state = state;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\treturn this.#state.startActor(\n\t\t\tthis.#config,\n\t\t\tthis.#inlineClient,\n\t\t\tthis,\n\t\t\tactorId,\n\t\t);\n\t}\n\n\t/**\n\t * Get the current storage directory path\n\t */\n\tget storagePath(): string {\n\t\treturn this.#state.storagePath;\n\t}\n\n\tgetContext(_actorId: string): ActorDriverContext {\n\t\treturn {};\n\t}\n\n\tasync kvBatchPut(\n\t\tactorId: string,\n\t\tentries: [Uint8Array, Uint8Array][],\n\t): Promise<void> {\n\t\tawait this.#state.kvBatchPut(actorId, entries);\n\t}\n\n\tasync kvBatchGet(\n\t\tactorId: string,\n\t\tkeys: Uint8Array[],\n\t): Promise<(Uint8Array | null)[]> {\n\t\treturn await this.#state.kvBatchGet(actorId, keys);\n\t}\n\n\tasync kvBatchDelete(actorId: string, keys: Uint8Array[]): Promise<void> {\n\t\tawait this.#state.kvBatchDelete(actorId, keys);\n\t}\n\n\tasync kvListPrefix(\n\t\tactorId: string,\n\t\tprefix: Uint8Array,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\treturn await this.#state.kvListPrefix(actorId, prefix);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#state.setActorAlarm(actor.id, timestamp);\n\t}\n\n\tgetDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#state.createDatabase(actorId);\n\t}\n\n\tstartSleep(actorId: string): void {\n\t\t// Spawns the sleepActor promise\n\t\tthis.#state.sleepActor(actorId);\n\t}\n\n\tasync startDestroy(actorId: string): Promise<void> {\n\t\tawait this.#state.destroyActor(actorId);\n\t}\n}\n","import invariant from \"invariant\";\nimport { lookupInRegistry } from \"@/actor/definition\";\nimport { ActorDuplicateKey } from \"@/actor/errors\";\nimport type { AnyActorInstance } from \"@/actor/instance/mod\";\nimport type { ActorKey } from \"@/actor/mod\";\nimport type { AnyClient } from \"@/client/client\";\nimport { type ActorDriver, getInitialActorKvState } from \"@/driver-helpers/mod\";\nimport type * as schema from \"@/schemas/file-system-driver/mod\";\nimport {\n\tACTOR_ALARM_VERSIONED,\n\tACTOR_STATE_VERSIONED,\n\tCURRENT_VERSION as FILE_SYSTEM_DRIVER_CURRENT_VERSION,\n} from \"@/schemas/file-system-driver/versioned\";\nimport {\n\tarrayBuffersEqual,\n\tbufferToArrayBuffer,\n\ttype LongTimeoutHandle,\n\tpromiseWithResolvers,\n\tsetLongTimeout,\n\tstringifyError,\n} from \"@/utils\";\nimport {\n\tgetNodeCrypto,\n\tgetNodeFs,\n\tgetNodeFsSync,\n\tgetNodePath,\n} from \"@/utils/node\";\nimport { logger } from \"./log\";\nimport {\n\tensureDirectoryExists,\n\tensureDirectoryExistsSync,\n\tgetStoragePath,\n} from \"./utils\";\nimport { RegistryConfig } from \"@/registry/config\";\n\n// Actor handler to track running instances\n\nenum ActorLifecycleState {\n\tNONEXISTENT, // Entry exists but actor not yet created\n\tAWAKE, // Actor is running normally\n\tSTARTING_SLEEP, // Actor is being put to sleep\n\tSTARTING_DESTROY, // Actor is being destroyed\n\tDESTROYED, // Actor was destroyed, should not be recreated\n}\n\ninterface ActorEntry {\n\tid: string;\n\n\tstate?: schema.ActorState;\n\n\t/** Promise for loading the actor state. */\n\tloadPromise?: Promise<ActorEntry>;\n\n\tactor?: AnyActorInstance;\n\t/** Promise for starting the actor. */\n\tstartPromise?: ReturnType<typeof promiseWithResolvers<void>>;\n\n\talarmTimeout?: LongTimeoutHandle;\n\t/** The timestamp currently scheduled for this actor's alarm (ms since epoch). */\n\talarmTimestamp?: number;\n\n\t/** Resolver for pending write operations that need to be notified when any write completes */\n\tpendingWriteResolver?: PromiseWithResolvers<void>;\n\n\tlifecycleState: ActorLifecycleState;\n\n\t// TODO: This might make sense to move in to actorstate, but we have a\n\t// single reader/writer so it's not an issue\n\t/** Generation of this actor when creating/destroying. */\n\tgeneration: string;\n}\n\n/**\n * Global state for the file system driver\n */\nexport class FileSystemGlobalState {\n\t#storagePath: string;\n\t#stateDir: string;\n\t#dbsDir: string;\n\t#alarmsDir: string;\n\n\t#persist: boolean;\n\n\t// IMPORTANT: Never delete from this map. Doing so will result in race\n\t// conditions since the actor generation will cease to be tracked\n\t// correctly. Always increment generation if a new actor is created.\n\t#actors = new Map<string, ActorEntry>();\n\n\t#actorCountOnStartup: number = 0;\n\n\t#runnerParams?: {\n\t\tconfig: RegistryConfig;\n\t\tinlineClient: AnyClient;\n\t\tactorDriver: ActorDriver;\n\t};\n\n\tget persist(): boolean {\n\t\treturn this.#persist;\n\t}\n\n\tget storagePath() {\n\t\treturn this.#storagePath;\n\t}\n\n\tget actorCountOnStartup() {\n\t\treturn this.#actorCountOnStartup;\n\t}\n\n\tconstructor(persist: boolean = true, customPath?: string) {\n\t\tthis.#persist = persist;\n\t\tthis.#storagePath = persist ? (customPath ?? getStoragePath()) : \"/tmp\";\n\t\tconst path = getNodePath();\n\t\tthis.#stateDir = path.join(this.#storagePath, \"state\");\n\t\tthis.#dbsDir = path.join(this.#storagePath, \"databases\");\n\t\tthis.#alarmsDir = path.join(this.#storagePath, \"alarms\");\n\n\t\tif (this.#persist) {\n\t\t\t// Ensure storage directories exist synchronously during initialization\n\t\t\tensureDirectoryExistsSync(this.#stateDir);\n\t\t\tensureDirectoryExistsSync(this.#dbsDir);\n\t\t\tensureDirectoryExistsSync(this.#alarmsDir);\n\n\t\t\ttry {\n\t\t\t\tconst fsSync = getNodeFsSync();\n\t\t\t\tconst actorIds = fsSync.readdirSync(this.#stateDir);\n\t\t\t\tthis.#actorCountOnStartup = actorIds.length;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({ msg: \"failed to count actors\", error });\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"file system driver ready\",\n\t\t\t\tdir: this.#storagePath,\n\t\t\t\tactorCount: this.#actorCountOnStartup,\n\t\t\t});\n\n\t\t\t// Cleanup stale temp files on startup\n\t\t\ttry {\n\t\t\t\tthis.#cleanupTempFilesSync();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to cleanup temp files\",\n\t\t\t\t\terror: err,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tlogger().debug({ msg: \"memory driver ready\" });\n\t\t}\n\t}\n\n\tgetActorStatePath(actorId: string): string {\n\t\treturn getNodePath().join(this.#stateDir, actorId);\n\t}\n\n\tgetActorDbPath(actorId: string): string {\n\t\treturn getNodePath().join(this.#dbsDir, `${actorId}.db`);\n\t}\n\n\tgetActorAlarmPath(actorId: string): string {\n\t\treturn getNodePath().join(this.#alarmsDir, actorId);\n\t}\n\n\tasync *getActorsIterator(params: {\n\t\tcursor?: string;\n\t}): AsyncGenerator<schema.ActorState> {\n\t\tlet actorIds = Array.from(this.#actors.keys()).sort();\n\n\t\t// Check if state directory exists first\n\t\tconst fsSync = getNodeFsSync();\n\t\tif (fsSync.existsSync(this.#stateDir)) {\n\t\t\tactorIds = fsSync\n\t\t\t\t.readdirSync(this.#stateDir)\n\t\t\t\t.filter((id) => !id.includes(\".tmp\"))\n\t\t\t\t.sort();\n\t\t}\n\n\t\tconst startIndex = params.cursor\n\t\t\t? actorIds.indexOf(params.cursor) + 1\n\t\t\t: 0;\n\n\t\tfor (let i = startIndex; i < actorIds.length; i++) {\n\t\t\tconst actorId = actorIds[i];\n\t\t\tif (!actorId) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst state = await this.loadActorStateOrError(actorId);\n\t\t\t\tyield state;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to load actor state\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Ensures an entry exists for this actor.\n\t *\n\t * Used for #createActor and #loadActor.\n\t */\n\t#upsertEntry(actorId: string): ActorEntry {\n\t\tlet entry = this.#actors.get(actorId);\n\t\tif (entry) {\n\t\t\treturn entry;\n\t\t}\n\n\t\tentry = {\n\t\t\tid: actorId,\n\t\t\tlifecycleState: ActorLifecycleState.NONEXISTENT,\n\t\t\tgeneration: crypto.randomUUID(),\n\t\t};\n\t\tthis.#actors.set(actorId, entry);\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Creates a new actor and writes to file system.\n\t */\n\tasync createActor(\n\t\tactorId: string,\n\t\tname: string,\n\t\tkey: ActorKey,\n\t\tinput: unknown | undefined,\n\t): Promise<ActorEntry> {\n\t\t// TODO: Does not check if actor already exists on fs\n\n\t\tconst entry = this.#upsertEntry(actorId);\n\n\t\t// Check if actor already exists (has state or is being stopped)\n\t\tif (entry.state) {\n\t\t\tthrow new ActorDuplicateKey(name, key);\n\t\t}\n\t\tif (this.isActorStopping(actorId)) {\n\t\t\tthrow new Error(`Actor ${actorId} is stopping`);\n\t\t}\n\n\t\t// If actor was destroyed, reset to NONEXISTENT and increment generation\n\t\tif (entry.lifecycleState === ActorLifecycleState.DESTROYED) {\n\t\t\tentry.lifecycleState = ActorLifecycleState.NONEXISTENT;\n\t\t\tentry.generation = crypto.randomUUID();\n\t\t}\n\n\t\t// Initialize storage\n\t\tconst kvStorage: schema.ActorKvEntry[] = [];\n\t\tconst initialKvState = getInitialActorKvState(input);\n\t\tfor (const [key, value] of initialKvState) {\n\t\t\tkvStorage.push({\n\t\t\t\tkey: bufferToArrayBuffer(key),\n\t\t\t\tvalue: bufferToArrayBuffer(value),\n\t\t\t});\n\t\t}\n\n\t\t// Initialize metadata\n\t\tentry.state = {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\tcreatedAt: BigInt(Date.now()),\n\t\t\tkvStorage,\n\t\t\tstartTs: null,\n\t\t\tconnectableTs: null,\n\t\t\tsleepTs: null,\n\t\t\tdestroyTs: null,\n\t\t};\n\t\tentry.lifecycleState = ActorLifecycleState.AWAKE;\n\n\t\tawait this.writeActor(actorId, entry.generation, entry.state);\n\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Loads the actor from disk or returns the existing actor entry. This will return an entry even if the actor does not actually exist.\n\t */\n\tasync loadActor(actorId: string): Promise<ActorEntry> {\n\t\tconst entry = this.#upsertEntry(actorId);\n\n\t\t// Check if destroyed - don't load from disk\n\t\tif (entry.lifecycleState === ActorLifecycleState.DESTROYED) {\n\t\t\treturn entry;\n\t\t}\n\n\t\t// Check if already loaded\n\t\tif (entry.state) {\n\t\t\treturn entry;\n\t\t}\n\n\t\t// If not persisted, then don't load from FS\n\t\tif (!this.#persist) {\n\t\t\treturn entry;\n\t\t}\n\n\t\t// If state is currently being loaded, wait for it\n\t\tif (entry.loadPromise) {\n\t\t\tawait entry.loadPromise;\n\t\t\treturn entry;\n\t\t}\n\n\t\t// Start loading state\n\t\tentry.loadPromise = this.loadActorState(entry);\n\t\treturn entry.loadPromise;\n\t}\n\n\tprivate async loadActorState(entry: ActorEntry) {\n\t\tconst stateFilePath = this.getActorStatePath(entry.id);\n\n\t\t// Read & parse file\n\t\ttry {\n\t\t\tconst fs = getNodeFs();\n\t\t\tconst stateData = await fs.readFile(stateFilePath);\n\n\t\t\t// Cache the loaded state in handler\n\t\t\tentry.state = ACTOR_STATE_VERSIONED.deserializeWithEmbeddedVersion(\n\t\t\t\tnew Uint8Array(stateData),\n\t\t\t);\n\n\t\t\treturn entry;\n\t\t} catch (innerError: any) {\n\t\t\t// File does not exist, meaning the actor does not exist\n\t\t\tif (innerError.code === \"ENOENT\") {\n\t\t\t\tentry.loadPromise = undefined;\n\t\t\t\treturn entry;\n\t\t\t}\n\n\t\t\t// For other errors, throw\n\t\t\tconst error = new Error(\n\t\t\t\t`Failed to load actor state: ${innerError}`,\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync loadOrCreateActor(\n\t\tactorId: string,\n\t\tname: string,\n\t\tkey: ActorKey,\n\t\tinput: unknown | undefined,\n\t): Promise<ActorEntry> {\n\t\t// Attempt to load actor\n\t\tconst entry = await this.loadActor(actorId);\n\n\t\t// If no state for this actor, then create & write state\n\t\tif (!entry.state) {\n\t\t\tif (this.isActorStopping(actorId)) {\n\t\t\t\tthrow new Error(`Actor ${actorId} stopping`);\n\t\t\t}\n\n\t\t\t// If actor was destroyed, reset to NONEXISTENT and increment generation\n\t\t\tif (entry.lifecycleState === ActorLifecycleState.DESTROYED) {\n\t\t\t\tentry.lifecycleState = ActorLifecycleState.NONEXISTENT;\n\t\t\t\tentry.generation = crypto.randomUUID();\n\t\t\t}\n\n\t\t\t// Initialize kvStorage with the initial persist data\n\t\t\tconst kvStorage: schema.ActorKvEntry[] = [];\n\t\t\tconst initialKvState = getInitialActorKvState(input);\n\t\t\tfor (const [key, value] of initialKvState) {\n\t\t\t\tkvStorage.push({\n\t\t\t\t\tkey: bufferToArrayBuffer(key),\n\t\t\t\t\tvalue: bufferToArrayBuffer(value),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tentry.state = {\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey: key as readonly string[],\n\t\t\t\tcreatedAt: BigInt(Date.now()),\n\t\t\t\tkvStorage,\n\t\t\t\tstartTs: null,\n\t\t\t\tconnectableTs: null,\n\t\t\t\tsleepTs: null,\n\t\t\t\tdestroyTs: null,\n\t\t\t};\n\t\t\tawait this.writeActor(actorId, entry.generation, entry.state);\n\t\t}\n\t\treturn entry;\n\t}\n\n\tasync sleepActor(actorId: string) {\n\t\tinvariant(\n\t\t\tthis.#persist,\n\t\t\t\"cannot sleep actor with memory driver, must use file system driver\",\n\t\t);\n\n\t\t// Get the actor. We upsert it even though we're about to destroy it so we have a lock on flagging `destroying` as true.\n\t\tconst actor = this.#upsertEntry(actorId);\n\t\tinvariant(actor, `tried to sleep ${actorId}, does not exist`);\n\n\t\t// Check if already destroying\n\t\tif (this.isActorStopping(actorId)) {\n\t\t\treturn;\n\t\t}\n\t\tactor.lifecycleState = ActorLifecycleState.STARTING_SLEEP;\n\n\t\t// Wait for actor to fully start before stopping it to avoid race conditions\n\t\tif (actor.loadPromise) await actor.loadPromise.catch();\n\t\tif (actor.startPromise?.promise)\n\t\t\tawait actor.startPromise.promise.catch();\n\n\t\t// Update state with sleep timestamp\n\t\tif (actor.state) {\n\t\t\tactor.state = {\n\t\t\t\t...actor.state,\n\t\t\t\tsleepTs: BigInt(Date.now()),\n\t\t\t};\n\t\t\tawait this.writeActor(actorId, actor.generation, actor.state);\n\t\t}\n\n\t\t// Stop actor\n\t\tinvariant(actor.actor, \"actor should be loaded\");\n\t\tawait actor.actor.onStop(\"sleep\");\n\n\t\t// Remove from map after stop is complete\n\t\tthis.#actors.delete(actorId);\n\t}\n\n\tasync destroyActor(actorId: string) {\n\t\t// Get the actor. We upsert it even though we're about to destroy it so we have a lock on flagging `destroying` as true.\n\t\tconst actor = this.#upsertEntry(actorId);\n\n\t\t// If actor is loaded, stop it first\n\t\t// Check if already destroying\n\t\tif (this.isActorStopping(actorId)) {\n\t\t\treturn;\n\t\t}\n\t\tactor.lifecycleState = ActorLifecycleState.STARTING_DESTROY;\n\n\t\t// Wait for actor to fully start before stopping it to avoid race conditions\n\t\tif (actor.loadPromise) await actor.loadPromise.catch();\n\t\tif (actor.startPromise?.promise)\n\t\t\tawait actor.startPromise.promise.catch();\n\n\t\t// Update state with destroy timestamp\n\t\tif (actor.state) {\n\t\t\tactor.state = {\n\t\t\t\t...actor.state,\n\t\t\t\tdestroyTs: BigInt(Date.now()),\n\t\t\t};\n\t\t\tawait this.writeActor(actorId, actor.generation, actor.state);\n\t\t}\n\n\t\t// Stop actor if it's running\n\t\tif (actor.actor) {\n\t\t\tawait actor.actor.onStop(\"destroy\");\n\t\t}\n\n\t\t// Clear alarm timeout if exists\n\t\tif (actor.alarmTimeout) {\n\t\t\tactor.alarmTimeout.abort();\n\t\t}\n\n\t\t// Delete persisted files if using file system driver\n\t\tif (this.#persist) {\n\t\t\tconst fs = getNodeFs();\n\n\t\t\t// Delete all actor files in parallel\n\t\t\tawait Promise.all([\n\t\t\t\t// Delete actor state file\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.unlink(this.getActorStatePath(actorId));\n\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\tif (err?.code !== \"ENOENT\") {\n\t\t\t\t\t\t\tlogger().error({\n\t\t\t\t\t\t\t\tmsg: \"failed to delete actor state file\",\n\t\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})(),\n\t\t\t\t// Delete actor database file\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.unlink(this.getActorDbPath(actorId));\n\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\tif (err?.code !== \"ENOENT\") {\n\t\t\t\t\t\t\tlogger().error({\n\t\t\t\t\t\t\t\tmsg: \"failed to delete actor database file\",\n\t\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})(),\n\t\t\t\t// Delete actor alarm file\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fs.unlink(this.getActorAlarmPath(actorId));\n\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\tif (err?.code !== \"ENOENT\") {\n\t\t\t\t\t\t\tlogger().error({\n\t\t\t\t\t\t\t\tmsg: \"failed to delete actor alarm file\",\n\t\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})(),\n\t\t\t]);\n\t\t}\n\n\t\t// Reset the entry\n\t\t//\n\t\t// Do not remove entry in order to avoid race condition with\n\t\t// destroying. Next actor creation will increment the generation.\n\t\tactor.state = undefined;\n\t\tactor.loadPromise = undefined;\n\t\tactor.actor = undefined;\n\t\tactor.startPromise = undefined;\n\t\tactor.alarmTimeout = undefined;\n\t\tactor.alarmTimeout = undefined;\n\t\tactor.pendingWriteResolver = undefined;\n\t\tactor.lifecycleState = ActorLifecycleState.DESTROYED;\n\t}\n\n\t/**\n\t * Save actor state to disk.\n\t */\n\tasync writeActor(\n\t\tactorId: string,\n\t\tgeneration: string,\n\t\tstate: schema.ActorState,\n\t): Promise<void> {\n\t\tif (!this.#persist) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst entry = this.#actors.get(actorId);\n\t\tinvariant(entry, \"actor entry does not exist\");\n\n\t\tawait this.#performWrite(actorId, generation, state);\n\t}\n\n\tisGenerationCurrentAndNotDestroyed(\n\t\tactorId: string,\n\t\tgeneration: string,\n\t): boolean {\n\t\tconst entry = this.#upsertEntry(actorId);\n\t\tif (!entry) return false;\n\t\treturn (\n\t\t\tentry.generation === generation &&\n\t\t\tentry.lifecycleState !== ActorLifecycleState.STARTING_DESTROY\n\t\t);\n\t}\n\n\tisActorStopping(actorId: string) {\n\t\tconst entry = this.#upsertEntry(actorId);\n\t\tif (!entry) return false;\n\t\treturn (\n\t\t\tentry.lifecycleState === ActorLifecycleState.STARTING_SLEEP ||\n\t\t\tentry.lifecycleState === ActorLifecycleState.STARTING_DESTROY\n\t\t);\n\t}\n\n\tasync setActorAlarm(actorId: string, timestamp: number) {\n\t\tconst entry = this.#actors.get(actorId);\n\t\tinvariant(entry, \"actor entry does not exist\");\n\n\t\t// Track generation of the actor when the write started to detect\n\t\t// destroy/create race condition\n\t\tconst writeGeneration = entry.generation;\n\t\tif (this.isActorStopping(actorId)) {\n\t\t\tlogger().info(\"skipping set alarm since actor stopping\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Persist alarm to disk\n\t\tif (this.#persist) {\n\t\t\tconst alarmPath = this.getActorAlarmPath(actorId);\n\t\t\tconst crypto = getNodeCrypto();\n\t\t\tconst tempPath = `${alarmPath}.tmp.${crypto.randomUUID()}`;\n\t\t\ttry {\n\t\t\t\tconst path = getNodePath();\n\t\t\t\tawait ensureDirectoryExists(path.dirname(alarmPath));\n\t\t\t\tconst alarmData: schema.ActorAlarm = {\n\t\t\t\t\tactorId,\n\t\t\t\t\ttimestamp: BigInt(timestamp),\n\t\t\t\t};\n\t\t\t\tconst data = ACTOR_ALARM_VERSIONED.serializeWithEmbeddedVersion(\n\t\t\t\t\talarmData,\n\t\t\t\t\tFILE_SYSTEM_DRIVER_CURRENT_VERSION,\n\t\t\t\t);\n\t\t\t\tconst fs = getNodeFs();\n\t\t\t\tawait fs.writeFile(tempPath, data);\n\n\t\t\t\tif (\n\t\t\t\t\t!this.isGenerationCurrentAndNotDestroyed(\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\twriteGeneration,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tlogger().debug(\n\t\t\t\t\t\t\"skipping writing alarm since actor destroying or new generation\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait fs.rename(tempPath, alarmPath);\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tconst fs = getNodeFs();\n\t\t\t\t\tawait fs.unlink(tempPath);\n\t\t\t\t} catch {}\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to write alarm\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t\tthrow new Error(`Failed to write alarm: ${error}`);\n\t\t\t}\n\t\t}\n\n\t\t// Schedule timeout\n\t\tthis.#scheduleAlarmTimeout(actorId, timestamp);\n\t}\n\n\t/**\n\t * Perform the actual write operation with atomic writes\n\t */\n\tasync #performWrite(\n\t\tactorId: string,\n\t\tgeneration: string,\n\t\tstate: schema.ActorState,\n\t): Promise<void> {\n\t\tconst dataPath = this.getActorStatePath(actorId);\n\t\t// Generate unique temp filename to prevent any race conditions\n\t\tconst crypto = getNodeCrypto();\n\t\tconst tempPath = `${dataPath}.tmp.${crypto.randomUUID()}`;\n\n\t\ttry {\n\t\t\t// Create directory if needed\n\t\t\tconst path = getNodePath();\n\t\t\tawait ensureDirectoryExists(path.dirname(dataPath));\n\n\t\t\t// Convert to BARE types for serialization\n\t\t\tconst bareState: schema.ActorState = {\n\t\t\t\tactorId: state.actorId,\n\t\t\t\tname: state.name,\n\t\t\t\tkey: state.key,\n\t\t\t\tcreatedAt: state.createdAt,\n\t\t\t\tkvStorage: state.kvStorage,\n\t\t\t\tstartTs: state.startTs,\n\t\t\t\tconnectableTs: state.connectableTs,\n\t\t\t\tsleepTs: state.sleepTs,\n\t\t\t\tdestroyTs: state.destroyTs,\n\t\t\t};\n\n\t\t\t// Perform atomic write\n\t\t\tconst serializedState =\n\t\t\t\tACTOR_STATE_VERSIONED.serializeWithEmbeddedVersion(\n\t\t\t\t\tbareState,\n\t\t\t\t\tFILE_SYSTEM_DRIVER_CURRENT_VERSION,\n\t\t\t\t);\n\t\t\tconst fs = getNodeFs();\n\t\t\tawait fs.writeFile(tempPath, serializedState);\n\n\t\t\tif (!this.isGenerationCurrentAndNotDestroyed(actorId, generation)) {\n\t\t\t\tlogger().debug(\n\t\t\t\t\t\"skipping writing alarm since actor destroying or new generation\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait fs.rename(tempPath, dataPath);\n\t\t} catch (error) {\n\t\t\t// Cleanup temp file on error\n\t\t\ttry {\n\t\t\t\tconst fs = getNodeFs();\n\t\t\t\tawait fs.unlink(tempPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"failed to save actor state\",\n\t\t\t\tactorId,\n\t\t\t\terror,\n\t\t\t});\n\t\t\tthrow new Error(`Failed to save actor state: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Call this method after the actor driver has been initiated.\n\t *\n\t * This will trigger all initial alarms from the file system.\n\t *\n\t * This needs to be sync since DriverConfig.actor is sync\n\t */\n\tonRunnerStart(\n\t\tconfig: RegistryConfig,\n\t\tinlineClient: AnyClient,\n\t\tactorDriver: ActorDriver,\n\t) {\n\t\tif (this.#runnerParams) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Save runner params for future use\n\t\tthis.#runnerParams = {\n\t\t\tconfig: config,\n\t\t\tinlineClient,\n\t\t\tactorDriver,\n\t\t};\n\n\t\t// Load alarms from disk and schedule timeouts\n\t\ttry {\n\t\t\tthis.#loadAlarmsSync();\n\t\t} catch (err) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"failed to load alarms on startup\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync startActor(\n\t\tconfig: RegistryConfig,\n\t\tinlineClient: AnyClient,\n\t\tactorDriver: ActorDriver,\n\t\tactorId: string,\n\t): Promise<AnyActorInstance> {\n\t\t// Get the actor metadata\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor does not exist and cannot be started: \"${actorId}\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Actor already starting\n\t\tif (entry.startPromise) {\n\t\t\tawait entry.startPromise.promise;\n\t\t\tinvariant(entry.actor, \"actor should have loaded\");\n\t\t\treturn entry.actor;\n\t\t}\n\n\t\t// Actor already loaded\n\t\tif (entry.actor) {\n\t\t\treturn entry.actor;\n\t\t}\n\n\t\t// Create start promise\n\t\tentry.startPromise = promiseWithResolvers();\n\n\t\ttry {\n\t\t\t// Create actor\n\t\t\tconst definition = lookupInRegistry(\n\t\t\t\tconfig,\n\t\t\t\tentry.state.name,\n\t\t\t);\n\t\t\tentry.actor = definition.instantiate();\n\n\t\t\t// Start actor\n\t\t\tawait entry.actor.start(\n\t\t\t\tactorDriver,\n\t\t\t\tinlineClient,\n\t\t\t\tactorId,\n\t\t\t\tentry.state.name,\n\t\t\t\tentry.state.key as string[],\n\t\t\t\t\"unknown\",\n\t\t\t);\n\n\t\t\t// Update state with start timestamp\n\t\t\t// NOTE: connectableTs is always in sync with startTs since actors become connectable immediately after starting\n\t\t\tconst now = BigInt(Date.now());\n\t\t\tentry.state = {\n\t\t\t\t...entry.state,\n\t\t\t\tstartTs: now,\n\t\t\t\tconnectableTs: now,\n\t\t\t\tsleepTs: null, // Clear sleep timestamp when actor wakes up\n\t\t\t};\n\t\t\tawait this.writeActor(actorId, entry.generation, entry.state);\n\n\t\t\t// Finish\n\t\t\tentry.startPromise.resolve();\n\t\t\tentry.startPromise = undefined;\n\n\t\t\treturn entry.actor;\n\t\t} catch (innerError) {\n\t\t\tconst error = new Error(\n\t\t\t\t`Failed to start actor ${actorId}: ${innerError}`,\n\t\t\t\t{ cause: innerError },\n\t\t\t);\n\t\t\tentry.startPromise?.reject(error);\n\t\t\tentry.startPromise = undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync loadActorStateOrError(actorId: string): Promise<schema.ActorState> {\n\t\tconst state = (await this.loadActor(actorId)).state;\n\t\tif (!state) throw new Error(`Actor does not exist: ${actorId}`);\n\t\treturn state;\n\t}\n\n\tgetActorOrError(actorId: string): ActorEntry {\n\t\tconst entry = this.#actors.get(actorId);\n\t\tif (!entry) throw new Error(`No entry for actor: ${actorId}`);\n\t\treturn entry;\n\t}\n\n\tasync createDatabase(actorId: string): Promise<string | undefined> {\n\t\treturn this.getActorDbPath(actorId);\n\t}\n\n\t/**\n\t * Load all persisted alarms from disk and schedule their timers.\n\t */\n\t#loadAlarmsSync(): void {\n\t\ttry {\n\t\t\tconst fsSync = getNodeFsSync();\n\t\t\tconst files = fsSync.existsSync(this.#alarmsDir)\n\t\t\t\t? fsSync.readdirSync(this.#alarmsDir)\n\t\t\t\t: [];\n\t\t\tfor (const file of files) {\n\t\t\t\t// Skip temp files\n\t\t\t\tif (file.includes(\".tmp.\")) continue;\n\t\t\t\tconst path = getNodePath();\n\t\t\t\tconst fullPath = path.join(this.#alarmsDir, file);\n\t\t\t\ttry {\n\t\t\t\t\tconst buf = fsSync.readFileSync(fullPath);\n\t\t\t\t\tconst alarmData =\n\t\t\t\t\t\tACTOR_ALARM_VERSIONED.deserializeWithEmbeddedVersion(\n\t\t\t\t\t\t\tnew Uint8Array(buf),\n\t\t\t\t\t\t);\n\t\t\t\t\tconst timestamp = Number(alarmData.timestamp);\n\t\t\t\t\tif (Number.isFinite(timestamp)) {\n\t\t\t\t\t\tthis.#scheduleAlarmTimeout(\n\t\t\t\t\t\t\talarmData.actorId,\n\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"invalid alarm file contents\",\n\t\t\t\t\t\t\tfile,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"failed to read alarm file\",\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"failed to list alarms directory\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Schedule an alarm timer for an actor without writing to disk.\n\t */\n\t#scheduleAlarmTimeout(actorId: string, timestamp: number) {\n\t\tconst entry = this.#upsertEntry(actorId);\n\n\t\t// If there's already an earlier alarm scheduled, do not override it.\n\t\tif (\n\t\t\tentry.alarmTimestamp !== undefined &&\n\t\t\ttimestamp >= entry.alarmTimestamp\n\t\t) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"skipping alarm schedule (later than existing)\",\n\t\t\t\tactorId,\n\t\t\t\ttimestamp,\n\t\t\t\tcurrent: entry.alarmTimestamp,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tlogger().debug({ msg: \"scheduling alarm\", actorId, timestamp });\n\n\t\t// Cancel existing timeout and update the current scheduled timestamp\n\t\tentry.alarmTimeout?.abort();\n\t\tentry.alarmTimestamp = timestamp;\n\n\t\tconst delay = Math.max(0, timestamp - Date.now());\n\t\tentry.alarmTimeout = setLongTimeout(async () => {\n\t\t\t// Clear currently scheduled timestamp as this alarm is firing now\n\t\t\tentry.alarmTimestamp = undefined;\n\t\t\t// On trigger: remove persisted alarm file\n\t\t\tif (this.#persist) {\n\t\t\t\ttry {\n\t\t\t\t\tconst fs = getNodeFs();\n\t\t\t\t\tawait fs.unlink(this.getActorAlarmPath(actorId));\n\t\t\t\t} catch (err: any) {\n\t\t\t\t\tif (err?.code !== \"ENOENT\") {\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"failed to remove alarm file\",\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tlogger().debug({ msg: \"triggering alarm\", actorId, timestamp });\n\n\t\t\t\t// Ensure actor state exists and start actor if needed\n\t\t\t\tconst loaded = await this.loadActor(actorId);\n\t\t\t\tif (!loaded.state)\n\t\t\t\t\tthrow new Error(`Actor does not exist: ${actorId}`);\n\n\t\t\t\t// Start actor if not already running\n\t\t\t\tconst runnerParams = this.#runnerParams;\n\t\t\t\tinvariant(runnerParams, \"missing runner params\");\n\t\t\t\tif (!loaded.actor) {\n\t\t\t\t\tawait this.startActor(\n\t\t\t\t\t\trunnerParams.config,\n\t\t\t\t\t\trunnerParams.inlineClient,\n\t\t\t\t\t\trunnerParams.actorDriver,\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tinvariant(loaded.actor, \"actor should be loaded after wake\");\n\t\t\t\tawait loaded.actor.onAlarm();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to handle alarm\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\t/**\n\t * Cleanup stale temp files on startup (synchronous)\n\t */\n\t#cleanupTempFilesSync(): void {\n\t\ttry {\n\t\t\tconst fsSync = getNodeFsSync();\n\t\t\tconst files = fsSync.readdirSync(this.#stateDir);\n\t\t\tconst tempFiles = files.filter((f) => f.includes(\".tmp.\"));\n\n\t\t\tconst oneHourAgo = Date.now() - 3600000; // 1 hour in ms\n\n\t\t\tfor (const tempFile of tempFiles) {\n\t\t\t\ttry {\n\t\t\t\t\tconst path = getNodePath();\n\t\t\t\t\tconst fullPath = path.join(this.#stateDir, tempFile);\n\t\t\t\t\tconst stat = fsSync.statSync(fullPath);\n\n\t\t\t\t\t// Remove if older than 1 hour\n\t\t\t\t\tif (stat.mtimeMs < oneHourAgo) {\n\t\t\t\t\t\tfsSync.unlinkSync(fullPath);\n\t\t\t\t\t\tlogger().info({\n\t\t\t\t\t\t\tmsg: \"cleaned up stale temp file\",\n\t\t\t\t\t\t\tfile: tempFile,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"failed to cleanup temp file\",\n\t\t\t\t\t\tfile: tempFile,\n\t\t\t\t\t\terror: err,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"failed to read actors directory for cleanup\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Batch put KV entries for an actor.\n\t */\n\tasync kvBatchPut(\n\t\tactorId: string,\n\t\tentries: [Uint8Array, Uint8Array][],\n\t): Promise<void> {\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tif (this.isActorStopping(actorId)) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Actor ${actorId} state not loaded`);\n\t\t\t}\n\t\t}\n\n\t\t// Create a mutable copy of kvStorage\n\t\tconst newKvStorage = [...entry.state.kvStorage];\n\n\t\t// Update kvStorage with new entries\n\t\tfor (const [key, value] of entries) {\n\t\t\t// Find existing entry with the same key\n\t\t\tconst existingIndex = newKvStorage.findIndex((e) =>\n\t\t\t\tarrayBuffersEqual(e.key, bufferToArrayBuffer(key)),\n\t\t\t);\n\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\t// Replace existing entry with new one\n\t\t\t\tnewKvStorage[existingIndex] = {\n\t\t\t\t\tkey: bufferToArrayBuffer(key),\n\t\t\t\t\tvalue: bufferToArrayBuffer(value),\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// Add new entry\n\t\t\t\tnewKvStorage.push({\n\t\t\t\t\tkey: bufferToArrayBuffer(key),\n\t\t\t\t\tvalue: bufferToArrayBuffer(value),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Update state with new kvStorage\n\t\tentry.state = {\n\t\t\t...entry.state,\n\t\t\tkvStorage: newKvStorage,\n\t\t};\n\n\t\t// Save state to disk\n\t\tawait this.writeActor(actorId, entry.generation, entry.state);\n\t}\n\n\t/**\n\t * Batch get KV entries for an actor.\n\t */\n\tasync kvBatchGet(\n\t\tactorId: string,\n\t\tkeys: Uint8Array[],\n\t): Promise<(Uint8Array | null)[]> {\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tif (this.isActorStopping(actorId)) {\n\t\t\t\tthrow new Error(`Actor ${actorId} is stopping`);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Actor ${actorId} state not loaded`);\n\t\t\t}\n\t\t}\n\n\t\tconst results: (Uint8Array | null)[] = [];\n\t\tfor (const key of keys) {\n\t\t\t// Find entry with the same key\n\t\t\tconst foundEntry = entry.state.kvStorage.find((e) =>\n\t\t\t\tarrayBuffersEqual(e.key, bufferToArrayBuffer(key)),\n\t\t\t);\n\n\t\t\tif (foundEntry) {\n\t\t\t\tresults.push(new Uint8Array(foundEntry.value));\n\t\t\t} else {\n\t\t\t\tresults.push(null);\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\t/**\n\t * Batch delete KV entries for an actor.\n\t */\n\tasync kvBatchDelete(actorId: string, keys: Uint8Array[]): Promise<void> {\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tif (this.isActorStopping(actorId)) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Actor ${actorId} state not loaded`);\n\t\t\t}\n\t\t}\n\n\t\t// Create a mutable copy of kvStorage\n\t\tconst newKvStorage = [...entry.state.kvStorage];\n\n\t\t// Delete entries from kvStorage\n\t\tfor (const key of keys) {\n\t\t\tconst indexToDelete = newKvStorage.findIndex((e) =>\n\t\t\t\tarrayBuffersEqual(e.key, bufferToArrayBuffer(key)),\n\t\t\t);\n\n\t\t\tif (indexToDelete >= 0) {\n\t\t\t\tnewKvStorage.splice(indexToDelete, 1);\n\t\t\t}\n\t\t}\n\n\t\t// Update state with new kvStorage\n\t\tentry.state = {\n\t\t\t...entry.state,\n\t\t\tkvStorage: newKvStorage,\n\t\t};\n\n\t\t// Save state to disk\n\t\tawait this.writeActor(actorId, entry.generation, entry.state);\n\t}\n\n\t/**\n\t * List KV entries with a given prefix for an actor.\n\t */\n\tasync kvListPrefix(\n\t\tactorId: string,\n\t\tprefix: Uint8Array,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tif (this.isActorStopping(actorId)) {\n\t\t\t\tthrow new Error(`Actor ${actorId} is destroying`);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Actor ${actorId} state not loaded`);\n\t\t\t}\n\t\t}\n\n\t\tconst results: [Uint8Array, Uint8Array][] = [];\n\t\tfor (const kvEntry of entry.state.kvStorage) {\n\t\t\tconst keyBytes = new Uint8Array(kvEntry.key);\n\t\t\t// Check if key starts with prefix\n\t\t\tif (keyBytes.length >= prefix.length) {\n\t\t\t\tlet hasPrefix = true;\n\t\t\t\tfor (let i = 0; i < prefix.length; i++) {\n\t\t\t\t\tif (keyBytes[i] !== prefix[i]) {\n\t\t\t\t\t\thasPrefix = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hasPrefix) {\n\t\t\t\t\tresults.push([keyBytes, new Uint8Array(kvEntry.value)]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n}\n","import { createVersionedDataHandler } from \"vbare\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport * as v1 from \"../../../dist/schemas/file-system-driver/v1\";\nimport * as v2 from \"../../../dist/schemas/file-system-driver/v2\";\nimport * as v3 from \"../../../dist/schemas/file-system-driver/v3\";\n\nexport const CURRENT_VERSION = 3;\n\n// Converter from v1 to v2\nconst v1ToV2 = (v1State: v1.ActorState): v2.ActorState => {\n\t// Create a new kvStorage list with the legacy persist data\n\tconst kvStorage: v2.ActorKvEntry[] = [];\n\n\t// Store the legacy persist data under key [1]\n\tif (v1State.persistedData) {\n\t\t// Key [1] as Uint8Array\n\t\tconst key = new Uint8Array([1]);\n\t\tkvStorage.push({\n\t\t\tkey: bufferToArrayBuffer(key),\n\t\t\tvalue: v1State.persistedData,\n\t\t});\n\t}\n\n\treturn {\n\t\tactorId: v1State.actorId,\n\t\tname: v1State.name,\n\t\tkey: v1State.key,\n\t\tkvStorage,\n\t\tcreatedAt: v1State.createdAt,\n\t};\n};\n\n// Converter from v2 to v3\nconst v2ToV3 = (v2State: v2.ActorState): v3.ActorState => {\n\t// Migrate from v2 to v3 by adding the new optional timestamp fields\n\treturn {\n\t\tactorId: v2State.actorId,\n\t\tname: v2State.name,\n\t\tkey: v2State.key,\n\t\tkvStorage: v2State.kvStorage,\n\t\tcreatedAt: v2State.createdAt,\n\t\tstartTs: null,\n\t\tconnectableTs: null,\n\t\tsleepTs: null,\n\t\tdestroyTs: null,\n\t};\n};\n\n// Converter from v3 to v2\nconst v3ToV2 = (v3State: v3.ActorState): v2.ActorState => {\n\t// Downgrade from v3 to v2 by removing the timestamp fields\n\treturn {\n\t\tactorId: v3State.actorId,\n\t\tname: v3State.name,\n\t\tkey: v3State.key,\n\t\tkvStorage: v3State.kvStorage,\n\t\tcreatedAt: v3State.createdAt,\n\t};\n};\n\n// Converter from v2 to v1\nconst v2ToV1 = (v2State: v2.ActorState): v1.ActorState => {\n\t// Downgrade from v2 to v1 by converting kvStorage back to persistedData\n\t// Find the persist data entry (key [1])\n\tconst persistDataEntry = v2State.kvStorage.find((entry) => {\n\t\tconst key = new Uint8Array(entry.key);\n\t\treturn key.length === 1 && key[0] === 1;\n\t});\n\n\treturn {\n\t\tactorId: v2State.actorId,\n\t\tname: v2State.name,\n\t\tkey: v2State.key,\n\t\tpersistedData: persistDataEntry?.value || new ArrayBuffer(0),\n\t\tcreatedAt: v2State.createdAt,\n\t};\n};\n\nexport const ACTOR_STATE_VERSIONED = createVersionedDataHandler<v3.ActorState>({\n\tdeserializeVersion: (bytes, version) => {\n\t\tswitch (version) {\n\t\t\tcase 1:\n\t\t\t\treturn v1.decodeActorState(bytes);\n\t\t\tcase 2:\n\t\t\t\treturn v2.decodeActorState(bytes);\n\t\t\tcase 3:\n\t\t\t\treturn v3.decodeActorState(bytes);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown version ${version}`);\n\t\t}\n\t},\n\tserializeVersion: (data, version) => {\n\t\tswitch (version) {\n\t\t\tcase 1:\n\t\t\t\treturn v1.encodeActorState(data as v1.ActorState);\n\t\t\tcase 2:\n\t\t\t\treturn v2.encodeActorState(data as v2.ActorState);\n\t\t\tcase 3:\n\t\t\t\treturn v3.encodeActorState(data as v3.ActorState);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown version ${version}`);\n\t\t}\n\t},\n\tdeserializeConverters: () => [v1ToV2, v2ToV3],\n\tserializeConverters: () => [v3ToV2, v2ToV1],\n});\n\nexport const ACTOR_ALARM_VERSIONED = createVersionedDataHandler<v3.ActorAlarm>({\n\tdeserializeVersion: (bytes, version) => {\n\t\tswitch (version) {\n\t\t\tcase 1:\n\t\t\t\treturn v1.decodeActorAlarm(bytes);\n\t\t\tcase 2:\n\t\t\t\treturn v2.decodeActorAlarm(bytes);\n\t\t\tcase 3:\n\t\t\t\treturn v3.decodeActorAlarm(bytes);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown version ${version}`);\n\t\t}\n\t},\n\tserializeVersion: (data, version) => {\n\t\tswitch (version) {\n\t\t\tcase 1:\n\t\t\t\treturn v1.encodeActorAlarm(data as v1.ActorAlarm);\n\t\t\tcase 2:\n\t\t\t\treturn v2.encodeActorAlarm(data as v2.ActorAlarm);\n\t\t\tcase 3:\n\t\t\t\treturn v3.encodeActorAlarm(data as v3.ActorAlarm);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown version ${version}`);\n\t\t}\n\t},\n\tdeserializeConverters: () => [],\n\tserializeConverters: () => [],\n});\n","// @generated - post-processed by compile-bare.ts\nimport * as bare from \"@rivetkit/bare-ts\"\n\nconst config = /* @__PURE__ */ bare.Config({})\n\nexport type u64 = bigint\nexport type uint = bigint\n\nfunction read0(bc: bare.ByteCursor): readonly string[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [bare.readString(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = bare.readString(bc)\n }\n return result\n}\n\nfunction write0(bc: bare.ByteCursor, x: readonly string[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n bare.writeString(bc, x[i])\n }\n}\n\nexport type ActorState = {\n readonly actorId: string,\n readonly name: string,\n readonly key: readonly string[],\n readonly persistedData: ArrayBuffer,\n readonly createdAt: u64,\n}\n\nexport function readActorState(bc: bare.ByteCursor): ActorState {\n return {\n actorId: bare.readString(bc),\n name: bare.readString(bc),\n key: read0(bc),\n persistedData: bare.readData(bc),\n createdAt: bare.readU64(bc),\n }\n}\n\nexport function writeActorState(bc: bare.ByteCursor, x: ActorState): void {\n bare.writeString(bc, x.actorId)\n bare.writeString(bc, x.name)\n write0(bc, x.key)\n bare.writeData(bc, x.persistedData)\n bare.writeU64(bc, x.createdAt)\n}\n\nexport function encodeActorState(x: ActorState): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorState(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorState(bytes: Uint8Array): ActorState {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorState(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\nexport type ActorAlarm = {\n readonly actorId: string,\n readonly timestamp: uint,\n}\n\nexport function readActorAlarm(bc: bare.ByteCursor): ActorAlarm {\n return {\n actorId: bare.readString(bc),\n timestamp: bare.readUint(bc),\n }\n}\n\nexport function writeActorAlarm(bc: bare.ByteCursor, x: ActorAlarm): void {\n bare.writeString(bc, x.actorId)\n bare.writeUint(bc, x.timestamp)\n}\n\nexport function encodeActorAlarm(x: ActorAlarm): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorAlarm(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorAlarm(bytes: Uint8Array): ActorAlarm {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorAlarm(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\n\nfunction assert(condition: boolean, message?: string): asserts condition {\n if (!condition) throw new Error(message ?? \"Assertion failed\")\n}\n","// @generated - post-processed by compile-bare.ts\nimport * as bare from \"@rivetkit/bare-ts\"\n\nconst config = /* @__PURE__ */ bare.Config({})\n\nexport type u64 = bigint\nexport type uint = bigint\n\nexport type ActorKvEntry = {\n readonly key: ArrayBuffer,\n readonly value: ArrayBuffer,\n}\n\nexport function readActorKvEntry(bc: bare.ByteCursor): ActorKvEntry {\n return {\n key: bare.readData(bc),\n value: bare.readData(bc),\n }\n}\n\nexport function writeActorKvEntry(bc: bare.ByteCursor, x: ActorKvEntry): void {\n bare.writeData(bc, x.key)\n bare.writeData(bc, x.value)\n}\n\nfunction read0(bc: bare.ByteCursor): readonly string[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [bare.readString(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = bare.readString(bc)\n }\n return result\n}\n\nfunction write0(bc: bare.ByteCursor, x: readonly string[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n bare.writeString(bc, x[i])\n }\n}\n\nfunction read1(bc: bare.ByteCursor): readonly ActorKvEntry[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [readActorKvEntry(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = readActorKvEntry(bc)\n }\n return result\n}\n\nfunction write1(bc: bare.ByteCursor, x: readonly ActorKvEntry[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n writeActorKvEntry(bc, x[i])\n }\n}\n\nexport type ActorState = {\n readonly actorId: string,\n readonly name: string,\n readonly key: readonly string[],\n readonly kvStorage: readonly ActorKvEntry[],\n readonly createdAt: u64,\n}\n\nexport function readActorState(bc: bare.ByteCursor): ActorState {\n return {\n actorId: bare.readString(bc),\n name: bare.readString(bc),\n key: read0(bc),\n kvStorage: read1(bc),\n createdAt: bare.readU64(bc),\n }\n}\n\nexport function writeActorState(bc: bare.ByteCursor, x: ActorState): void {\n bare.writeString(bc, x.actorId)\n bare.writeString(bc, x.name)\n write0(bc, x.key)\n write1(bc, x.kvStorage)\n bare.writeU64(bc, x.createdAt)\n}\n\nexport function encodeActorState(x: ActorState): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorState(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorState(bytes: Uint8Array): ActorState {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorState(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\nexport type ActorAlarm = {\n readonly actorId: string,\n readonly timestamp: uint,\n}\n\nexport function readActorAlarm(bc: bare.ByteCursor): ActorAlarm {\n return {\n actorId: bare.readString(bc),\n timestamp: bare.readUint(bc),\n }\n}\n\nexport function writeActorAlarm(bc: bare.ByteCursor, x: ActorAlarm): void {\n bare.writeString(bc, x.actorId)\n bare.writeUint(bc, x.timestamp)\n}\n\nexport function encodeActorAlarm(x: ActorAlarm): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorAlarm(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorAlarm(bytes: Uint8Array): ActorAlarm {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorAlarm(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\n\nfunction assert(condition: boolean, message?: string): asserts condition {\n if (!condition) throw new Error(message ?? \"Assertion failed\")\n}\n","// @generated - post-processed by compile-bare.ts\nimport * as bare from \"@rivetkit/bare-ts\"\n\nconst config = /* @__PURE__ */ bare.Config({})\n\nexport type u64 = bigint\nexport type uint = bigint\n\nexport type ActorKvEntry = {\n readonly key: ArrayBuffer,\n readonly value: ArrayBuffer,\n}\n\nexport function readActorKvEntry(bc: bare.ByteCursor): ActorKvEntry {\n return {\n key: bare.readData(bc),\n value: bare.readData(bc),\n }\n}\n\nexport function writeActorKvEntry(bc: bare.ByteCursor, x: ActorKvEntry): void {\n bare.writeData(bc, x.key)\n bare.writeData(bc, x.value)\n}\n\nfunction read0(bc: bare.ByteCursor): readonly string[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [bare.readString(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = bare.readString(bc)\n }\n return result\n}\n\nfunction write0(bc: bare.ByteCursor, x: readonly string[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n bare.writeString(bc, x[i])\n }\n}\n\nfunction read1(bc: bare.ByteCursor): readonly ActorKvEntry[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [readActorKvEntry(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = readActorKvEntry(bc)\n }\n return result\n}\n\nfunction write1(bc: bare.ByteCursor, x: readonly ActorKvEntry[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n writeActorKvEntry(bc, x[i])\n }\n}\n\nfunction read2(bc: bare.ByteCursor): u64 | null {\n return bare.readBool(bc)\n ? bare.readU64(bc)\n : null\n}\n\nfunction write2(bc: bare.ByteCursor, x: u64 | null): void {\n bare.writeBool(bc, x !== null)\n if (x !== null) {\n bare.writeU64(bc, x)\n }\n}\n\nexport type ActorState = {\n readonly actorId: string,\n readonly name: string,\n readonly key: readonly string[],\n readonly kvStorage: readonly ActorKvEntry[],\n readonly createdAt: u64,\n readonly startTs: u64 | null,\n readonly connectableTs: u64 | null,\n readonly sleepTs: u64 | null,\n readonly destroyTs: u64 | null,\n}\n\nexport function readActorState(bc: bare.ByteCursor): ActorState {\n return {\n actorId: bare.readString(bc),\n name: bare.readString(bc),\n key: read0(bc),\n kvStorage: read1(bc),\n createdAt: bare.readU64(bc),\n startTs: read2(bc),\n connectableTs: read2(bc),\n sleepTs: read2(bc),\n destroyTs: read2(bc),\n }\n}\n\nexport function writeActorState(bc: bare.ByteCursor, x: ActorState): void {\n bare.writeString(bc, x.actorId)\n bare.writeString(bc, x.name)\n write0(bc, x.key)\n write1(bc, x.kvStorage)\n bare.writeU64(bc, x.createdAt)\n write2(bc, x.startTs)\n write2(bc, x.connectableTs)\n write2(bc, x.sleepTs)\n write2(bc, x.destroyTs)\n}\n\nexport function encodeActorState(x: ActorState): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorState(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorState(bytes: Uint8Array): ActorState {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorState(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\nexport type ActorAlarm = {\n readonly actorId: string,\n readonly timestamp: uint,\n}\n\nexport function readActorAlarm(bc: bare.ByteCursor): ActorAlarm {\n return {\n actorId: bare.readString(bc),\n timestamp: bare.readUint(bc),\n }\n}\n\nexport function writeActorAlarm(bc: bare.ByteCursor, x: ActorAlarm): void {\n bare.writeString(bc, x.actorId)\n bare.writeUint(bc, x.timestamp)\n}\n\nexport function encodeActorAlarm(x: ActorAlarm): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorAlarm(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorAlarm(bytes: Uint8Array): ActorAlarm {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorAlarm(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\n\nfunction assert(condition: boolean, message?: string): asserts condition {\n if (!condition) throw new Error(message ?? \"Assertion failed\")\n}\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-fs\");\n}\n","import type { ActorKey } from \"@/actor/mod\";\nimport {\n\tgetNodeCrypto,\n\tgetNodeFs,\n\tgetNodeFsSync,\n\tgetNodeOs,\n\tgetNodePath,\n} from \"@/utils/node\";\n\n/**\n * Generate a deterministic actor ID from name and key\n */\nexport function generateActorId(name: string, key: ActorKey): string {\n\t// Generate deterministic key string\n\tconst jsonString = JSON.stringify([name, key]);\n\n\t// Hash to ensure safe file system names\n\tconst crypto = getNodeCrypto();\n\tconst hash = crypto\n\t\t.createHash(\"sha256\")\n\t\t.update(jsonString)\n\t\t.digest(\"hex\")\n\t\t.substring(0, 16);\n\n\treturn hash;\n}\n\n/**\n * Create a hash for a path, normalizing it first\n */\nfunction createHashForPath(dirPath: string): string {\n\tconst path = getNodePath();\n\t// Normalize the path first\n\tconst normalizedPath = path.normalize(dirPath);\n\n\t// Extract the last path component for readability\n\tconst lastComponent = path.basename(normalizedPath);\n\n\t// Create SHA-256 hash\n\tconst crypto = getNodeCrypto();\n\tconst hash = crypto\n\t\t.createHash(\"sha256\")\n\t\t.update(normalizedPath)\n\t\t.digest(\"hex\")\n\t\t.substring(0, 8); // Take first 8 characters for brevity\n\n\treturn `${lastComponent}-${hash}`;\n}\n\n/**\n * Get the storage path for the current working directory or a specified path\n */\nexport function getStoragePath(): string {\n\tconst dataPath = getDataPath(\"rivetkit\");\n\tconst dirHash = createHashForPath(process.cwd());\n\tconst path = getNodePath();\n\treturn path.join(dataPath, dirHash);\n}\n\n/**\n * Check if a path exists\n */\nexport async function pathExists(path: string): Promise<boolean> {\n\ttry {\n\t\tconst fs = getNodeFs();\n\t\tawait fs.access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport async function ensureDirectoryExists(\n\tdirectoryPath: string,\n): Promise<void> {\n\tif (!(await pathExists(directoryPath))) {\n\t\tconst fs = getNodeFs();\n\t\tawait fs.mkdir(directoryPath, { recursive: true });\n\t}\n}\n\n/**\n * Ensure a directory exists synchronously - only used during initialization\n * All other operations use the async version\n */\nexport function ensureDirectoryExistsSync(directoryPath: string): void {\n\tconst fsSync = getNodeFsSync();\n\tif (!fsSync.existsSync(directoryPath)) {\n\t\tfsSync.mkdirSync(directoryPath, { recursive: true });\n\t}\n}\n\n/**\n * Returns platform-specific data directory\n */\nfunction getDataPath(appName: string): string {\n\tconst platform = process.platform;\n\tconst os = getNodeOs();\n\tconst homeDir = os.homedir();\n\tconst path = getNodePath();\n\n\tswitch (platform) {\n\t\tcase \"win32\":\n\t\t\treturn path.join(\n\t\t\t\tprocess.env.APPDATA || path.join(homeDir, \"AppData\", \"Roaming\"),\n\t\t\t\tappName,\n\t\t\t);\n\t\tcase \"darwin\":\n\t\t\treturn path.join(\n\t\t\t\thomeDir,\n\t\t\t\t\"Library\",\n\t\t\t\t\"Application Support\",\n\t\t\t\tappName,\n\t\t\t);\n\t\tdefault: // linux and others\n\t\t\treturn path.join(\n\t\t\t\tprocess.env.XDG_DATA_HOME ||\n\t\t\t\t\tpath.join(homeDir, \".local\", \"share\"),\n\t\t\t\tappName,\n\t\t\t);\n\t}\n}\n","import type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { ActorStopping } from \"@/actor/errors\";\nimport { type ActorRouter, createActorRouter } from \"@/actor/router\";\nimport { routeWebSocket } from \"@/actor/router-websocket-endpoints\";\nimport { createClientWithDriver } from \"@/client/client\";\nimport { ClientConfigSchema } from \"@/client/config\";\nimport { createInlineWebSocket } from \"@/common/inline-websocket-adapter\";\nimport { noopNext } from \"@/common/utils\";\nimport type {\n\tActorDriver,\n\tActorOutput,\n\tCreateInput,\n\tGetForIdInput,\n\tGetOrCreateWithKeyInput,\n\tGetWithKeyInput,\n\tListActorsInput,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { ManagerDisplayInformation } from \"@/manager/driver\";\nimport type { Encoding, UniversalWebSocket } from \"@/mod\";\nimport type { DriverConfig, RegistryConfig } from \"@/registry/config\";\nimport type * as schema from \"@/schemas/file-system-driver/mod\";\nimport type { GetUpgradeWebSocket } from \"@/utils\";\nimport type { FileSystemGlobalState } from \"./global-state\";\nimport { logger } from \"./log\";\nimport { generateActorId } from \"./utils\";\n\nexport class FileSystemManagerDriver implements ManagerDriver {\n\t#config: RegistryConfig;\n\t#state: FileSystemGlobalState;\n\t#driverConfig: DriverConfig;\n\t#getUpgradeWebSocket: GetUpgradeWebSocket | undefined;\n\n\t#actorDriver: ActorDriver;\n\t#actorRouter: ActorRouter;\n\n\tconstructor(\n\t\tconfig: RegistryConfig,\n\t\tstate: FileSystemGlobalState,\n\t\tdriverConfig: DriverConfig,\n\t) {\n\t\tthis.#config = config;\n\t\tthis.#state = state;\n\t\tthis.#driverConfig = driverConfig;\n\n\t\t// Actors run on the same node as the manager, so we create a dummy actor router that we route requests to\n\t\tconst inlineClient = createClientWithDriver(this);\n\n\t\tthis.#actorDriver = this.#driverConfig.actor(\n\t\t\tconfig,\n\t\t\tthis,\n\t\t\tinlineClient,\n\t\t);\n\t\tthis.#actorRouter = createActorRouter(\n\t\t\tthis.#config,\n\t\t\tthis.#actorDriver,\n\t\t\tundefined,\n\t\t\tconfig.test.enabled,\n\t\t);\n\t}\n\n\tasync sendRequest(\n\t\tactorId: string,\n\t\tactorRequest: Request,\n\t): Promise<Response> {\n\t\treturn await this.#actorRouter.fetch(actorRequest, {\n\t\t\tactorId,\n\t\t});\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<UniversalWebSocket> {\n\t\t// Normalize the path (add leading slash if needed) but preserve query params\n\t\tconst normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n\n\t\t// Create a fake request with the full URL including query parameters\n\t\tconst fakeUrl = `http://inline-actor${normalizedPath}`;\n\t\tconst fakeRequest = new Request(fakeUrl, {\n\t\t\tmethod: \"GET\",\n\t\t});\n\n\t\t// Extract just the pathname for routing (without query params)\n\t\tconst pathOnly = normalizedPath.split(\"?\")[0];\n\n\t\tconst wsHandler = await routeWebSocket(\n\t\t\tfakeRequest,\n\t\t\tpathOnly,\n\t\t\t{},\n\t\t\tthis.#config,\n\t\t\tthis.#actorDriver,\n\t\t\tactorId,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t);\n\t\treturn createInlineWebSocket(wsHandler);\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\treturn await this.#actorRouter.fetch(actorRequest, {\n\t\t\tactorId,\n\t\t});\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<Response> {\n\t\tconst upgradeWebSocket = this.#getUpgradeWebSocket?.();\n\t\tinvariant(upgradeWebSocket, \"missing getUpgradeWebSocket\");\n\n\t\t// Handle raw WebSocket paths\n\t\tconst pathOnly = path.split(\"?\")[0];\n\t\tconst normalizedPath = pathOnly.startsWith(\"/\")\n\t\t\t? pathOnly\n\t\t\t: `/${pathOnly}`;\n\t\tconst wsHandler = await routeWebSocket(\n\t\t\t// TODO: Create new request with new path\n\t\t\tc.req.raw,\n\t\t\tnormalizedPath,\n\t\t\tc.req.header(),\n\t\t\tthis.#config,\n\t\t\tthis.#actorDriver,\n\t\t\tactorId,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t);\n\t\treturn upgradeWebSocket(() => wsHandler)(c, noopNext());\n\t}\n\n\tasync buildGatewayUrl(actorId: string): Promise<string> {\n\t\tconst port = this.#config.managerPort ?? 6420;\n\t\treturn `http://127.0.0.1:${port}/gateway/${encodeURIComponent(actorId)}`;\n\t}\n\n\tasync getForId({\n\t\tactorId,\n\t}: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// Validate the actor exists\n\t\tconst actor = await this.#state.loadActor(actorId);\n\t\tif (!actor.state) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (this.#state.isActorStopping(actorId)) {\n\t\t\tthrow new ActorStopping(actorId);\n\t\t}\n\n\t\treturn actorStateToOutput(actor.state);\n\t}\n\n\tasync getWithKey({\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput): Promise<ActorOutput | undefined> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(name, key);\n\n\t\t// Check if actor exists\n\t\tconst actor = await this.#state.loadActor(actorId);\n\t\tif (actor.state) {\n\t\t\treturn actorStateToOutput(actor.state);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(input.name, input.key);\n\n\t\t// Use the atomic getOrCreateActor method\n\t\tawait this.#state.loadOrCreateActor(\n\t\t\tactorId,\n\t\t\tinput.name,\n\t\t\tinput.key,\n\t\t\tinput.input,\n\t\t);\n\n\t\t// Start the actor immediately so timestamps are set\n\t\tawait this.#actorDriver.loadActor(actorId);\n\n\t\t// Reload state to get updated timestamps\n\t\tconst state = await this.#state.loadActorStateOrError(actorId);\n\t\treturn actorStateToOutput(state);\n\t}\n\n\tasync createActor({ name, key, input }: CreateInput): Promise<ActorOutput> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(name, key);\n\n\t\tawait this.#state.createActor(actorId, name, key, input);\n\n\t\t// Start the actor immediately so timestamps are set\n\t\tawait this.#actorDriver.loadActor(actorId);\n\n\t\t// Reload state to get updated timestamps\n\t\tconst state = await this.#state.loadActorStateOrError(actorId);\n\t\treturn actorStateToOutput(state);\n\t}\n\n\tasync listActors({ name }: ListActorsInput): Promise<ActorOutput[]> {\n\t\tconst actors: ActorOutput[] = [];\n\t\tconst itr = this.#state.getActorsIterator({});\n\n\t\tfor await (const actor of itr) {\n\t\t\tif (actor.name === name) {\n\t\t\t\tactors.push(actorStateToOutput(actor));\n\t\t\t}\n\t\t}\n\n\t\t// Sort by create ts desc (most recent first)\n\t\tactors.sort((a, b) => {\n\t\t\tconst aTs = a.createTs ?? 0;\n\t\t\tconst bTs = b.createTs ?? 0;\n\t\t\treturn bTs - aTs;\n\t\t});\n\n\t\treturn actors;\n\t}\n\n\tasync kvGet(actorId: string, key: Uint8Array): Promise<string | null> {\n\t\tconst response = await this.#state.kvBatchGet(actorId, [key]);\n\t\treturn response[0] !== null\n\t\t\t? new TextDecoder().decode(response[0])\n\t\t\t: null;\n\t}\n\n\tdisplayInformation(): ManagerDisplayInformation {\n\t\treturn {\n\t\t\tproperties: {\n\t\t\t\t...(this.#state.persist\n\t\t\t\t\t? { Data: this.#state.storagePath }\n\t\t\t\t\t: {}),\n\t\t\t\tInstances: this.#state.actorCountOnStartup.toString(),\n\t\t\t},\n\t\t};\n\t}\n\n\textraStartupLog() {\n\t\treturn {\n\t\t\tinstances: this.#state.actorCountOnStartup,\n\t\t\tdata: this.#state.storagePath,\n\t\t};\n\t}\n\n\tsetGetUpgradeWebSocket(getUpgradeWebSocket: GetUpgradeWebSocket): void {\n\t\tthis.#getUpgradeWebSocket = getUpgradeWebSocket;\n\t}\n}\n\nfunction actorStateToOutput(state: schema.ActorState): ActorOutput {\n\treturn {\n\t\tactorId: state.actorId,\n\t\tname: state.name,\n\t\tkey: state.key as string[],\n\t\tcreateTs: Number(state.createdAt),\n\t\tstartTs: state.startTs !== null ? Number(state.startTs) : null,\n\t\tconnectableTs:\n\t\t\tstate.connectableTs !== null ? Number(state.connectableTs) : null,\n\t\tsleepTs: state.sleepTs !== null ? Number(state.sleepTs) : null,\n\t\tdestroyTs: state.destroyTs !== null ? Number(state.destroyTs) : null,\n\t};\n}\n","import { importNodeDependencies } from \"@/utils/node\";\nimport { FileSystemActorDriver } from \"./actor\";\nimport { FileSystemGlobalState } from \"./global-state\";\nimport { FileSystemManagerDriver } from \"./manager\";\nimport { DriverConfig } from \"@/registry/config\";\n\nexport { FileSystemActorDriver } from \"./actor\";\nexport { FileSystemGlobalState } from \"./global-state\";\nexport { FileSystemManagerDriver } from \"./manager\";\nexport { getStoragePath } from \"./utils\";\n\nexport function createFileSystemOrMemoryDriver(\n\tpersist: boolean = true,\n\tcustomPath?: string,\n): DriverConfig {\n\timportNodeDependencies();\n\n\tconst state = new FileSystemGlobalState(persist, customPath);\n\tconst driverConfig: DriverConfig = {\n\t\tname: persist ? \"file-system\" : \"memory\",\n\t\tdisplayName: persist ? \"File System\" : \"Memory\",\n\t\tmanager: (config) =>\n\t\t\tnew FileSystemManagerDriver(\n\t\t\t\tconfig,\n\t\t\t\tstate,\n\t\t\t\tdriverConfig,\n\t\t\t),\n\t\tactor: (config, managerDriver, inlineClient) => {\n\t\t\tconst actorDriver = new FileSystemActorDriver(\n\t\t\t\tconfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t\tstate,\n\t\t\t);\n\n\t\t\tstate.onRunnerStart(\n\t\t\t\tconfig,\n\t\t\t\tinlineClient,\n\t\t\t\tactorDriver,\n\t\t\t);\n\n\t\t\treturn actorDriver;\n\t\t},\n\t\tautoStartActorDriver: true,\n\t};\n\treturn driverConfig;\n}\n\nexport function createFileSystemDriver(opts?: { path?: string }): DriverConfig {\n\treturn createFileSystemOrMemoryDriver(true, opts?.path);\n}\n\nexport function createMemoryDriver(): DriverConfig {\n\treturn createFileSystemOrMemoryDriver(false);\n}\n"]}
|