rivetkit 2.3.0-rc.8 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/dist/browser/client.d.ts +481 -74
  2. package/dist/browser/client.js +174 -148
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +47 -18
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +2 -2
  7. package/dist/tsup/actor/errors.d.cts +1 -1
  8. package/dist/tsup/actor/errors.d.ts +1 -1
  9. package/dist/tsup/actor/errors.js +1 -1
  10. package/dist/tsup/agent-os/index.cjs +2160 -2086
  11. package/dist/tsup/agent-os/index.cjs.map +1 -1
  12. package/dist/tsup/agent-os/index.d.cts +479 -73
  13. package/dist/tsup/agent-os/index.d.ts +479 -73
  14. package/dist/tsup/agent-os/index.js +2160 -2086
  15. package/dist/tsup/agent-os/index.js.map +1 -1
  16. package/dist/tsup/{chunk-KY3CERZR.js → chunk-2OTRTA3J.js} +7 -21
  17. package/dist/tsup/chunk-2OTRTA3J.js.map +1 -0
  18. package/dist/tsup/{chunk-HGW6PBWR.cjs → chunk-3677IIOV.cjs} +11 -25
  19. package/dist/tsup/chunk-3677IIOV.cjs.map +1 -0
  20. package/dist/tsup/{chunk-OT7FF6GB.cjs → chunk-47HHIEXH.cjs} +24 -9
  21. package/dist/tsup/chunk-47HHIEXH.cjs.map +1 -0
  22. package/dist/tsup/{chunk-EMFKMVJR.js → chunk-4JDSFJS5.js} +69 -58
  23. package/dist/tsup/chunk-4JDSFJS5.js.map +1 -0
  24. package/dist/tsup/{chunk-7HLFSAJP.cjs → chunk-7QKCIVAY.cjs} +225 -214
  25. package/dist/tsup/chunk-7QKCIVAY.cjs.map +1 -0
  26. package/dist/tsup/{chunk-AWTPTUQ7.cjs → chunk-B6VUNZUD.cjs} +10 -10
  27. package/dist/tsup/{chunk-AWTPTUQ7.cjs.map → chunk-B6VUNZUD.cjs.map} +1 -1
  28. package/dist/tsup/{chunk-D3T3ZBSY.js → chunk-BEI24WTI.js} +2 -2
  29. package/dist/tsup/{chunk-TMLOKTRB.js → chunk-BRP62GZC.js} +1 -1
  30. package/dist/tsup/chunk-BRP62GZC.js.map +1 -0
  31. package/dist/tsup/{chunk-D5G75T7J.js → chunk-DPIMKYNB.js} +61 -2
  32. package/dist/tsup/chunk-DPIMKYNB.js.map +1 -0
  33. package/dist/tsup/{chunk-BATTOVHF.cjs → chunk-DXXJPH55.cjs} +40 -13
  34. package/dist/tsup/chunk-DXXJPH55.cjs.map +1 -0
  35. package/dist/tsup/{chunk-3YY5S6TV.js → chunk-HXUEHHJF.js} +2 -2
  36. package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
  37. package/dist/tsup/{chunk-4BPKKZJO.cjs → chunk-I4LN3FNT.cjs} +10 -10
  38. package/dist/tsup/chunk-I4LN3FNT.cjs.map +1 -0
  39. package/dist/tsup/{chunk-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
  40. package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
  41. package/dist/tsup/{chunk-63WNTDRC.cjs → chunk-KORQB2IR.cjs} +1 -1
  42. package/dist/tsup/{chunk-63WNTDRC.cjs.map → chunk-KORQB2IR.cjs.map} +1 -1
  43. package/dist/tsup/{chunk-6TQSSJ4F.cjs → chunk-LVTBW2RE.cjs} +3 -3
  44. package/dist/tsup/{chunk-6TQSSJ4F.cjs.map → chunk-LVTBW2RE.cjs.map} +1 -1
  45. package/dist/tsup/{chunk-4JU3IPG2.js → chunk-MEHBWPLJ.js} +6 -6
  46. package/dist/tsup/chunk-MEHBWPLJ.js.map +1 -0
  47. package/dist/tsup/{chunk-SRNOPUC6.cjs → chunk-NIY3RSPX.cjs} +62 -3
  48. package/dist/tsup/chunk-NIY3RSPX.cjs.map +1 -0
  49. package/dist/tsup/{chunk-UZXQEGVJ.js → chunk-P2GNQ4RN.js} +4 -4
  50. package/dist/tsup/{chunk-UZXQEGVJ.js.map → chunk-P2GNQ4RN.js.map} +1 -1
  51. package/dist/tsup/{chunk-VUGENVIK.js → chunk-UMZVD6DQ.js} +22 -7
  52. package/dist/tsup/chunk-UMZVD6DQ.js.map +1 -0
  53. package/dist/tsup/{chunk-LD5YASJU.cjs → chunk-VE2X4KMG.cjs} +2 -2
  54. package/dist/tsup/{chunk-LD5YASJU.cjs.map → chunk-VE2X4KMG.cjs.map} +1 -1
  55. package/dist/tsup/{chunk-GBG63SUG.js → chunk-VTTFNQQI.js} +32 -5
  56. package/dist/tsup/chunk-VTTFNQQI.js.map +1 -0
  57. package/dist/tsup/{chunk-2NDZ7JCR.cjs → chunk-ZA7FLHKH.cjs} +1 -1
  58. package/dist/tsup/chunk-ZA7FLHKH.cjs.map +1 -0
  59. package/dist/tsup/client/mod.cjs +9 -9
  60. package/dist/tsup/client/mod.d.cts +5 -5
  61. package/dist/tsup/client/mod.d.ts +5 -5
  62. package/dist/tsup/client/mod.js +8 -8
  63. package/dist/tsup/common/log.cjs +3 -3
  64. package/dist/tsup/common/log.js +2 -2
  65. package/dist/tsup/common/websocket.cjs +4 -4
  66. package/dist/tsup/common/websocket.js +3 -3
  67. package/dist/tsup/{config-Ak1lv4gF.d.ts → config-BxWAw3iH.d.ts} +512 -27
  68. package/dist/tsup/{config-DU_xj4qZ.d.cts → config-CZQQ-mso.d.cts} +512 -27
  69. package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.cts} +1 -2
  70. package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.ts} +1 -2
  71. package/dist/tsup/{context-DAAp4Lpg.d.ts → context-Bw7xq8w3.d.cts} +8 -8
  72. package/dist/tsup/{context-Dt_L55q8.d.cts → context-D8QA76sV.d.ts} +8 -8
  73. package/dist/tsup/db/drizzle.cjs +3 -3
  74. package/dist/tsup/db/drizzle.d.cts +1 -1
  75. package/dist/tsup/db/drizzle.d.ts +1 -1
  76. package/dist/tsup/db/drizzle.js +1 -1
  77. package/dist/tsup/db/mod.cjs +2 -2
  78. package/dist/tsup/db/mod.d.cts +2 -2
  79. package/dist/tsup/db/mod.d.ts +2 -2
  80. package/dist/tsup/db/mod.js +1 -1
  81. package/dist/tsup/dynamic/mod.cjs +24 -0
  82. package/dist/tsup/dynamic/mod.cjs.map +1 -0
  83. package/dist/tsup/dynamic/mod.d.cts +37 -0
  84. package/dist/tsup/dynamic/mod.d.ts +37 -0
  85. package/dist/tsup/dynamic/mod.js +24 -0
  86. package/dist/tsup/dynamic/mod.js.map +1 -0
  87. package/dist/tsup/inspector/mod.cjs +6 -6
  88. package/dist/tsup/inspector/mod.js +5 -5
  89. package/dist/tsup/inspector-tab/mod.cjs +173 -0
  90. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  91. package/dist/tsup/inspector-tab/mod.d.cts +250 -0
  92. package/dist/tsup/inspector-tab/mod.d.ts +250 -0
  93. package/dist/tsup/inspector-tab/mod.js +173 -0
  94. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  95. package/dist/tsup/mod.cjs +615 -348
  96. package/dist/tsup/mod.cjs.map +1 -1
  97. package/dist/tsup/mod.d.cts +5 -5
  98. package/dist/tsup/mod.d.ts +5 -5
  99. package/dist/tsup/mod.js +511 -244
  100. package/dist/tsup/mod.js.map +1 -1
  101. package/dist/tsup/test/mod.cjs +21 -18
  102. package/dist/tsup/test/mod.cjs.map +1 -1
  103. package/dist/tsup/test/mod.d.cts +4 -4
  104. package/dist/tsup/test/mod.d.ts +4 -4
  105. package/dist/tsup/test/mod.js +18 -15
  106. package/dist/tsup/test/mod.js.map +1 -1
  107. package/dist/tsup/{utils-DVekpm4I.d.cts → utils-DQosb24I.d.cts} +1 -1
  108. package/dist/tsup/{utils-DVekpm4I.d.ts → utils-DQosb24I.d.ts} +1 -1
  109. package/dist/tsup/utils.cjs +3 -3
  110. package/dist/tsup/utils.d.cts +1 -1
  111. package/dist/tsup/utils.d.ts +1 -1
  112. package/dist/tsup/utils.js +2 -2
  113. package/dist/tsup/workflow/mod.cjs +279 -279
  114. package/dist/tsup/workflow/mod.cjs.map +1 -1
  115. package/dist/tsup/workflow/mod.d.cts +6 -6
  116. package/dist/tsup/workflow/mod.d.ts +6 -6
  117. package/dist/tsup/workflow/mod.js +380 -380
  118. package/dist/tsup/workflow/mod.js.map +1 -1
  119. package/package.json +29 -9
  120. package/src/actor/config.ts +156 -51
  121. package/src/actor/contexts/index.ts +7 -2
  122. package/src/actor/definition.ts +17 -19
  123. package/src/actor/driver.ts +3 -3
  124. package/src/actor/errors.ts +8 -2
  125. package/src/actor/instance/mod.ts +26 -34
  126. package/src/actor/keys.ts +1 -1
  127. package/src/actor/mod.ts +22 -20
  128. package/src/actor/schema.ts +2 -2
  129. package/src/agent-os/actor/index.ts +38 -18
  130. package/src/agent-os/actor/preview.ts +1 -2
  131. package/src/agent-os/config.ts +1 -1
  132. package/src/agent-os/fs/database-vfs.ts +1 -1
  133. package/src/agent-os/index.ts +16 -15
  134. package/src/client/actor-common.ts +87 -54
  135. package/src/client/actor-conn.ts +11 -11
  136. package/src/client/actor-handle.ts +69 -52
  137. package/src/client/actor-query.ts +5 -5
  138. package/src/client/errors.ts +1 -1
  139. package/src/client/lifecycle-errors.ts +2 -4
  140. package/src/client/query.ts +1 -1
  141. package/src/client/queue.ts +8 -4
  142. package/src/client/raw-utils.ts +8 -6
  143. package/src/client/resolve-gateway-target.ts +1 -1
  144. package/src/client/utils.ts +2 -6
  145. package/src/common/actor-websocket.ts +3 -1
  146. package/src/common/bare/actor-persist/v1.ts +205 -163
  147. package/src/common/bare/actor-persist/v2.ts +265 -213
  148. package/src/common/bare/actor-persist/v3.ts +176 -172
  149. package/src/common/bare/actor-persist/v4.ts +254 -253
  150. package/src/common/bare/transport/v1.ts +659 -543
  151. package/src/common/client-protocol-versioned.ts +66 -64
  152. package/src/common/database/config.ts +2 -8
  153. package/src/common/database/native-database.ts +1 -1
  154. package/src/common/database/shared.ts +1 -0
  155. package/src/common/encoding.ts +13 -17
  156. package/src/common/engine.ts +28 -1
  157. package/src/common/eventsource.ts +1 -1
  158. package/src/common/inline-websocket-adapter.ts +3 -2
  159. package/src/common/router.ts +13 -17
  160. package/src/common/utils.ts +1 -2
  161. package/src/common/websocket-interface.ts +1 -1
  162. package/src/db/mod.ts +1 -1
  163. package/src/devtools-loader/index.ts +4 -7
  164. package/src/devtools-loader/serve-devtools.ts +26 -0
  165. package/src/drivers/engine/actor-driver.ts +48 -46
  166. package/src/dynamic/instance.ts +32 -0
  167. package/src/dynamic/internal.ts +50 -0
  168. package/src/dynamic/isolate-runtime.ts +66 -0
  169. package/src/dynamic/mod.ts +32 -0
  170. package/src/engine-client/actor-http-client.ts +3 -3
  171. package/src/engine-client/actor-websocket-client.ts +5 -5
  172. package/src/engine-client/api-endpoints.ts +51 -2
  173. package/src/engine-client/api-utils.ts +2 -2
  174. package/src/engine-client/driver.ts +1 -1
  175. package/src/engine-client/mod.ts +5 -3
  176. package/src/engine-client/ws-proxy.ts +9 -4
  177. package/src/inspector/client.browser.ts +5 -11
  178. package/src/inspector/mod.ts +1 -3
  179. package/src/inspector-tab/mod.ts +315 -0
  180. package/src/registry/config/envoy.ts +1 -2
  181. package/src/registry/config/index.ts +40 -16
  182. package/src/registry/index.ts +226 -83
  183. package/src/registry/napi-runtime.ts +46 -12
  184. package/src/registry/native-validation.ts +10 -12
  185. package/src/registry/native.ts +307 -164
  186. package/src/registry/process-metrics.ts +90 -23
  187. package/src/registry/runtime.ts +53 -6
  188. package/src/registry/wasm-runtime.ts +30 -3
  189. package/src/serde.ts +1 -1
  190. package/src/serverless/configure.ts +18 -7
  191. package/src/test/mod.ts +11 -8
  192. package/src/utils/endpoint-parser.ts +1 -1
  193. package/src/utils/env-vars.ts +6 -0
  194. package/src/utils/router.ts +1 -1
  195. package/src/utils/serve.ts +4 -5
  196. package/src/utils.ts +1 -2
  197. package/src/workflow/context.ts +30 -29
  198. package/src/workflow/driver.ts +4 -6
  199. package/src/workflow/inspector.ts +2 -2
  200. package/src/workflow/mod.ts +15 -17
  201. package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
  202. package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
  203. package/dist/tsup/chunk-4BPKKZJO.cjs.map +0 -1
  204. package/dist/tsup/chunk-4JU3IPG2.js.map +0 -1
  205. package/dist/tsup/chunk-7HLFSAJP.cjs.map +0 -1
  206. package/dist/tsup/chunk-BATTOVHF.cjs.map +0 -1
  207. package/dist/tsup/chunk-D5G75T7J.js.map +0 -1
  208. package/dist/tsup/chunk-EMFKMVJR.js.map +0 -1
  209. package/dist/tsup/chunk-GBG63SUG.js.map +0 -1
  210. package/dist/tsup/chunk-HGW6PBWR.cjs.map +0 -1
  211. package/dist/tsup/chunk-KY3CERZR.js.map +0 -1
  212. package/dist/tsup/chunk-OT7FF6GB.cjs.map +0 -1
  213. package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
  214. package/dist/tsup/chunk-SRNOPUC6.cjs.map +0 -1
  215. package/dist/tsup/chunk-TMLOKTRB.js.map +0 -1
  216. package/dist/tsup/chunk-VUGENVIK.js.map +0 -1
  217. package/dist/tsup/process-metrics-NW754INA.js +0 -118
  218. package/dist/tsup/process-metrics-NW754INA.js.map +0 -1
  219. package/dist/tsup/process-metrics-TYAGKCEJ.cjs +0 -118
  220. package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +0 -1
  221. /package/dist/tsup/{chunk-D3T3ZBSY.js.map → chunk-BEI24WTI.js.map} +0 -0
@@ -1,1396 +1,1812 @@
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(); } }// src/agent-os/actor/db.ts
2
- async function migrateAgentOsTables(db2) {
3
- await db2.execute(`
4
- CREATE TABLE IF NOT EXISTS agent_os_preview_tokens (
5
- token TEXT PRIMARY KEY,
6
- port INTEGER NOT NULL,
7
- created_at INTEGER NOT NULL,
8
- expires_at INTEGER NOT NULL
9
- );
10
-
11
- CREATE INDEX IF NOT EXISTS idx_preview_tokens_expires_at
12
- ON agent_os_preview_tokens(expires_at);
13
-
14
- CREATE TABLE IF NOT EXISTS agent_os_fs_entries (
15
- path TEXT PRIMARY KEY,
16
- is_directory INTEGER NOT NULL DEFAULT 0,
17
- content BLOB,
18
- mode INTEGER NOT NULL DEFAULT 33188,
19
- uid INTEGER NOT NULL DEFAULT 0,
20
- gid INTEGER NOT NULL DEFAULT 0,
21
- size INTEGER NOT NULL DEFAULT 0,
22
- atime_ms INTEGER NOT NULL,
23
- mtime_ms INTEGER NOT NULL,
24
- ctime_ms INTEGER NOT NULL,
25
- birthtime_ms INTEGER NOT NULL,
26
- symlink_target TEXT,
27
- nlink INTEGER NOT NULL DEFAULT 1
28
- );
29
-
30
- CREATE INDEX IF NOT EXISTS idx_fs_entries_parent
31
- ON agent_os_fs_entries(path);
32
-
33
- CREATE TABLE IF NOT EXISTS agent_os_sessions (
34
- session_id TEXT PRIMARY KEY,
35
- agent_type TEXT NOT NULL,
36
- capabilities TEXT NOT NULL,
37
- agent_info TEXT,
38
- created_at INTEGER NOT NULL
39
- );
40
-
41
- CREATE TABLE IF NOT EXISTS agent_os_session_events (
42
- id INTEGER PRIMARY KEY AUTOINCREMENT,
43
- session_id TEXT NOT NULL,
44
- seq INTEGER NOT NULL,
45
- event TEXT NOT NULL,
46
- created_at INTEGER NOT NULL,
47
- FOREIGN KEY (session_id) REFERENCES agent_os_sessions(session_id) ON DELETE CASCADE
48
- );
49
-
50
- CREATE INDEX IF NOT EXISTS idx_session_events_session_seq
51
- ON agent_os_session_events(session_id, seq);
52
- `);
53
- }
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(); } }// src/agent-os/actor/index.ts
2
+ var _agentoscore = require('@rivet-dev/agent-os-core');
54
3
 
55
- // src/agent-os/fs/database-vfs.ts
56
- var _posix = require('path/posix'); var posixPath = _interopRequireWildcard(_posix);
57
- var S_IFDIR = 16384;
58
- var S_IFREG = 32768;
59
- var S_IFLNK = 40960;
60
- var DEFAULT_FILE_MODE = S_IFREG | 420;
61
- var DEFAULT_DIR_MODE = S_IFDIR | 493;
62
- function normPath(p) {
63
- const normalized = posixPath.normalize(`/${p}`);
64
- if (normalized.length > 1 && normalized.endsWith("/")) {
65
- return normalized.slice(0, -1);
66
- }
67
- return normalized;
68
- }
69
- function parentPath(p) {
70
- const parent = posixPath.dirname(p);
71
- return parent;
72
- }
73
- function throwENOENT(path) {
74
- const err = new Error(`ENOENT: no such file or directory: ${path}`);
75
- err.name = "ENOENT";
76
- throw err;
77
- }
78
- function throwEEXIST(path) {
79
- const err = new Error(`EEXIST: file already exists: ${path}`);
80
- err.name = "EEXIST";
81
- throw err;
82
- }
83
- function throwENOTDIR(path) {
84
- const err = new Error(`ENOTDIR: not a directory: ${path}`);
85
- err.name = "ENOTDIR";
86
- throw err;
87
- }
88
- function throwEISDIR(path) {
89
- const err = new Error(`EISDIR: illegal operation on a directory: ${path}`);
90
- err.name = "EISDIR";
91
- throw err;
92
- }
93
- function throwENOTEMPTY(path) {
94
- const err = new Error(`ENOTEMPTY: directory not empty: ${path}`);
95
- err.name = "ENOTEMPTY";
96
- throw err;
97
- }
98
- function throwENOSYS(op) {
99
- const err = new Error(`ENOSYS: function not implemented: ${op}`);
100
- err.name = "ENOSYS";
101
- throw err;
102
- }
103
- function rowToStat(row) {
104
- return {
105
- mode: row.mode,
106
- size: row.size,
107
- isDirectory: row.is_directory === 1,
108
- isSymbolicLink: row.symlink_target !== null,
109
- atimeMs: row.atime_ms,
110
- mtimeMs: row.mtime_ms,
111
- ctimeMs: row.ctime_ms,
112
- birthtimeMs: row.birthtime_ms,
113
- ino: 0,
114
- nlink: row.nlink,
115
- uid: row.uid,
116
- gid: row.gid
117
- };
118
- }
119
- function createDatabaseVfs(options) {
120
- const { db: db2 } = options;
121
- async function getEntry(path) {
122
- const rows = await db2.execute(
123
- "SELECT * FROM agent_os_fs_entries WHERE path = ?",
124
- path
4
+ // src/actor/config.ts
5
+ var _v4 = require('zod/v4');
6
+ var DEFAULT_SLEEP_GRACE_PERIOD = 15e3;
7
+ var zFunction = () => _v4.z.custom((val) => typeof val === "function");
8
+ var WorkflowInspectorConfigSchema = _v4.z.object({
9
+ getHistory: zFunction(),
10
+ onHistoryUpdated: zFunction().optional(),
11
+ replayFromStep: zFunction().optional()
12
+ });
13
+ var RunInspectorConfigSchema = _v4.z.object({
14
+ workflow: WorkflowInspectorConfigSchema.optional()
15
+ }).optional();
16
+ var BUILTIN_INSPECTOR_TAB_IDS = [
17
+ "workflow",
18
+ "database",
19
+ "state",
20
+ "queue",
21
+ "connections",
22
+ "console"
23
+ ];
24
+ var BuiltinInspectorTabIdSchema = _v4.z.enum(BUILTIN_INSPECTOR_TAB_IDS);
25
+ var CUSTOM_INSPECTOR_TAB_ID_RE = /^[A-Za-z0-9_-]+$/;
26
+ var CustomInspectorTabEntrySchema = _v4.z.object({
27
+ id: _v4.z.string().regex(
28
+ CUSTOM_INSPECTOR_TAB_ID_RE,
29
+ "inspector.tabs[].id must contain only letters, digits, underscore, or dash"
30
+ ),
31
+ label: _v4.z.string().min(1),
32
+ source: _v4.z.string().min(1),
33
+ /**
34
+ * Optional icon id. The dashboard maps strings to glyphs (see its
35
+ * icon registry); unknown ids fall back to a generic icon.
36
+ */
37
+ icon: _v4.z.string().min(1).optional(),
38
+ hidden: _v4.z.literal(false).optional()
39
+ }).strict();
40
+ var HideInspectorTabEntrySchema = _v4.z.object({
41
+ id: BuiltinInspectorTabIdSchema,
42
+ hidden: _v4.z.literal(true)
43
+ }).strict();
44
+ var InspectorTabEntrySchema = _v4.z.union([
45
+ CustomInspectorTabEntrySchema,
46
+ HideInspectorTabEntrySchema
47
+ ]);
48
+ var ActorInspectorConfigSchema = _v4.z.object({
49
+ tabs: _v4.z.array(InspectorTabEntrySchema).default(() => [])
50
+ }).strict().refine(
51
+ (data) => {
52
+ const ids = data.tabs.map((t) => t.id);
53
+ return new Set(ids).size === ids.length;
54
+ },
55
+ { message: "Duplicate id in inspector.tabs", path: ["tabs"] }
56
+ ).refine(
57
+ (data) => {
58
+ const builtinSet = new Set(BUILTIN_INSPECTOR_TAB_IDS);
59
+ return data.tabs.every(
60
+ (t) => t.hidden === true || !builtinSet.has(t.id)
125
61
  );
126
- return rows[0];
62
+ },
63
+ {
64
+ message: "Custom inspector tab id collides with a built-in (use hidden: true to hide a built-in)",
65
+ path: ["tabs"]
127
66
  }
128
- async function getEntryOrThrow(path) {
129
- const entry = await getEntry(path);
130
- if (!entry) {
131
- throwENOENT(path);
132
- }
133
- return entry;
67
+ );
68
+ var RunConfigSchema = _v4.z.object({
69
+ /** Display name for the actor in the Inspector UI. */
70
+ name: _v4.z.string().optional(),
71
+ /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
72
+ icon: _v4.z.string().optional(),
73
+ /** The run handler function. */
74
+ run: zFunction(),
75
+ /** Inspector integration for long-running run handlers. */
76
+ inspector: RunInspectorConfigSchema.optional()
77
+ });
78
+ var zRunHandler = _v4.z.union([zFunction(), RunConfigSchema]).optional();
79
+ var GlobalActorOptionsBaseSchema = _v4.z.object({
80
+ /** Display name for the actor in the Inspector UI. */
81
+ name: _v4.z.string().optional(),
82
+ /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
83
+ icon: _v4.z.string().optional(),
84
+ /**
85
+ * Can hibernate WebSockets for onWebSocket.
86
+ *
87
+ * WebSockets using actions/events are hibernatable by default.
88
+ *
89
+ * @experimental
90
+ **/
91
+ canHibernateWebSocket: _v4.z.union([_v4.z.boolean(), zFunction()]).default(false)
92
+ }).strict();
93
+ var GlobalActorOptionsSchema = GlobalActorOptionsBaseSchema.prefault(
94
+ () => ({})
95
+ );
96
+ var InstanceActorOptionsBaseSchema = _v4.z.object({
97
+ createVarsTimeout: _v4.z.number().positive().default(5e3),
98
+ createConnStateTimeout: _v4.z.number().positive().default(5e3),
99
+ onBeforeConnectTimeout: _v4.z.number().positive().default(5e3),
100
+ onConnectTimeout: _v4.z.number().positive().default(5e3),
101
+ onMigrateTimeout: _v4.z.number().positive().default(3e4),
102
+ sleepGracePeriod: _v4.z.number().positive().default(DEFAULT_SLEEP_GRACE_PERIOD),
103
+ /** @deprecated `onDestroyTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */
104
+ onDestroyTimeout: _v4.z.number().positive().optional(),
105
+ /** @deprecated `waitUntilTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */
106
+ waitUntilTimeout: _v4.z.number().positive().optional(),
107
+ stateSaveInterval: _v4.z.number().positive().default(1e3),
108
+ actionTimeout: _v4.z.number().positive().default(6e4),
109
+ connectionLivenessTimeout: _v4.z.number().positive().default(2500),
110
+ connectionLivenessInterval: _v4.z.number().positive().default(5e3),
111
+ /** @deprecated Use `c.keepAwake(promise)` to scope keep-awake to a specific operation, or keep `noSleep` for actors that must stay awake indefinitely. Will be removed in 2.2.0. */
112
+ noSleep: _v4.z.boolean().default(false),
113
+ sleepTimeout: _v4.z.number().positive().default(3e4),
114
+ maxQueueSize: _v4.z.number().positive().default(1e3),
115
+ maxQueueMessageSize: _v4.z.number().positive().default(64 * 1024),
116
+ /** Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading. */
117
+ preloadMaxWorkflowBytes: _v4.z.number().nonnegative().optional(),
118
+ /** Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading. */
119
+ preloadMaxConnectionsBytes: _v4.z.number().nonnegative().optional()
120
+ }).strict();
121
+ var InstanceActorOptionsSchema = InstanceActorOptionsBaseSchema.prefault(() => ({}));
122
+ var ActorOptionsSchema = GlobalActorOptionsBaseSchema.extend(
123
+ InstanceActorOptionsBaseSchema.shape
124
+ ).strict().prefault(() => ({}));
125
+ var ActorConfigSchema = _v4.z.object({
126
+ onCreate: zFunction().optional(),
127
+ onDestroy: zFunction().optional(),
128
+ onMigrate: zFunction().optional(),
129
+ onWake: zFunction().optional(),
130
+ onSleep: zFunction().optional(),
131
+ run: zRunHandler,
132
+ onStateChange: zFunction().optional(),
133
+ onBeforeConnect: zFunction().optional(),
134
+ onConnect: zFunction().optional(),
135
+ onDisconnect: zFunction().optional(),
136
+ onBeforeActionResponse: zFunction().optional(),
137
+ onRequest: zFunction().optional(),
138
+ onWebSocket: zFunction().optional(),
139
+ actions: _v4.z.record(_v4.z.string(), zFunction()).default(() => ({})),
140
+ actionInputSchemas: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
141
+ connParamsSchema: _v4.z.any().optional(),
142
+ events: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
143
+ queues: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
144
+ state: _v4.z.any().optional(),
145
+ createState: zFunction().optional(),
146
+ connState: _v4.z.any().optional(),
147
+ createConnState: zFunction().optional(),
148
+ vars: _v4.z.any().optional(),
149
+ db: _v4.z.any().optional(),
150
+ createVars: zFunction().optional(),
151
+ options: ActorOptionsSchema,
152
+ inspector: ActorInspectorConfigSchema.optional()
153
+ }).strict().refine(
154
+ (data) => !(data.state !== void 0 && data.createState !== void 0),
155
+ {
156
+ message: "Cannot define both 'state' and 'createState'",
157
+ path: ["state"]
134
158
  }
135
- async function ensureParentExists(path) {
136
- const parent = parentPath(path);
137
- if (parent === path) return;
138
- const entry = await getEntry(parent);
139
- if (!entry) {
140
- throwENOENT(parent);
141
- }
142
- if (entry.is_directory !== 1) {
143
- throwENOTDIR(parent);
144
- }
159
+ ).refine(
160
+ (data) => !(data.connState !== void 0 && data.createConnState !== void 0),
161
+ {
162
+ message: "Cannot define both 'connState' and 'createConnState'",
163
+ path: ["connState"]
145
164
  }
146
- async function getChildEntries(dirPath) {
147
- const prefix = dirPath === "/" ? "/" : `${dirPath}/`;
148
- const rows = await db2.execute(
149
- "SELECT * FROM agent_os_fs_entries WHERE path LIKE ? AND path != ?",
150
- `${prefix}%`,
151
- dirPath
152
- );
153
- return rows.filter((row) => {
154
- const relative = row.path.slice(prefix.length);
155
- return relative.length > 0 && !relative.includes("/");
156
- });
165
+ ).refine(
166
+ (data) => !(data.vars !== void 0 && data.createVars !== void 0),
167
+ {
168
+ message: "Cannot define both 'vars' and 'createVars'",
169
+ path: ["vars"]
157
170
  }
158
- const rootInit = (async () => {
159
- const root = await getEntry("/");
160
- if (!root) {
161
- const now = Date.now();
162
- await db2.execute(
163
- `INSERT OR IGNORE INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
164
- "/",
165
- DEFAULT_DIR_MODE,
166
- now,
167
- now,
168
- now,
169
- now
170
- );
171
- }
172
- })();
173
- const backend = {
174
- async readFile(p) {
175
- await rootInit;
176
- const path = normPath(p);
177
- const entry = await getEntryOrThrow(path);
178
- if (entry.is_directory === 1) {
179
- throwEISDIR(path);
180
- }
181
- return _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
182
- },
183
- async readTextFile(p) {
184
- const data = await backend.readFile(p);
185
- return new TextDecoder().decode(data);
186
- },
187
- async readDir(p) {
188
- await rootInit;
189
- const path = normPath(p);
190
- const entry = await getEntryOrThrow(path);
191
- if (entry.is_directory !== 1) {
192
- throwENOTDIR(path);
193
- }
194
- const children = await getChildEntries(path);
195
- return children.map((child) => posixPath.basename(child.path));
196
- },
197
- async readDirWithTypes(p) {
198
- await rootInit;
199
- const path = normPath(p);
200
- const entry = await getEntryOrThrow(path);
201
- if (entry.is_directory !== 1) {
202
- throwENOTDIR(path);
203
- }
204
- const children = await getChildEntries(path);
205
- return children.map((child) => ({
206
- name: posixPath.basename(child.path),
207
- isDirectory: child.is_directory === 1,
208
- isSymbolicLink: child.symlink_target !== null,
209
- ino: 0
210
- }));
211
- },
212
- async writeFile(p, content) {
213
- await rootInit;
214
- const path = normPath(p);
215
- await ensureParentExists(path);
216
- const existing = await getEntry(path);
217
- if (existing && existing.is_directory === 1) {
218
- throwEISDIR(path);
219
- }
220
- const data = typeof content === "string" ? new TextEncoder().encode(content) : content;
221
- const now = Date.now();
222
- if (existing) {
223
- await db2.execute(
224
- `UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ?, atime_ms = ? WHERE path = ?`,
225
- data,
226
- data.byteLength,
227
- now,
228
- now,
229
- now,
230
- path
231
- );
232
- } else {
233
- await db2.execute(
234
- `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 0, ?, ?, 0, 0, ?, ?, ?, ?, ?, NULL, 1)`,
235
- path,
236
- data,
237
- DEFAULT_FILE_MODE,
238
- data.byteLength,
239
- now,
240
- now,
241
- now,
242
- now
243
- );
244
- }
245
- },
246
- async createDir(p) {
247
- await rootInit;
248
- const path = normPath(p);
249
- await ensureParentExists(path);
250
- const existing = await getEntry(path);
251
- if (existing) {
252
- throwEEXIST(path);
253
- }
254
- const now = Date.now();
255
- await db2.execute(
256
- `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
257
- path,
258
- DEFAULT_DIR_MODE,
259
- now,
260
- now,
261
- now,
262
- now
263
- );
264
- },
265
- async mkdir(p, options2) {
266
- await rootInit;
267
- const path = normPath(p);
268
- if (options2 == null ? void 0 : options2.recursive) {
269
- const parts = path.split("/").filter(Boolean);
270
- let current = "";
271
- for (const part of parts) {
272
- current += `/${part}`;
273
- const existing = await getEntry(current);
274
- if (!existing) {
275
- const now = Date.now();
276
- await db2.execute(
277
- `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
278
- current,
279
- DEFAULT_DIR_MODE,
280
- now,
281
- now,
282
- now,
283
- now
284
- );
285
- } else if (existing.is_directory !== 1) {
286
- throwENOTDIR(current);
287
- }
288
- }
289
- } else {
290
- await backend.createDir(p);
171
+ );
172
+ var DocActorOptionsSchema = _v4.z.object({
173
+ name: _v4.z.string().optional().describe("Display name for the actor in the Inspector UI."),
174
+ icon: _v4.z.string().optional().describe(
175
+ "Icon for the actor in the Inspector UI. Can be an emoji (e.g., '\u{1F680}') or FontAwesome icon name (e.g., 'rocket')."
176
+ ),
177
+ createVarsTimeout: _v4.z.number().optional().describe("Timeout in ms for createVars handler. Default: 5000"),
178
+ createConnStateTimeout: _v4.z.number().optional().describe(
179
+ "Timeout in ms for createConnState handler. Default: 5000"
180
+ ),
181
+ onMigrateTimeout: _v4.z.number().optional().describe("Timeout in ms for onMigrate handler. Default: 30000"),
182
+ onBeforeConnectTimeout: _v4.z.number().optional().describe(
183
+ "Timeout in ms for onBeforeConnect handler. Default: 5000"
184
+ ),
185
+ onConnectTimeout: _v4.z.number().optional().describe("Timeout in ms for onConnect handler. Default: 5000"),
186
+ sleepGracePeriod: _v4.z.number().optional().describe(
187
+ `Max time in ms for the graceful shutdown window. Covers lifecycle hooks (onSleep, onDestroy), the run handler wait, async raw WebSocket handlers, disconnect callbacks, and final state serialization. Default: ${DEFAULT_SLEEP_GRACE_PERIOD}.`
188
+ ),
189
+ onDestroyTimeout: _v4.z.number().optional().describe(
190
+ "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0."
191
+ ),
192
+ waitUntilTimeout: _v4.z.number().optional().describe(
193
+ "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0."
194
+ ),
195
+ stateSaveInterval: _v4.z.number().optional().describe(
196
+ "Interval in ms between automatic state saves. Default: 1000"
197
+ ),
198
+ actionTimeout: _v4.z.number().optional().describe("Timeout in ms for action handlers. Default: 60000"),
199
+ connectionLivenessTimeout: _v4.z.number().optional().describe(
200
+ "Timeout in ms for connection liveness checks. Default: 2500"
201
+ ),
202
+ connectionLivenessInterval: _v4.z.number().optional().describe(
203
+ "Interval in ms between connection liveness checks. Default: 5000"
204
+ ),
205
+ noSleep: _v4.z.boolean().optional().describe(
206
+ "Deprecated. If true, the actor will never sleep. Use c.keepAwake(promise) to scope keep-awake to a specific operation instead. Default: false"
207
+ ),
208
+ sleepTimeout: _v4.z.number().optional().describe(
209
+ "Time in ms of inactivity before the actor sleeps. Default: 30000"
210
+ ),
211
+ maxQueueSize: _v4.z.number().optional().describe(
212
+ "Maximum number of queue messages before rejecting new messages. Default: 1000"
213
+ ),
214
+ maxQueueMessageSize: _v4.z.number().optional().describe(
215
+ "Maximum size of each queue message in bytes. Default: 65536"
216
+ ),
217
+ canHibernateWebSocket: _v4.z.boolean().optional().describe(
218
+ "Whether WebSockets using onWebSocket can be hibernated. WebSockets using actions/events are hibernatable by default. Default: false"
219
+ ),
220
+ preloadMaxWorkflowBytes: _v4.z.number().optional().describe(
221
+ "Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading."
222
+ ),
223
+ preloadMaxConnectionsBytes: _v4.z.number().optional().describe(
224
+ "Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading."
225
+ )
226
+ }).describe("Actor options for timeouts and behavior configuration.");
227
+ var DocActorConfigSchema = _v4.z.object({
228
+ state: _v4.z.unknown().optional().describe(
229
+ "Initial state value for the actor. Cannot be used with createState."
230
+ ),
231
+ createState: _v4.z.unknown().optional().describe(
232
+ "Function to create initial state. Receives context and input. Cannot be used with state."
233
+ ),
234
+ connState: _v4.z.unknown().optional().describe(
235
+ "Initial connection state value. Cannot be used with createConnState."
236
+ ),
237
+ createConnState: _v4.z.unknown().optional().describe(
238
+ "Function to create connection state. Receives context and connection params. The pending connection is not visible in c.conns until this succeeds. Cannot be used with connState."
239
+ ),
240
+ vars: _v4.z.unknown().optional().describe(
241
+ "Initial ephemeral variables value. Cannot be used with createVars."
242
+ ),
243
+ createVars: _v4.z.unknown().optional().describe(
244
+ "Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars."
245
+ ),
246
+ db: _v4.z.unknown().optional().describe("Database provider instance for the actor."),
247
+ onCreate: _v4.z.unknown().optional().describe(
248
+ "Called when the actor is first initialized. Use to initialize state."
249
+ ),
250
+ onDestroy: _v4.z.unknown().optional().describe("Called when the actor is destroyed."),
251
+ onMigrate: _v4.z.unknown().optional().describe(
252
+ "Called on every actor start after persisted state loads and before onWake. Use for repeatable schema migrations."
253
+ ),
254
+ onWake: _v4.z.unknown().optional().describe(
255
+ "Called when the actor wakes up and is ready to receive connections and actions."
256
+ ),
257
+ onSleep: _v4.z.unknown().optional().describe(
258
+ "Called when the actor is stopping or sleeping. Use to clean up resources."
259
+ ),
260
+ run: _v4.z.unknown().optional().describe(
261
+ "Called after actor starts. Does not block startup. Use for background tasks like queue processing or tick loops. If it exits, the actor follows the normal idle sleep timeout once idle. If it throws, the actor logs the error and then follows the normal idle sleep timeout once idle."
262
+ ),
263
+ onStateChange: _v4.z.unknown().optional().describe(
264
+ "Called when the actor's state changes. State changes within this hook won't trigger recursion."
265
+ ),
266
+ onBeforeConnect: _v4.z.unknown().optional().describe(
267
+ "Called before a client connects. Throw an error to reject the connection. The pending connection is not visible in c.conns while this runs."
268
+ ),
269
+ onConnect: _v4.z.unknown().optional().describe(
270
+ "Called when a client successfully connects. The connection is visible in c.conns before this runs."
271
+ ),
272
+ onDisconnect: _v4.z.unknown().optional().describe("Called when a client disconnects."),
273
+ onBeforeActionResponse: _v4.z.unknown().optional().describe(
274
+ "Called before sending an action response. Use to transform output."
275
+ ),
276
+ onRequest: _v4.z.unknown().optional().describe(
277
+ "Called for raw HTTP requests to /actors/{name}/http/* endpoints."
278
+ ),
279
+ onWebSocket: _v4.z.unknown().optional().describe(
280
+ "Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints."
281
+ ),
282
+ actions: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe(
283
+ "Map of action name to handler function. Defaults to an empty object."
284
+ ),
285
+ actionInputSchemas: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe(
286
+ "Optional schema map for validating action argument tuples in native runtimes."
287
+ ),
288
+ connParamsSchema: _v4.z.unknown().optional().describe(
289
+ "Optional schema for validating connection params in native runtimes."
290
+ ),
291
+ events: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe("Map of event names to schemas."),
292
+ queues: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe("Map of queue names to schemas."),
293
+ options: DocActorOptionsSchema.optional()
294
+ }).describe("Actor configuration passed to the actor() function.");
295
+
296
+ // src/common/log.ts
297
+
298
+
299
+
300
+ var _pino = require('pino');
301
+
302
+
303
+ // src/actor/errors.ts
304
+ function isTypedErrorTag(value) {
305
+ return value === "ActorError" || value === "RivetError";
306
+ }
307
+ function isRivetErrorLike(error) {
308
+ return typeof error === "object" && error !== null && "group" in error && typeof error.group === "string" && "code" in error && typeof error.code === "string" && "message" in error && typeof error.message === "string" && (!("__type" in error) || isTypedErrorTag(error.__type));
309
+ }
310
+ function isRivetErrorCode(error, group, code) {
311
+ return isRivetErrorLike(error) && error.group === group && error.code === code;
312
+ }
313
+
314
+ // package.json
315
+ var package_default = {
316
+ name: "rivetkit",
317
+ version: "2.3.0",
318
+ description: "Lightweight libraries for building stateful actors on edge platforms",
319
+ license: "Apache-2.0",
320
+ keywords: [
321
+ "rivetkit",
322
+ "stateful",
323
+ "serverless",
324
+ "actors",
325
+ "agents",
326
+ "realtime",
327
+ "websocket",
328
+ "actors",
329
+ "framework"
330
+ ],
331
+ files: [
332
+ "dist",
333
+ "schemas",
334
+ "src",
335
+ "package.json"
336
+ ],
337
+ type: "module",
338
+ exports: {
339
+ ".": {
340
+ import: {
341
+ types: "./dist/tsup/mod.d.ts",
342
+ default: "./dist/tsup/mod.js"
343
+ },
344
+ require: {
345
+ types: "./dist/tsup/mod.d.cts",
346
+ default: "./dist/tsup/mod.cjs"
291
347
  }
292
348
  },
293
- async exists(p) {
294
- await rootInit;
295
- const path = normPath(p);
296
- const entry = await getEntry(path);
297
- return entry !== void 0;
298
- },
299
- async stat(p) {
300
- await rootInit;
301
- const path = normPath(p);
302
- const entry = await getEntryOrThrow(path);
303
- return rowToStat(entry);
304
- },
305
- async removeFile(p) {
306
- await rootInit;
307
- const path = normPath(p);
308
- const entry = await getEntryOrThrow(path);
309
- if (entry.is_directory === 1) {
310
- throwEISDIR(path);
349
+ "./workflow": {
350
+ import: {
351
+ types: "./dist/tsup/workflow/mod.d.ts",
352
+ default: "./dist/tsup/workflow/mod.js"
353
+ },
354
+ require: {
355
+ types: "./dist/tsup/workflow/mod.d.cts",
356
+ default: "./dist/tsup/workflow/mod.cjs"
311
357
  }
312
- await db2.execute(
313
- "DELETE FROM agent_os_fs_entries WHERE path = ?",
314
- path
315
- );
316
358
  },
317
- async removeDir(p) {
318
- await rootInit;
319
- const path = normPath(p);
320
- const entry = await getEntryOrThrow(path);
321
- if (entry.is_directory !== 1) {
322
- throwENOTDIR(path);
323
- }
324
- const children = await getChildEntries(path);
325
- if (children.length > 0) {
326
- throwENOTEMPTY(path);
359
+ "./test": {
360
+ import: {
361
+ types: "./dist/tsup/test/mod.d.ts",
362
+ default: "./dist/tsup/test/mod.js"
363
+ },
364
+ require: {
365
+ types: "./dist/tsup/test/mod.d.cts",
366
+ default: "./dist/tsup/test/mod.cjs"
327
367
  }
328
- await db2.execute(
329
- "DELETE FROM agent_os_fs_entries WHERE path = ?",
330
- path
331
- );
332
368
  },
333
- async rename(oldPath, newPath) {
334
- await rootInit;
335
- const from = normPath(oldPath);
336
- const to = normPath(newPath);
337
- const entry = await getEntryOrThrow(from);
338
- await ensureParentExists(to);
339
- const destEntry = await getEntry(to);
340
- if (destEntry) {
341
- if (destEntry.is_directory === 1) {
342
- const children = await getChildEntries(to);
343
- if (children.length > 0) {
344
- throwENOTEMPTY(to);
345
- }
346
- }
347
- await db2.execute(
348
- "DELETE FROM agent_os_fs_entries WHERE path = ?",
349
- to
350
- );
351
- }
352
- if (entry.is_directory === 1) {
353
- const prefix = from === "/" ? "/" : `${from}/`;
354
- const newPrefix = to === "/" ? "/" : `${to}/`;
355
- const descendants = await db2.execute(
356
- "SELECT path FROM agent_os_fs_entries WHERE path LIKE ?",
357
- `${prefix}%`
358
- );
359
- for (const desc of descendants) {
360
- const newDescPath = newPrefix + desc.path.slice(prefix.length);
361
- await db2.execute(
362
- "UPDATE agent_os_fs_entries SET path = ? WHERE path = ?",
363
- newDescPath,
364
- desc.path
365
- );
366
- }
369
+ "./db": {
370
+ import: {
371
+ types: "./dist/tsup/db/mod.d.ts",
372
+ default: "./dist/tsup/db/mod.js"
373
+ },
374
+ require: {
375
+ types: "./dist/tsup/db/mod.d.cts",
376
+ default: "./dist/tsup/db/mod.cjs"
367
377
  }
368
- const now = Date.now();
369
- await db2.execute(
370
- "UPDATE agent_os_fs_entries SET path = ?, ctime_ms = ? WHERE path = ?",
371
- to,
372
- now,
373
- from
374
- );
375
378
  },
376
- async realpath(p) {
377
- await rootInit;
378
- const path = normPath(p);
379
- const entry = await getEntryOrThrow(path);
380
- if (entry.symlink_target !== null) {
381
- return normPath(entry.symlink_target);
379
+ "./db/drizzle": {
380
+ import: {
381
+ types: "./dist/tsup/db/drizzle.d.ts",
382
+ default: "./dist/tsup/db/drizzle.js"
383
+ },
384
+ require: {
385
+ types: "./dist/tsup/db/drizzle.d.cts",
386
+ default: "./dist/tsup/db/drizzle.cjs"
382
387
  }
383
- return path;
384
388
  },
385
- async symlink(target, linkPath) {
386
- await rootInit;
387
- const link = normPath(linkPath);
388
- await ensureParentExists(link);
389
- const existing = await getEntry(link);
390
- if (existing) {
391
- throwEEXIST(link);
389
+ "./dynamic": {
390
+ import: {
391
+ types: "./dist/tsup/dynamic/mod.d.ts",
392
+ default: "./dist/tsup/dynamic/mod.js"
393
+ },
394
+ require: {
395
+ types: "./dist/tsup/dynamic/mod.d.cts",
396
+ default: "./dist/tsup/dynamic/mod.cjs"
392
397
  }
393
- const now = Date.now();
394
- await db2.execute(
395
- `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 0, NULL, ?, 0, 0, ?, ?, ?, ?, ?, ?, 1)`,
396
- link,
397
- S_IFLNK | 511,
398
- target.length,
399
- now,
400
- now,
401
- now,
402
- now,
403
- target
404
- );
405
398
  },
406
- async readlink(p) {
407
- await rootInit;
408
- const path = normPath(p);
409
- const entry = await getEntryOrThrow(path);
410
- if (entry.symlink_target === null) {
411
- const err = new Error(`EINVAL: not a symlink: ${path}`);
412
- err.name = "EINVAL";
413
- throw err;
399
+ "./client": {
400
+ import: {
401
+ browser: {
402
+ types: "./dist/browser/client.d.ts",
403
+ default: "./dist/browser/client.js"
404
+ },
405
+ types: "./dist/tsup/client/mod.d.ts",
406
+ default: "./dist/tsup/client/mod.js"
407
+ },
408
+ require: {
409
+ types: "./dist/tsup/client/mod.d.cts",
410
+ default: "./dist/tsup/client/mod.cjs"
414
411
  }
415
- return entry.symlink_target;
416
- },
417
- async lstat(p) {
418
- return backend.stat(p);
419
- },
420
- async link(oldPath, newPath) {
421
- throwENOSYS("link");
422
- },
423
- async chmod(p, mode) {
424
- await rootInit;
425
- const path = normPath(p);
426
- await getEntryOrThrow(path);
427
- const now = Date.now();
428
- await db2.execute(
429
- "UPDATE agent_os_fs_entries SET mode = ?, ctime_ms = ? WHERE path = ?",
430
- mode,
431
- now,
432
- path
433
- );
434
412
  },
435
- async chown(p, uid, gid) {
436
- await rootInit;
437
- const path = normPath(p);
438
- await getEntryOrThrow(path);
439
- const now = Date.now();
440
- await db2.execute(
441
- "UPDATE agent_os_fs_entries SET uid = ?, gid = ?, ctime_ms = ? WHERE path = ?",
442
- uid,
443
- gid,
444
- now,
445
- path
446
- );
413
+ "./log": {
414
+ import: {
415
+ types: "./dist/tsup/common/log.d.ts",
416
+ default: "./dist/tsup/common/log.js"
417
+ },
418
+ require: {
419
+ types: "./dist/tsup/common/log.d.cts",
420
+ default: "./dist/tsup/common/log.cjs"
421
+ }
447
422
  },
448
- async utimes(p, atime, mtime) {
449
- await rootInit;
450
- const path = normPath(p);
451
- await getEntryOrThrow(path);
452
- const now = Date.now();
453
- await db2.execute(
454
- "UPDATE agent_os_fs_entries SET atime_ms = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?",
455
- atime,
456
- mtime,
457
- now,
458
- path
459
- );
423
+ "./errors": {
424
+ import: {
425
+ types: "./dist/tsup/actor/errors.d.ts",
426
+ default: "./dist/tsup/actor/errors.js"
427
+ },
428
+ require: {
429
+ types: "./dist/tsup/actor/errors.d.cts",
430
+ default: "./dist/tsup/actor/errors.cjs"
431
+ }
460
432
  },
461
- async truncate(p, length) {
462
- await rootInit;
463
- const path = normPath(p);
464
- const entry = await getEntryOrThrow(path);
465
- if (entry.is_directory === 1) {
466
- throwEISDIR(path);
433
+ "./inspector": {
434
+ import: {
435
+ types: "./dist/tsup/inspector/mod.d.ts",
436
+ default: "./dist/tsup/inspector/mod.js"
437
+ },
438
+ require: {
439
+ types: "./dist/tsup/inspector/mod.d.cts",
440
+ default: "./dist/tsup/inspector/mod.cjs"
467
441
  }
468
- const existing = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
469
- let newContent;
470
- if (length >= existing.byteLength) {
471
- newContent = new Uint8Array(length);
472
- newContent.set(existing);
473
- } else {
474
- newContent = existing.slice(0, length);
442
+ },
443
+ "./inspector-tab": {
444
+ import: {
445
+ types: "./dist/tsup/inspector-tab/mod.d.ts",
446
+ default: "./dist/tsup/inspector-tab/mod.js"
447
+ },
448
+ require: {
449
+ types: "./dist/tsup/inspector-tab/mod.d.cts",
450
+ default: "./dist/tsup/inspector-tab/mod.cjs"
451
+ }
452
+ },
453
+ "./inspector/client": {
454
+ import: {
455
+ types: "./dist/browser/inspector/client.d.ts",
456
+ default: "./dist/browser/inspector/client.js"
475
457
  }
476
- const now = Date.now();
477
- await db2.execute(
478
- "UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?",
479
- newContent,
480
- length,
481
- now,
482
- now,
483
- path
484
- );
485
458
  },
486
- async pread(p, offset, length) {
487
- await rootInit;
488
- const path = normPath(p);
489
- const entry = await getEntryOrThrow(path);
490
- if (entry.is_directory === 1) {
491
- throwEISDIR(path);
459
+ "./utils": {
460
+ import: {
461
+ types: "./dist/tsup/utils.d.ts",
462
+ default: "./dist/tsup/utils.js"
463
+ },
464
+ require: {
465
+ types: "./dist/tsup/utils.d.cts",
466
+ default: "./dist/tsup/utils.cjs"
492
467
  }
493
- const content = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
494
- const end = Math.min(offset + length, content.byteLength);
495
- if (offset >= content.byteLength) {
496
- return new Uint8Array(0);
468
+ },
469
+ "./agent-os": {
470
+ import: {
471
+ types: "./dist/tsup/agent-os/index.d.ts",
472
+ default: "./dist/tsup/agent-os/index.js"
473
+ },
474
+ require: {
475
+ types: "./dist/tsup/agent-os/index.d.cts",
476
+ default: "./dist/tsup/agent-os/index.cjs"
497
477
  }
498
- return content.slice(offset, end);
478
+ }
479
+ },
480
+ engines: {
481
+ node: ">=22.0.0"
482
+ },
483
+ sideEffects: [
484
+ "./dist/tsup/chunk-*.js",
485
+ "./dist/tsup/chunk-*.cjs"
486
+ ],
487
+ scripts: {
488
+ build: "tsup src/mod.ts src/client/mod.ts src/common/log.ts src/common/websocket.ts src/actor/errors.ts src/utils.ts src/workflow/mod.ts src/test/mod.ts src/inspector/mod.ts src/inspector-tab/mod.ts src/db/mod.ts src/db/drizzle.ts src/dynamic/mod.ts && tsup src/agent-os/index.ts --no-clean --out-dir dist/tsup/agent-os",
489
+ "build:browser": "tsup --config tsup.browser.config.ts",
490
+ "check-types": "tsc --noEmit",
491
+ lint: "biome check . && pnpm run check:test-skips && pnpm run check:wait-for-comments",
492
+ "lint:fix": "biome check --write .",
493
+ "check:test-skips": "tsx scripts/check-annotated-skips.ts",
494
+ "check:wait-for-comments": "tsx scripts/check-wait-for-comments.ts",
495
+ format: "biome format .",
496
+ "format:write": "biome format --write .",
497
+ test: "vitest run",
498
+ "test:platforms": "pnpm run build && RIVETKIT_INCLUDE_PLATFORM_TESTS=1 vitest run tests/platforms --passWithNoTests",
499
+ "test:watch": "vitest",
500
+ "dump-asyncapi": "tsx scripts/dump-asyncapi.ts",
501
+ "registry-config-schema-gen": "tsx scripts/registry-config-schema-gen.ts",
502
+ "actor-config-schema-gen": "tsx scripts/actor-config-schema-gen.ts"
503
+ },
504
+ dependencies: {
505
+ "@hono/node-server": "^1.18.2",
506
+ "@hono/node-ws": "^1.1.1",
507
+ "@hono/zod-openapi": "^1.1.5",
508
+ "@rivet-dev/agent-os-core": "^0.1.1",
509
+ "@rivetkit/bare-ts": "^0.6.2",
510
+ "@rivetkit/engine-cli": "workspace:*",
511
+ "@rivetkit/engine-envoy-protocol": "workspace:*",
512
+ "@rivetkit/on-change": "6.0.1",
513
+ "@rivetkit/rivetkit-napi": "workspace:*",
514
+ "@rivetkit/rivetkit-wasm": "workspace:*",
515
+ "@rivetkit/traces": "workspace:*",
516
+ "@rivetkit/virtual-websocket": "workspace:*",
517
+ "@rivetkit/workflow-engine": "workspace:*",
518
+ "cbor-x": "^1.6.0",
519
+ "drizzle-orm": "^0.44.2",
520
+ "get-port": "^7.1.0",
521
+ hono: "^4.7.0",
522
+ invariant: "^2.2.4",
523
+ "p-retry": "^6.2.1",
524
+ pino: "^9.5.0",
525
+ uuid: "^12.0.0",
526
+ vbare: "^0.0.4",
527
+ zod: "^4.1.0"
528
+ },
529
+ devDependencies: {
530
+ "@biomejs/biome": "^2.3",
531
+ "@copilotkit/llmock": "^1.6.0",
532
+ "@rivet-dev/agent-os-common": "*",
533
+ "@rivet-dev/agent-os-pi": "^0.1.1",
534
+ "@standard-schema/spec": "^1.0.0",
535
+ "@types/invariant": "^2",
536
+ "@types/node": "^22.13.1",
537
+ eventsource: "^4.0.0",
538
+ tsup: "^8.4.0",
539
+ tsx: "^4.19.4",
540
+ typescript: "^5.7.3",
541
+ "vite-tsconfig-paths": "^5.1.4",
542
+ vitest: "^3.1.1",
543
+ ws: "^8.18.1"
544
+ },
545
+ peerDependencies: {
546
+ "drizzle-kit": "^0.31.2",
547
+ eventsource: "^4.0.0",
548
+ ws: "^8.0.0"
549
+ },
550
+ peerDependenciesMeta: {
551
+ "drizzle-kit": {
552
+ optional: true
499
553
  },
500
- async pwrite(p, offset, data) {
501
- await rootInit;
502
- const path = normPath(p);
503
- const entry = await getEntryOrThrow(path);
504
- if (entry.is_directory === 1) {
505
- throwEISDIR(path);
554
+ eventsource: {
555
+ optional: true
556
+ },
557
+ ws: {
558
+ optional: true
559
+ }
560
+ },
561
+ stableVersion: "0.8.0"
562
+ };
563
+
564
+ // src/utils.ts
565
+ var VERSION = package_default.version;
566
+ function getEnvUniversal(key) {
567
+ if (typeof Deno !== "undefined") {
568
+ return Deno.env.get(key);
569
+ } else if (typeof process !== "undefined") {
570
+ return process.env[key];
571
+ }
572
+ }
573
+
574
+ // src/utils/env-vars.ts
575
+ var getLogLevel = () => _nullishCoalesce(getEnvUniversal("RIVET_LOG_LEVEL"), () => ( getEnvUniversal("LOG_LEVEL")));
576
+ var getLogTarget = () => getEnvUniversal("RIVET_LOG_TARGET") === "1";
577
+ var getLogTimestamp = () => getEnvUniversal("RIVET_LOG_TIMESTAMP") === "1";
578
+
579
+ // src/common/log.ts
580
+ var baseLogger;
581
+ var configuredLogLevel;
582
+ var loggerCache = /* @__PURE__ */ new Map();
583
+ var LogLevelSchema = _v4.z.enum([
584
+ "trace",
585
+ "debug",
586
+ "info",
587
+ "warn",
588
+ "error",
589
+ "fatal",
590
+ "silent"
591
+ ]);
592
+ function getPinoLevel(logLevel) {
593
+ if (logLevel) {
594
+ return logLevel;
595
+ }
596
+ if (configuredLogLevel) {
597
+ return configuredLogLevel;
598
+ }
599
+ const raw = (getLogLevel() || "warn").toString().toLowerCase();
600
+ const parsed = LogLevelSchema.safeParse(raw);
601
+ if (parsed.success) {
602
+ return parsed.data;
603
+ }
604
+ return "info";
605
+ }
606
+ function getIncludeTarget() {
607
+ return getLogTarget();
608
+ }
609
+ function configureDefaultLogger(logLevel) {
610
+ if (logLevel) {
611
+ configuredLogLevel = logLevel;
612
+ }
613
+ baseLogger = _pino.pino.call(void 0,
614
+ {
615
+ level: getPinoLevel(logLevel),
616
+ messageKey: "msg",
617
+ // Do not include pid/hostname in output
618
+ base: {},
619
+ errorKey: "error",
620
+ // Keep the numeric level so the logfmt sink can match Pino's levels.
621
+ formatters: {
622
+ level(_label, number) {
623
+ return { level: number };
624
+ }
625
+ },
626
+ timestamp: getLogTimestamp() ? _pino.stdTimeFunctions.epochTime : false
627
+ },
628
+ createLogfmtDestination()
629
+ );
630
+ loggerCache.clear();
631
+ }
632
+ function getBaseLogger() {
633
+ if (!baseLogger) {
634
+ configureDefaultLogger();
635
+ }
636
+ return baseLogger;
637
+ }
638
+ function getLogger(name = "default") {
639
+ const cached = loggerCache.get(name);
640
+ if (cached) {
641
+ return cached;
642
+ }
643
+ const base = getBaseLogger();
644
+ const child = getIncludeTarget() ? base.child({ target: name }) : base;
645
+ loggerCache.set(name, child);
646
+ return child;
647
+ }
648
+ var PINO_LEVEL_LABELS = {
649
+ 10: "trace",
650
+ 20: "debug",
651
+ 30: "info",
652
+ 40: "warn",
653
+ 50: "error",
654
+ 60: "fatal"
655
+ };
656
+ function createLogfmtDestination() {
657
+ return {
658
+ write(msg) {
659
+ var _a;
660
+ const line = formatLogfmtLine(msg);
661
+ if (typeof process !== "undefined" && ((_a = process.stdout) == null ? void 0 : _a.write)) {
662
+ process.stdout.write(`${line}
663
+ `);
664
+ } else {
665
+ console.log(line);
506
666
  }
507
- const content = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
508
- const end = offset + data.byteLength;
509
- const newSize = Math.max(content.byteLength, end);
510
- const buf = new Uint8Array(newSize);
511
- buf.set(content);
512
- buf.set(data, offset);
513
- const now = Date.now();
514
- await db2.execute(
515
- `UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?`,
516
- buf,
517
- newSize,
518
- now,
519
- now,
520
- path
521
- );
522
667
  }
523
- };
524
- return backend;
668
+ };
669
+ }
670
+ function formatLogfmtLine(raw) {
671
+ let data;
672
+ try {
673
+ data = JSON.parse(raw);
674
+ } catch (e2) {
675
+ return raw.trimEnd();
676
+ }
677
+ const parts = [];
678
+ appendLogfmtEntry(parts, "level", formatPinoLevel(data.level));
679
+ if (data.time !== void 0) {
680
+ appendLogfmtEntry(parts, "ts", data.time);
681
+ }
682
+ for (const [key, value] of Object.entries(data)) {
683
+ if (key === "level" || key === "time") {
684
+ continue;
685
+ }
686
+ appendLogfmtEntry(parts, key, value);
687
+ }
688
+ return parts.join(" ");
689
+ }
690
+ function formatPinoLevel(level) {
691
+ if (typeof level === "number") {
692
+ return _nullishCoalesce(PINO_LEVEL_LABELS[level], () => ( level.toString()));
693
+ }
694
+ if (typeof level === "string") {
695
+ return level.toLowerCase();
696
+ }
697
+ return "info";
698
+ }
699
+ function appendLogfmtEntry(parts, key, value) {
700
+ const safeKey = key.replace(/[\s="]/g, "");
701
+ if (safeKey.length === 0) {
702
+ return;
703
+ }
704
+ parts.push(`${safeKey}=${formatLogfmtValue(value)}`);
705
+ }
706
+ function formatLogfmtValue(value) {
707
+ if (typeof value === "number" || typeof value === "boolean") {
708
+ return String(value);
709
+ }
710
+ if (value === null || value === void 0) {
711
+ return "null";
712
+ }
713
+ if (typeof value === "string") {
714
+ return quoteLogfmtString(value);
715
+ }
716
+ return quoteLogfmtString(JSON.stringify(value));
717
+ }
718
+ function quoteLogfmtString(value) {
719
+ if (!/[\s="]/.test(value)) {
720
+ return value;
721
+ }
722
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
525
723
  }
526
724
 
527
- // src/agent-os/actor/index.ts
528
- var _agentoscore = require('@rivet-dev/agent-os-core');
725
+ // src/actor/log.ts
726
+ function loggerWithoutContext() {
727
+ return getLogger("actor-runtime");
728
+ }
529
729
 
530
- // src/actor/config.ts
531
- var _v4 = require('zod/v4');
532
- var DEFAULT_SLEEP_GRACE_PERIOD = 15e3;
533
- var zFunction = () => _v4.z.custom((val) => typeof val === "function");
534
- var WorkflowInspectorConfigSchema = _v4.z.object({
535
- getHistory: zFunction(),
536
- onHistoryUpdated: zFunction().optional(),
537
- replayFromStep: zFunction().optional()
538
- });
539
- var RunInspectorConfigSchema = _v4.z.object({
540
- workflow: WorkflowInspectorConfigSchema.optional()
541
- }).optional();
542
- var RunConfigSchema = _v4.z.object({
543
- /** Display name for the actor in the Inspector UI. */
544
- name: _v4.z.string().optional(),
545
- /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
546
- icon: _v4.z.string().optional(),
547
- /** The run handler function. */
548
- run: zFunction(),
549
- /** Inspector integration for long-running run handlers. */
550
- inspector: RunInspectorConfigSchema.optional()
551
- });
552
- var zRunHandler = _v4.z.union([zFunction(), RunConfigSchema]).optional();
553
- var GlobalActorOptionsBaseSchema = _v4.z.object({
554
- /** Display name for the actor in the Inspector UI. */
555
- name: _v4.z.string().optional(),
556
- /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
557
- icon: _v4.z.string().optional(),
558
- /**
559
- * Can hibernate WebSockets for onWebSocket.
560
- *
561
- * WebSockets using actions/events are hibernatable by default.
562
- *
563
- * @experimental
564
- **/
565
- canHibernateWebSocket: _v4.z.union([_v4.z.boolean(), zFunction()]).default(false)
566
- }).strict();
567
- var GlobalActorOptionsSchema = GlobalActorOptionsBaseSchema.prefault(
568
- () => ({})
569
- );
570
- var InstanceActorOptionsBaseSchema = _v4.z.object({
571
- createVarsTimeout: _v4.z.number().positive().default(5e3),
572
- createConnStateTimeout: _v4.z.number().positive().default(5e3),
573
- onBeforeConnectTimeout: _v4.z.number().positive().default(5e3),
574
- onConnectTimeout: _v4.z.number().positive().default(5e3),
575
- onMigrateTimeout: _v4.z.number().positive().default(3e4),
576
- sleepGracePeriod: _v4.z.number().positive().default(DEFAULT_SLEEP_GRACE_PERIOD),
577
- /** @deprecated `onDestroyTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */
578
- onDestroyTimeout: _v4.z.number().positive().optional(),
579
- /** @deprecated `waitUntilTimeout` is folded into `sleepGracePeriod`, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0. */
580
- waitUntilTimeout: _v4.z.number().positive().optional(),
581
- stateSaveInterval: _v4.z.number().positive().default(1e3),
582
- actionTimeout: _v4.z.number().positive().default(6e4),
583
- connectionLivenessTimeout: _v4.z.number().positive().default(2500),
584
- connectionLivenessInterval: _v4.z.number().positive().default(5e3),
585
- /** @deprecated Use `c.keepAwake(promise)` to scope keep-awake to a specific operation, or keep `noSleep` for actors that must stay awake indefinitely. Will be removed in 2.2.0. */
586
- noSleep: _v4.z.boolean().default(false),
587
- sleepTimeout: _v4.z.number().positive().default(3e4),
588
- maxQueueSize: _v4.z.number().positive().default(1e3),
589
- maxQueueMessageSize: _v4.z.number().positive().default(64 * 1024),
590
- /** Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading. */
591
- preloadMaxWorkflowBytes: _v4.z.number().nonnegative().optional(),
592
- /** Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading. */
593
- preloadMaxConnectionsBytes: _v4.z.number().nonnegative().optional()
594
- }).strict();
595
- var InstanceActorOptionsSchema = InstanceActorOptionsBaseSchema.prefault(() => ({}));
596
- var ActorOptionsSchema = GlobalActorOptionsBaseSchema.extend(
597
- InstanceActorOptionsBaseSchema.shape
598
- ).strict().prefault(() => ({}));
599
- var ActorConfigSchema = _v4.z.object({
600
- onCreate: zFunction().optional(),
601
- onDestroy: zFunction().optional(),
602
- onMigrate: zFunction().optional(),
603
- onWake: zFunction().optional(),
604
- onSleep: zFunction().optional(),
605
- run: zRunHandler,
606
- onStateChange: zFunction().optional(),
607
- onBeforeConnect: zFunction().optional(),
608
- onConnect: zFunction().optional(),
609
- onDisconnect: zFunction().optional(),
610
- onBeforeActionResponse: zFunction().optional(),
611
- onRequest: zFunction().optional(),
612
- onWebSocket: zFunction().optional(),
613
- actions: _v4.z.record(_v4.z.string(), zFunction()).default(() => ({})),
614
- actionInputSchemas: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
615
- connParamsSchema: _v4.z.any().optional(),
616
- events: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
617
- queues: _v4.z.record(_v4.z.string(), _v4.z.any()).optional(),
618
- state: _v4.z.any().optional(),
619
- createState: zFunction().optional(),
620
- connState: _v4.z.any().optional(),
621
- createConnState: zFunction().optional(),
622
- vars: _v4.z.any().optional(),
623
- db: _v4.z.any().optional(),
624
- createVars: zFunction().optional(),
625
- options: ActorOptionsSchema
626
- }).strict().refine(
627
- (data) => !(data.state !== void 0 && data.createState !== void 0),
628
- {
629
- message: "Cannot define both 'state' and 'createState'",
630
- path: ["state"]
730
+ // src/actor/definition.ts
731
+ var warnedDeprecatedTimeoutKeys = /* @__PURE__ */ new Set();
732
+ function warnDeprecatedShutdownTimeoutKeys(options) {
733
+ if (!options || typeof options !== "object") return;
734
+ const opts = options;
735
+ for (const key of ["onDestroyTimeout", "waitUntilTimeout"]) {
736
+ if (opts[key] !== void 0 && !warnedDeprecatedTimeoutKeys.has(key)) {
737
+ warnedDeprecatedTimeoutKeys.add(key);
738
+ loggerWithoutContext().warn({
739
+ msg: `actor option \`${key}\` is deprecated and is now ignored. Configure \`sleepGracePeriod\` instead, which bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0.`
740
+ });
741
+ }
631
742
  }
632
- ).refine(
633
- (data) => !(data.connState !== void 0 && data.createConnState !== void 0),
634
- {
635
- message: "Cannot define both 'connState' and 'createConnState'",
636
- path: ["connState"]
743
+ }
744
+ var ActorDefinition = class {
745
+ #config;
746
+ constructor(config) {
747
+ this.#config = config;
748
+ }
749
+ get config() {
750
+ return this.#config;
751
+ }
752
+ };
753
+ function actor(input) {
754
+ warnDeprecatedShutdownTimeoutKeys(
755
+ input == null ? void 0 : input.options
756
+ );
757
+ const config = ActorConfigSchema.parse(input);
758
+ return new ActorDefinition(config);
759
+ }
760
+
761
+ // src/actor/schema.ts
762
+ function event(options) {
763
+ return _nullishCoalesce(options, () => ( {}));
764
+ }
765
+
766
+ // src/common/database/shared.ts
767
+ function isSqliteBindingValue(value) {
768
+ if (value === null || typeof value === "number" || typeof value === "string" || typeof value === "bigint" || value instanceof Uint8Array) {
769
+ return true;
770
+ }
771
+ if (Array.isArray(value)) {
772
+ return value.every((item) => typeof item === "number");
773
+ }
774
+ return false;
775
+ }
776
+ function isPlainObject(value) {
777
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
778
+ return false;
779
+ }
780
+ return Object.getPrototypeOf(value) === Object.prototype;
781
+ }
782
+ function isSqliteBindingObject(value) {
783
+ if (!isPlainObject(value)) {
784
+ return false;
785
+ }
786
+ return Object.values(value).every((entry) => isSqliteBindingValue(entry));
787
+ }
788
+ function toSqliteBindings(input) {
789
+ if (Array.isArray(input)) {
790
+ for (const value of input) {
791
+ if (!isSqliteBindingValue(value)) {
792
+ throw new Error(
793
+ `unsupported sqlite binding type: ${typeof value}`
794
+ );
795
+ }
796
+ }
797
+ return input;
798
+ }
799
+ if (isSqliteBindingObject(input)) {
800
+ return input;
801
+ }
802
+ throw new Error("unsupported sqlite binding collection");
803
+ }
804
+
805
+ // src/common/database/mod.ts
806
+ function hasMultipleStatements(query) {
807
+ const trimmed = query.trim().replace(/;+$/, "").trimEnd();
808
+ return trimmed.includes(";");
809
+ }
810
+ function db({
811
+ onMigrate
812
+ } = {}) {
813
+ return {
814
+ createClient: async (ctx) => {
815
+ const nativeDatabaseProvider = ctx.nativeDatabaseProvider;
816
+ if (!nativeDatabaseProvider) {
817
+ throw new Error(
818
+ "native SQLite is required, but the current runtime did not provide a native database provider"
819
+ );
820
+ }
821
+ const db2 = await nativeDatabaseProvider.open(ctx.actorId);
822
+ let closed = false;
823
+ const ensureOpen = () => {
824
+ if (closed) {
825
+ throw new Error(
826
+ "Database is closed. This usually means a background timer (setInterval, setTimeout) or a stray promise is still running after the actor stopped. Use c.abortSignal to clean up timers before the actor shuts down."
827
+ );
828
+ }
829
+ };
830
+ const client = {
831
+ execute: async (query, ...args) => {
832
+ var _a, _b, _c, _d;
833
+ ensureOpen();
834
+ const kvReadsBefore = _nullishCoalesce(((_a = ctx.metrics) == null ? void 0 : _a.totalKvReads), () => ( 0));
835
+ const kvWritesBefore = _nullishCoalesce(((_b = ctx.metrics) == null ? void 0 : _b.totalKvWrites), () => ( 0));
836
+ const start = performance.now();
837
+ try {
838
+ if (args.length > 0) {
839
+ const bindings = args.length === 1 && isSqliteBindingObject(args[0]) ? toSqliteBindings(args[0]) : toSqliteBindings(args);
840
+ const { rows, columns } = await db2.execute(
841
+ query,
842
+ bindings
843
+ );
844
+ return rows.map(
845
+ (row) => rowToObject(row, columns)
846
+ );
847
+ }
848
+ if (!hasMultipleStatements(query)) {
849
+ const { rows, columns } = await db2.execute(query);
850
+ return rows.map(
851
+ (row) => rowToObject(row, columns)
852
+ );
853
+ }
854
+ return await execMultiStatement(db2, query);
855
+ } finally {
856
+ const durationMs = performance.now() - start;
857
+ (_c = ctx.metrics) == null ? void 0 : _c.trackSql(query, durationMs);
858
+ if (ctx.metrics) {
859
+ const kvReads = ctx.metrics.totalKvReads - kvReadsBefore;
860
+ const kvWrites = ctx.metrics.totalKvWrites - kvWritesBefore;
861
+ (_d = ctx.log) == null ? void 0 : _d.debug({
862
+ msg: "sql query",
863
+ query: query.slice(0, 120),
864
+ durationMs,
865
+ kvReads,
866
+ kvWrites
867
+ });
868
+ }
869
+ }
870
+ },
871
+ close: async () => {
872
+ if (!closed) {
873
+ closed = true;
874
+ await db2.close();
875
+ }
876
+ },
877
+ nativeMetrics: () => {
878
+ var _a;
879
+ return _nullishCoalesce(((_a = db2.nativeMetrics) == null ? void 0 : _a.call(db2)), () => ( null));
880
+ }
881
+ };
882
+ return client;
883
+ },
884
+ onMigrate: async (client) => {
885
+ if (onMigrate) {
886
+ await withMigrationSavepoint(client, () => onMigrate(client));
887
+ }
888
+ }
889
+ };
890
+ }
891
+ function rowToObject(row, columns) {
892
+ const rowObj = {};
893
+ for (let i = 0; i < columns.length; i++) {
894
+ rowObj[columns[i]] = row[i];
637
895
  }
638
- ).refine(
639
- (data) => !(data.vars !== void 0 && data.createVars !== void 0),
640
- {
641
- message: "Cannot define both 'vars' and 'createVars'",
642
- path: ["vars"]
896
+ return rowObj;
897
+ }
898
+ async function execMultiStatement(db2, query) {
899
+ const results = [];
900
+ let columnNames = null;
901
+ await db2.exec(query, (row, columns) => {
902
+ if (!columnNames) {
903
+ columnNames = columns;
904
+ }
905
+ results.push(rowToObject(row, columnNames));
906
+ });
907
+ return results;
908
+ }
909
+ async function withMigrationSavepoint(client, callback) {
910
+ await client.execute("SAVEPOINT __rivet_on_migrate");
911
+ try {
912
+ const result = await callback();
913
+ await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
914
+ return result;
915
+ } catch (error) {
916
+ try {
917
+ await client.execute("ROLLBACK TO SAVEPOINT __rivet_on_migrate");
918
+ } finally {
919
+ await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
920
+ }
921
+ throw error;
643
922
  }
923
+ }
924
+
925
+ // src/agent-os/config.ts
926
+
927
+ var zFunction2 = () => _v4.z.custom((val) => typeof val === "function");
928
+ var AgentOsOptionsSchema = _v4.z.custom(
929
+ (val) => typeof val === "object" && val !== null
644
930
  );
645
- var DocActorOptionsSchema = _v4.z.object({
646
- name: _v4.z.string().optional().describe("Display name for the actor in the Inspector UI."),
647
- icon: _v4.z.string().optional().describe(
648
- "Icon for the actor in the Inspector UI. Can be an emoji (e.g., '\u{1F680}') or FontAwesome icon name (e.g., 'rocket')."
649
- ),
650
- createVarsTimeout: _v4.z.number().optional().describe("Timeout in ms for createVars handler. Default: 5000"),
651
- createConnStateTimeout: _v4.z.number().optional().describe(
652
- "Timeout in ms for createConnState handler. Default: 5000"
653
- ),
654
- onMigrateTimeout: _v4.z.number().optional().describe("Timeout in ms for onMigrate handler. Default: 30000"),
655
- onBeforeConnectTimeout: _v4.z.number().optional().describe(
656
- "Timeout in ms for onBeforeConnect handler. Default: 5000"
657
- ),
658
- onConnectTimeout: _v4.z.number().optional().describe("Timeout in ms for onConnect handler. Default: 5000"),
659
- sleepGracePeriod: _v4.z.number().optional().describe(
660
- `Max time in ms for the graceful shutdown window. Covers lifecycle hooks (onSleep, onDestroy), the run handler wait, async raw WebSocket handlers, disconnect callbacks, and final state serialization. Default: ${DEFAULT_SLEEP_GRACE_PERIOD}.`
661
- ),
662
- onDestroyTimeout: _v4.z.number().optional().describe(
663
- "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0."
664
- ),
665
- waitUntilTimeout: _v4.z.number().optional().describe(
666
- "Deprecated. Folded into sleepGracePeriod, which now bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0."
667
- ),
668
- stateSaveInterval: _v4.z.number().optional().describe(
669
- "Interval in ms between automatic state saves. Default: 1000"
670
- ),
671
- actionTimeout: _v4.z.number().optional().describe("Timeout in ms for action handlers. Default: 60000"),
672
- connectionLivenessTimeout: _v4.z.number().optional().describe(
673
- "Timeout in ms for connection liveness checks. Default: 2500"
674
- ),
675
- connectionLivenessInterval: _v4.z.number().optional().describe(
676
- "Interval in ms between connection liveness checks. Default: 5000"
677
- ),
678
- noSleep: _v4.z.boolean().optional().describe(
679
- "Deprecated. If true, the actor will never sleep. Use c.keepAwake(promise) to scope keep-awake to a specific operation instead. Default: false"
680
- ),
681
- sleepTimeout: _v4.z.number().optional().describe(
682
- "Time in ms of inactivity before the actor sleeps. Default: 30000"
683
- ),
684
- maxQueueSize: _v4.z.number().optional().describe(
685
- "Maximum number of queue messages before rejecting new messages. Default: 1000"
686
- ),
687
- maxQueueMessageSize: _v4.z.number().optional().describe(
688
- "Maximum size of each queue message in bytes. Default: 65536"
689
- ),
690
- canHibernateWebSocket: _v4.z.boolean().optional().describe(
691
- "Whether WebSockets using onWebSocket can be hibernated. WebSockets using actions/events are hibernatable by default. Default: false"
692
- ),
693
- preloadMaxWorkflowBytes: _v4.z.number().optional().describe(
694
- "Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading."
695
- ),
696
- preloadMaxConnectionsBytes: _v4.z.number().optional().describe(
697
- "Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading."
698
- )
699
- }).describe("Actor options for timeouts and behavior configuration.");
700
- var DocActorConfigSchema = _v4.z.object({
701
- state: _v4.z.unknown().optional().describe(
702
- "Initial state value for the actor. Cannot be used with createState."
703
- ),
704
- createState: _v4.z.unknown().optional().describe(
705
- "Function to create initial state. Receives context and input. Cannot be used with state."
706
- ),
707
- connState: _v4.z.unknown().optional().describe(
708
- "Initial connection state value. Cannot be used with createConnState."
709
- ),
710
- createConnState: _v4.z.unknown().optional().describe(
711
- "Function to create connection state. Receives context and connection params. The pending connection is not visible in c.conns until this succeeds. Cannot be used with connState."
712
- ),
713
- vars: _v4.z.unknown().optional().describe(
714
- "Initial ephemeral variables value. Cannot be used with createVars."
715
- ),
716
- createVars: _v4.z.unknown().optional().describe(
717
- "Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars."
718
- ),
719
- db: _v4.z.unknown().optional().describe("Database provider instance for the actor."),
720
- onCreate: _v4.z.unknown().optional().describe(
721
- "Called when the actor is first initialized. Use to initialize state."
722
- ),
723
- onDestroy: _v4.z.unknown().optional().describe("Called when the actor is destroyed."),
724
- onMigrate: _v4.z.unknown().optional().describe(
725
- "Called on every actor start after persisted state loads and before onWake. Use for repeatable schema migrations."
726
- ),
727
- onWake: _v4.z.unknown().optional().describe(
728
- "Called when the actor wakes up and is ready to receive connections and actions."
729
- ),
730
- onSleep: _v4.z.unknown().optional().describe(
731
- "Called when the actor is stopping or sleeping. Use to clean up resources."
732
- ),
733
- run: _v4.z.unknown().optional().describe(
734
- "Called after actor starts. Does not block startup. Use for background tasks like queue processing or tick loops. If it exits, the actor follows the normal idle sleep timeout once idle. If it throws, the actor logs the error and then follows the normal idle sleep timeout once idle."
735
- ),
736
- onStateChange: _v4.z.unknown().optional().describe(
737
- "Called when the actor's state changes. State changes within this hook won't trigger recursion."
738
- ),
739
- onBeforeConnect: _v4.z.unknown().optional().describe(
740
- "Called before a client connects. Throw an error to reject the connection. The pending connection is not visible in c.conns while this runs."
741
- ),
742
- onConnect: _v4.z.unknown().optional().describe(
743
- "Called when a client successfully connects. The connection is visible in c.conns before this runs."
744
- ),
745
- onDisconnect: _v4.z.unknown().optional().describe("Called when a client disconnects."),
746
- onBeforeActionResponse: _v4.z.unknown().optional().describe(
747
- "Called before sending an action response. Use to transform output."
748
- ),
749
- onRequest: _v4.z.unknown().optional().describe(
750
- "Called for raw HTTP requests to /actors/{name}/http/* endpoints."
751
- ),
752
- onWebSocket: _v4.z.unknown().optional().describe(
753
- "Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints."
754
- ),
755
- actions: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe(
756
- "Map of action name to handler function. Defaults to an empty object."
757
- ),
758
- actionInputSchemas: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe(
759
- "Optional schema map for validating action argument tuples in native runtimes."
760
- ),
761
- connParamsSchema: _v4.z.unknown().optional().describe(
762
- "Optional schema for validating connection params in native runtimes."
763
- ),
764
- events: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe("Map of event names to schemas."),
765
- queues: _v4.z.record(_v4.z.string(), _v4.z.unknown()).optional().describe("Map of queue names to schemas."),
766
- options: DocActorOptionsSchema.optional()
767
- }).describe("Actor configuration passed to the actor() function.");
931
+ var agentOsActorConfigSchema = _v4.z.object({
932
+ options: AgentOsOptionsSchema.optional(),
933
+ preview: _v4.z.object({
934
+ defaultExpiresInSeconds: _v4.z.number().positive().default(3600),
935
+ maxExpiresInSeconds: _v4.z.number().positive().default(86400)
936
+ }).strict().prefault(() => ({})),
937
+ onBeforeConnect: zFunction2().optional(),
938
+ onSessionEvent: zFunction2().optional(),
939
+ onPermissionRequest: zFunction2().optional()
940
+ }).strict();
768
941
 
769
- // src/common/log.ts
942
+ // src/agent-os/actor/db.ts
943
+ async function migrateAgentOsTables(db2) {
944
+ await db2.execute(`
945
+ CREATE TABLE IF NOT EXISTS agent_os_preview_tokens (
946
+ token TEXT PRIMARY KEY,
947
+ port INTEGER NOT NULL,
948
+ created_at INTEGER NOT NULL,
949
+ expires_at INTEGER NOT NULL
950
+ );
951
+
952
+ CREATE INDEX IF NOT EXISTS idx_preview_tokens_expires_at
953
+ ON agent_os_preview_tokens(expires_at);
770
954
 
955
+ CREATE TABLE IF NOT EXISTS agent_os_fs_entries (
956
+ path TEXT PRIMARY KEY,
957
+ is_directory INTEGER NOT NULL DEFAULT 0,
958
+ content BLOB,
959
+ mode INTEGER NOT NULL DEFAULT 33188,
960
+ uid INTEGER NOT NULL DEFAULT 0,
961
+ gid INTEGER NOT NULL DEFAULT 0,
962
+ size INTEGER NOT NULL DEFAULT 0,
963
+ atime_ms INTEGER NOT NULL,
964
+ mtime_ms INTEGER NOT NULL,
965
+ ctime_ms INTEGER NOT NULL,
966
+ birthtime_ms INTEGER NOT NULL,
967
+ symlink_target TEXT,
968
+ nlink INTEGER NOT NULL DEFAULT 1
969
+ );
771
970
 
971
+ CREATE INDEX IF NOT EXISTS idx_fs_entries_parent
972
+ ON agent_os_fs_entries(path);
772
973
 
773
- var _pino = require('pino');
974
+ CREATE TABLE IF NOT EXISTS agent_os_sessions (
975
+ session_id TEXT PRIMARY KEY,
976
+ agent_type TEXT NOT NULL,
977
+ capabilities TEXT NOT NULL,
978
+ agent_info TEXT,
979
+ created_at INTEGER NOT NULL
980
+ );
774
981
 
982
+ CREATE TABLE IF NOT EXISTS agent_os_session_events (
983
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
984
+ session_id TEXT NOT NULL,
985
+ seq INTEGER NOT NULL,
986
+ event TEXT NOT NULL,
987
+ created_at INTEGER NOT NULL,
988
+ FOREIGN KEY (session_id) REFERENCES agent_os_sessions(session_id) ON DELETE CASCADE
989
+ );
775
990
 
776
- // src/actor/errors.ts
777
- function isTypedErrorTag(value) {
778
- return value === "ActorError" || value === "RivetError";
779
- }
780
- function isRivetErrorLike(error) {
781
- return typeof error === "object" && error !== null && "group" in error && typeof error.group === "string" && "code" in error && typeof error.code === "string" && "message" in error && typeof error.message === "string" && (!("__type" in error) || isTypedErrorTag(error.__type));
782
- }
783
- function isRivetErrorCode(error, group, code) {
784
- return isRivetErrorLike(error) && error.group === group && error.code === code;
991
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_seq
992
+ ON agent_os_session_events(session_id, seq);
993
+ `);
785
994
  }
786
995
 
787
- // package.json
788
- var package_default = {
789
- name: "rivetkit",
790
- version: "2.3.0-rc.8",
791
- description: "Lightweight libraries for building stateful actors on edge platforms",
792
- license: "Apache-2.0",
793
- keywords: [
794
- "rivetkit",
795
- "stateful",
796
- "serverless",
797
- "actors",
798
- "agents",
799
- "realtime",
800
- "websocket",
801
- "actors",
802
- "framework"
803
- ],
804
- files: [
805
- "dist",
806
- "schemas",
807
- "src",
808
- "package.json"
809
- ],
810
- type: "module",
811
- exports: {
812
- ".": {
813
- import: {
814
- types: "./dist/tsup/mod.d.ts",
815
- default: "./dist/tsup/mod.js"
816
- },
817
- require: {
818
- types: "./dist/tsup/mod.d.cts",
819
- default: "./dist/tsup/mod.cjs"
820
- }
996
+ // src/agent-os/actor/filesystem.ts
997
+ function buildFilesystemActions(config) {
998
+ return {
999
+ readFile: async (c, path) => {
1000
+ const agentOs2 = await ensureVm(c, config);
1001
+ return agentOs2.readFile(path);
821
1002
  },
822
- "./workflow": {
823
- import: {
824
- types: "./dist/tsup/workflow/mod.d.ts",
825
- default: "./dist/tsup/workflow/mod.js"
826
- },
827
- require: {
828
- types: "./dist/tsup/workflow/mod.d.cts",
829
- default: "./dist/tsup/workflow/mod.cjs"
830
- }
1003
+ writeFile: async (c, path, content) => {
1004
+ const agentOs2 = await ensureVm(c, config);
1005
+ await agentOs2.writeFile(path, content);
831
1006
  },
832
- "./test": {
833
- import: {
834
- types: "./dist/tsup/test/mod.d.ts",
835
- default: "./dist/tsup/test/mod.js"
836
- },
837
- require: {
838
- types: "./dist/tsup/test/mod.d.cts",
839
- default: "./dist/tsup/test/mod.cjs"
840
- }
1007
+ readFiles: async (c, paths) => {
1008
+ const agentOs2 = await ensureVm(c, config);
1009
+ return agentOs2.readFiles(paths);
841
1010
  },
842
- "./db": {
843
- import: {
844
- types: "./dist/tsup/db/mod.d.ts",
845
- default: "./dist/tsup/db/mod.js"
846
- },
847
- require: {
848
- types: "./dist/tsup/db/mod.d.cts",
849
- default: "./dist/tsup/db/mod.cjs"
1011
+ writeFiles: async (c, entries) => {
1012
+ const agentOs2 = await ensureVm(c, config);
1013
+ return agentOs2.writeFiles(entries);
1014
+ },
1015
+ mkdir: async (c, path, options) => {
1016
+ const agentOs2 = await ensureVm(c, config);
1017
+ await agentOs2.mkdir(path, options);
1018
+ },
1019
+ readdir: async (c, path) => {
1020
+ const agentOs2 = await ensureVm(c, config);
1021
+ return agentOs2.readdir(path);
1022
+ },
1023
+ readdirRecursive: async (c, path, options) => {
1024
+ const agentOs2 = await ensureVm(c, config);
1025
+ return agentOs2.readdirRecursive(path, options);
1026
+ },
1027
+ stat: async (c, path) => {
1028
+ const agentOs2 = await ensureVm(c, config);
1029
+ return agentOs2.stat(path);
1030
+ },
1031
+ exists: async (c, path) => {
1032
+ const agentOs2 = await ensureVm(c, config);
1033
+ return agentOs2.exists(path);
1034
+ },
1035
+ move: async (c, from, to) => {
1036
+ const agentOs2 = await ensureVm(c, config);
1037
+ await agentOs2.move(from, to);
1038
+ },
1039
+ deleteFile: async (c, path, options) => {
1040
+ const agentOs2 = await ensureVm(c, config);
1041
+ await agentOs2.delete(path, options);
1042
+ },
1043
+ // TODO: mountFs and unmountFs are not exposed as actor actions because
1044
+ // filesystem drivers (VirtualFileSystem) are not serializable over the
1045
+ // network. Mount filesystems via the `options.mounts` config in agentOs()
1046
+ // instead. See: https://github.com/rivet-dev/rivet/issues/XXXX
1047
+ listAgents: async (c) => {
1048
+ const agentOs2 = await ensureVm(c, config);
1049
+ return agentOs2.listAgents();
1050
+ }
1051
+ };
1052
+ }
1053
+
1054
+ // src/agent-os/actor/network.ts
1055
+ function buildNetworkActions(config) {
1056
+ return {
1057
+ vmFetch: async (c, port, url, options) => {
1058
+ const agentOs2 = await ensureVm(c, config);
1059
+ const headers = new Headers(options == null ? void 0 : options.headers);
1060
+ const request = new Request(url, {
1061
+ method: _nullishCoalesce((options == null ? void 0 : options.method), () => ( "GET")),
1062
+ headers,
1063
+ body: _nullishCoalesce((options == null ? void 0 : options.body), () => ( null))
1064
+ });
1065
+ const response = await agentOs2.fetch(port, request);
1066
+ const responseHeaders = {};
1067
+ response.headers.forEach((value, key) => {
1068
+ responseHeaders[key] = value;
1069
+ });
1070
+ const body = new Uint8Array(await response.arrayBuffer());
1071
+ return {
1072
+ status: response.status,
1073
+ statusText: response.statusText,
1074
+ headers: responseHeaders,
1075
+ body
1076
+ };
1077
+ }
1078
+ };
1079
+ }
1080
+
1081
+ // src/agent-os/actor/preview.ts
1082
+ var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
1083
+ function generateToken() {
1084
+ const bytes = _crypto2.default.randomBytes(32);
1085
+ const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
1086
+ let token = "";
1087
+ for (let i = 0; i < 32; i++) {
1088
+ token += alphabet[bytes[i] % alphabet.length];
1089
+ }
1090
+ return token;
1091
+ }
1092
+ var CORS_HEADERS = {
1093
+ "Access-Control-Allow-Origin": "*",
1094
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
1095
+ "Access-Control-Allow-Headers": "*"
1096
+ };
1097
+ function addCorsHeaders(response) {
1098
+ const headers = new Headers(response.headers);
1099
+ for (const [key, value] of Object.entries(CORS_HEADERS)) {
1100
+ headers.set(key, value);
1101
+ }
1102
+ return new Response(response.body, {
1103
+ status: response.status,
1104
+ statusText: response.statusText,
1105
+ headers
1106
+ });
1107
+ }
1108
+ function buildOnRequestHandler(config) {
1109
+ return async (c, request) => {
1110
+ var _a;
1111
+ const url = new URL(request.url);
1112
+ const pathname = url.pathname;
1113
+ const match = pathname.match(/^\/fetch\/([a-z0-9]+)(\/.*)?$/);
1114
+ if (!match) {
1115
+ return new Response("Not Found", { status: 404 });
1116
+ }
1117
+ if (request.method === "OPTIONS") {
1118
+ return new Response(null, { status: 204, headers: CORS_HEADERS });
1119
+ }
1120
+ const token = match[1];
1121
+ const remainingPath = _nullishCoalesce(match[2], () => ( "/"));
1122
+ const now = Date.now();
1123
+ const rows = await c.db.execute(
1124
+ `SELECT port FROM agent_os_preview_tokens WHERE token = ? AND expires_at > ?`,
1125
+ token,
1126
+ now
1127
+ );
1128
+ if (rows.length === 0) {
1129
+ c.log.warn({ msg: "agent-os preview auth failed", token });
1130
+ return addCorsHeaders(new Response("Forbidden", { status: 403 }));
1131
+ }
1132
+ const port = (_a = rows[0]) == null ? void 0 : _a.port;
1133
+ const agentOs2 = await ensureVm(
1134
+ c,
1135
+ config
1136
+ );
1137
+ const vmUrl = `http://localhost:${port}${remainingPath}${url.search}`;
1138
+ const vmRequest = new Request(vmUrl, {
1139
+ method: request.method,
1140
+ headers: request.headers,
1141
+ body: request.body,
1142
+ duplex: "half"
1143
+ });
1144
+ const vmResponse = await agentOs2.fetch(port, vmRequest);
1145
+ c.log.info({
1146
+ msg: "agent-os preview request proxied",
1147
+ port,
1148
+ method: request.method,
1149
+ path: remainingPath,
1150
+ status: vmResponse.status
1151
+ });
1152
+ return addCorsHeaders(vmResponse);
1153
+ };
1154
+ }
1155
+ function buildPreviewActions(config) {
1156
+ return {
1157
+ createSignedPreviewUrl: async (c, port, expiresInSeconds) => {
1158
+ await ensureVm(c, config);
1159
+ const effectiveExpires = _nullishCoalesce(expiresInSeconds, () => ( config.preview.defaultExpiresInSeconds));
1160
+ const maxExpires = config.preview.maxExpiresInSeconds;
1161
+ if (effectiveExpires < 1 || effectiveExpires > maxExpires) {
1162
+ throw new Error(
1163
+ `expiresInSeconds must be between 1 and ${maxExpires}`
1164
+ );
850
1165
  }
1166
+ const token = generateToken();
1167
+ const now = Date.now();
1168
+ const expiresAt = now + effectiveExpires * 1e3;
1169
+ await c.db.execute(
1170
+ `INSERT INTO agent_os_preview_tokens (token, port, created_at, expires_at)
1171
+ VALUES (?, ?, ?, ?)`,
1172
+ token,
1173
+ port,
1174
+ now,
1175
+ expiresAt
1176
+ );
1177
+ await c.db.execute(
1178
+ `DELETE FROM agent_os_preview_tokens WHERE expires_at <= ?`,
1179
+ now
1180
+ );
1181
+ const path = `/request/fetch/${token}`;
1182
+ c.log.info({
1183
+ msg: "agent-os preview token created",
1184
+ port,
1185
+ expiresInSeconds: effectiveExpires
1186
+ });
1187
+ return { path, token, port, expiresAt };
851
1188
  },
852
- "./db/drizzle": {
853
- import: {
854
- types: "./dist/tsup/db/drizzle.d.ts",
855
- default: "./dist/tsup/db/drizzle.js"
856
- },
857
- require: {
858
- types: "./dist/tsup/db/drizzle.d.cts",
859
- default: "./dist/tsup/db/drizzle.cjs"
860
- }
1189
+ expireSignedPreviewUrl: async (c, token) => {
1190
+ await c.db.execute(
1191
+ `DELETE FROM agent_os_preview_tokens WHERE token = ?`,
1192
+ token
1193
+ );
1194
+ c.log.info({ msg: "agent-os preview token expired", token });
1195
+ }
1196
+ };
1197
+ }
1198
+
1199
+ // src/agent-os/actor/process.ts
1200
+ function broadcastProcessEvent(c, name, payload) {
1201
+ try {
1202
+ c.broadcast(name, payload);
1203
+ } catch (error) {
1204
+ if (isRivetErrorCode(error, "actor", "stopping")) {
1205
+ return;
1206
+ }
1207
+ throw error;
1208
+ }
1209
+ }
1210
+ function buildProcessActions(config) {
1211
+ return {
1212
+ exec: async (c, command, options) => {
1213
+ const agentOs2 = await ensureVm(c, config);
1214
+ return agentOs2.exec(command, options);
861
1215
  },
862
- "./client": {
863
- import: {
864
- browser: {
865
- types: "./dist/browser/client.d.ts",
866
- default: "./dist/browser/client.js"
1216
+ spawn: async (c, command, args, options) => {
1217
+ const agentOs2 = await ensureVm(c, config);
1218
+ const { pid } = agentOs2.spawn(command, args, {
1219
+ ...options,
1220
+ onStdout: (data) => {
1221
+ var _a;
1222
+ broadcastProcessEvent(c, "processOutput", {
1223
+ pid,
1224
+ stream: "stdout",
1225
+ data
1226
+ });
1227
+ (_a = options == null ? void 0 : options.onStdout) == null ? void 0 : _a.call(options, data);
867
1228
  },
868
- types: "./dist/tsup/client/mod.d.ts",
869
- default: "./dist/tsup/client/mod.js"
870
- },
871
- require: {
872
- types: "./dist/tsup/client/mod.d.cts",
873
- default: "./dist/tsup/client/mod.cjs"
874
- }
1229
+ onStderr: (data) => {
1230
+ var _a;
1231
+ broadcastProcessEvent(c, "processOutput", {
1232
+ pid,
1233
+ stream: "stderr",
1234
+ data
1235
+ });
1236
+ (_a = options == null ? void 0 : options.onStderr) == null ? void 0 : _a.call(options, data);
1237
+ }
1238
+ });
1239
+ c.vars.activeProcesses.add(pid);
1240
+ syncPreventSleep(c);
1241
+ c.log.info({
1242
+ msg: "agent-os process spawned",
1243
+ pid,
1244
+ command
1245
+ });
1246
+ agentOs2.waitProcess(pid).then((exitCode) => {
1247
+ broadcastProcessEvent(c, "processExit", { pid, exitCode });
1248
+ c.log.info({
1249
+ msg: "agent-os process exited",
1250
+ pid,
1251
+ exitCode
1252
+ });
1253
+ }).catch(() => {
1254
+ }).finally(() => {
1255
+ c.vars.activeProcesses.delete(pid);
1256
+ syncPreventSleep(c);
1257
+ });
1258
+ return { pid };
875
1259
  },
876
- "./log": {
877
- import: {
878
- types: "./dist/tsup/common/log.d.ts",
879
- default: "./dist/tsup/common/log.js"
880
- },
881
- require: {
882
- types: "./dist/tsup/common/log.d.cts",
883
- default: "./dist/tsup/common/log.cjs"
884
- }
1260
+ writeProcessStdin: async (c, pid, data) => {
1261
+ const agentOs2 = await ensureVm(c, config);
1262
+ agentOs2.writeProcessStdin(pid, data);
885
1263
  },
886
- "./errors": {
887
- import: {
888
- types: "./dist/tsup/actor/errors.d.ts",
889
- default: "./dist/tsup/actor/errors.js"
890
- },
891
- require: {
892
- types: "./dist/tsup/actor/errors.d.cts",
893
- default: "./dist/tsup/actor/errors.cjs"
894
- }
1264
+ closeProcessStdin: async (c, pid) => {
1265
+ const agentOs2 = await ensureVm(c, config);
1266
+ agentOs2.closeProcessStdin(pid);
895
1267
  },
896
- "./inspector": {
897
- import: {
898
- types: "./dist/tsup/inspector/mod.d.ts",
899
- default: "./dist/tsup/inspector/mod.js"
900
- },
901
- require: {
902
- types: "./dist/tsup/inspector/mod.d.cts",
903
- default: "./dist/tsup/inspector/mod.cjs"
904
- }
1268
+ waitProcess: async (c, pid) => {
1269
+ const agentOs2 = await ensureVm(c, config);
1270
+ return agentOs2.waitProcess(pid);
905
1271
  },
906
- "./inspector/client": {
907
- import: {
908
- types: "./dist/browser/inspector/client.d.ts",
909
- default: "./dist/browser/inspector/client.js"
910
- }
1272
+ listProcesses: async (c) => {
1273
+ const agentOs2 = await ensureVm(c, config);
1274
+ return agentOs2.listProcesses();
911
1275
  },
912
- "./utils": {
913
- import: {
914
- types: "./dist/tsup/utils.d.ts",
915
- default: "./dist/tsup/utils.js"
916
- },
917
- require: {
918
- types: "./dist/tsup/utils.d.cts",
919
- default: "./dist/tsup/utils.cjs"
920
- }
1276
+ allProcesses: async (c) => {
1277
+ const agentOs2 = await ensureVm(c, config);
1278
+ return agentOs2.allProcesses();
921
1279
  },
922
- "./agent-os": {
923
- import: {
924
- types: "./dist/tsup/agent-os/index.d.ts",
925
- default: "./dist/tsup/agent-os/index.js"
926
- },
927
- require: {
928
- types: "./dist/tsup/agent-os/index.d.cts",
929
- default: "./dist/tsup/agent-os/index.cjs"
930
- }
931
- }
932
- },
933
- engines: {
934
- node: ">=22.0.0"
935
- },
936
- sideEffects: [
937
- "./dist/tsup/chunk-*.js",
938
- "./dist/tsup/chunk-*.cjs"
939
- ],
940
- scripts: {
941
- build: "tsup src/mod.ts src/client/mod.ts src/common/log.ts src/common/websocket.ts src/actor/errors.ts src/utils.ts src/workflow/mod.ts src/test/mod.ts src/inspector/mod.ts src/db/mod.ts src/db/drizzle.ts && tsup src/agent-os/index.ts --no-clean --out-dir dist/tsup/agent-os",
942
- "build:browser": "tsup --config tsup.browser.config.ts",
943
- "check-types": "tsc --noEmit",
944
- lint: "biome check . && pnpm run check:test-skips && pnpm run check:wait-for-comments",
945
- "lint:fix": "biome check --write .",
946
- "check:test-skips": "tsx scripts/check-annotated-skips.ts",
947
- "check:wait-for-comments": "tsx scripts/check-wait-for-comments.ts",
948
- format: "biome format .",
949
- "format:write": "biome format --write .",
950
- test: "vitest run",
951
- "test:platforms": "pnpm run build && RIVETKIT_INCLUDE_PLATFORM_TESTS=1 vitest run tests/platforms --passWithNoTests",
952
- "test:watch": "vitest",
953
- "dump-asyncapi": "tsx scripts/dump-asyncapi.ts",
954
- "registry-config-schema-gen": "tsx scripts/registry-config-schema-gen.ts",
955
- "actor-config-schema-gen": "tsx scripts/actor-config-schema-gen.ts"
956
- },
957
- dependencies: {
958
- "@hono/node-server": "^1.18.2",
959
- "@hono/node-ws": "^1.1.1",
960
- "@hono/zod-openapi": "^1.1.5",
961
- "@rivet-dev/agent-os-core": "^0.1.1",
962
- "@rivetkit/bare-ts": "^0.6.2",
963
- "@rivetkit/engine-cli": "workspace:*",
964
- "@rivetkit/engine-envoy-protocol": "workspace:*",
965
- "@rivetkit/on-change": "6.0.1",
966
- "@rivetkit/rivetkit-napi": "workspace:*",
967
- "@rivetkit/rivetkit-wasm": "workspace:*",
968
- "@rivetkit/traces": "workspace:*",
969
- "@rivetkit/virtual-websocket": "workspace:*",
970
- "@rivetkit/workflow-engine": "workspace:*",
971
- "cbor-x": "^1.6.0",
972
- "drizzle-orm": "^0.44.2",
973
- "get-port": "^7.1.0",
974
- hono: "^4.7.0",
975
- invariant: "^2.2.4",
976
- "p-retry": "^6.2.1",
977
- pino: "^9.5.0",
978
- uuid: "^12.0.0",
979
- vbare: "^0.0.4",
980
- zod: "^4.1.0"
981
- },
982
- devDependencies: {
983
- "@biomejs/biome": "^2.3",
984
- "@copilotkit/llmock": "^1.6.0",
985
- "@rivet-dev/agent-os-common": "*",
986
- "@rivet-dev/agent-os-pi": "^0.1.1",
987
- "@standard-schema/spec": "^1.0.0",
988
- "@types/invariant": "^2",
989
- "@types/node": "^22.13.1",
990
- eventsource: "^4.0.0",
991
- tsup: "^8.4.0",
992
- tsx: "^4.19.4",
993
- typescript: "^5.7.3",
994
- "vite-tsconfig-paths": "^5.1.4",
995
- vitest: "^3.1.1",
996
- ws: "^8.18.1"
997
- },
998
- peerDependencies: {
999
- "drizzle-kit": "^0.31.2",
1000
- eventsource: "^4.0.0",
1001
- ws: "^8.0.0"
1002
- },
1003
- peerDependenciesMeta: {
1004
- "drizzle-kit": {
1005
- optional: true
1280
+ processTree: async (c) => {
1281
+ const agentOs2 = await ensureVm(c, config);
1282
+ return agentOs2.processTree();
1283
+ },
1284
+ getProcess: async (c, pid) => {
1285
+ const agentOs2 = await ensureVm(c, config);
1286
+ return agentOs2.getProcess(pid);
1006
1287
  },
1007
- eventsource: {
1008
- optional: true
1288
+ stopProcess: async (c, pid) => {
1289
+ const agentOs2 = await ensureVm(c, config);
1290
+ agentOs2.stopProcess(pid);
1009
1291
  },
1010
- ws: {
1011
- optional: true
1292
+ killProcess: async (c, pid) => {
1293
+ const agentOs2 = await ensureVm(c, config);
1294
+ agentOs2.killProcess(pid);
1012
1295
  }
1013
- },
1014
- stableVersion: "0.8.0"
1015
- };
1016
-
1017
- // src/utils.ts
1018
- var VERSION = package_default.version;
1019
- function getEnvUniversal(key) {
1020
- if (typeof Deno !== "undefined") {
1021
- return Deno.env.get(key);
1022
- } else if (typeof process !== "undefined") {
1023
- return process.env[key];
1024
- }
1296
+ };
1025
1297
  }
1026
1298
 
1027
- // src/utils/env-vars.ts
1028
- var getLogLevel = () => _nullishCoalesce(getEnvUniversal("RIVET_LOG_LEVEL"), () => ( getEnvUniversal("LOG_LEVEL")));
1029
- var getLogTarget = () => getEnvUniversal("RIVET_LOG_TARGET") === "1";
1030
- var getLogTimestamp = () => getEnvUniversal("RIVET_LOG_TIMESTAMP") === "1";
1031
-
1032
- // src/common/log.ts
1033
- var baseLogger;
1034
- var configuredLogLevel;
1035
- var loggerCache = /* @__PURE__ */ new Map();
1036
- var LogLevelSchema = _v4.z.enum([
1037
- "trace",
1038
- "debug",
1039
- "info",
1040
- "warn",
1041
- "error",
1042
- "fatal",
1043
- "silent"
1044
- ]);
1045
- function getPinoLevel(logLevel) {
1046
- if (logLevel) {
1047
- return logLevel;
1048
- }
1049
- if (configuredLogLevel) {
1050
- return configuredLogLevel;
1299
+ // src/agent-os/actor/session.ts
1300
+ function stripFunctions(value) {
1301
+ if (value === null || value === void 0) return value;
1302
+ if (typeof value === "function") return void 0;
1303
+ if (typeof value !== "object") return value;
1304
+ if (Array.isArray(value)) return value.map(stripFunctions);
1305
+ const out = {};
1306
+ for (const [k, v] of Object.entries(value)) {
1307
+ if (typeof v !== "function") {
1308
+ out[k] = stripFunctions(v);
1309
+ }
1051
1310
  }
1052
- const raw = (getLogLevel() || "warn").toString().toLowerCase();
1053
- const parsed = LogLevelSchema.safeParse(raw);
1054
- if (parsed.success) {
1055
- return parsed.data;
1311
+ return out;
1312
+ }
1313
+ function assertSessionExists(c, sessionId) {
1314
+ if (!c.vars.sessions.has(sessionId)) {
1315
+ throw new Error(`session not found: ${sessionId}`);
1056
1316
  }
1057
- return "info";
1058
1317
  }
1059
- function getIncludeTarget() {
1060
- return getLogTarget();
1318
+ function toSessionRecord(agentOs2, sessionId, agentType) {
1319
+ return {
1320
+ sessionId,
1321
+ agentType,
1322
+ capabilities: _nullishCoalesce(agentOs2.getSessionCapabilities(sessionId), () => ( {})),
1323
+ agentInfo: agentOs2.getSessionAgentInfo(sessionId)
1324
+ };
1061
1325
  }
1062
- function configureDefaultLogger(logLevel) {
1063
- if (logLevel) {
1064
- configuredLogLevel = logLevel;
1065
- }
1066
- baseLogger = _pino.pino.call(void 0,
1067
- {
1068
- level: getPinoLevel(logLevel),
1069
- messageKey: "msg",
1070
- // Do not include pid/hostname in output
1071
- base: {},
1072
- errorKey: "error",
1073
- // Keep the numeric level so the logfmt sink can match Pino's levels.
1074
- formatters: {
1075
- level(_label, number) {
1076
- return { level: number };
1326
+ async function persistSession(c, agentOs2, sessionId, agentType) {
1327
+ const now = Date.now();
1328
+ const capabilities = _nullishCoalesce(agentOs2.getSessionCapabilities(sessionId), () => ( {}));
1329
+ const agentInfo = agentOs2.getSessionAgentInfo(sessionId);
1330
+ await c.db.execute(
1331
+ `INSERT OR REPLACE INTO agent_os_sessions (session_id, agent_type, capabilities, agent_info, created_at)
1332
+ VALUES (?, ?, ?, ?, ?)`,
1333
+ sessionId,
1334
+ agentType,
1335
+ JSON.stringify(capabilities),
1336
+ agentInfo ? JSON.stringify(agentInfo) : null,
1337
+ now
1338
+ );
1339
+ }
1340
+ async function persistSessionEvent(c, sessionId, event2) {
1341
+ var _a;
1342
+ const now = Date.now();
1343
+ const rows = await c.db.execute(
1344
+ `SELECT MAX(seq) as max_seq FROM agent_os_session_events WHERE session_id = ?`,
1345
+ sessionId
1346
+ );
1347
+ const nextSeq = (_nullishCoalesce(((_a = rows[0]) == null ? void 0 : _a.max_seq), () => ( -1))) + 1;
1348
+ await c.db.execute(
1349
+ `INSERT INTO agent_os_session_events (session_id, seq, event, created_at)
1350
+ VALUES (?, ?, ?, ?)`,
1351
+ sessionId,
1352
+ nextSeq,
1353
+ JSON.stringify(event2),
1354
+ now
1355
+ );
1356
+ }
1357
+ async function deletePersistedSession(c, sessionId) {
1358
+ await c.db.execute(
1359
+ `DELETE FROM agent_os_session_events WHERE session_id = ?`,
1360
+ sessionId
1361
+ );
1362
+ await c.db.execute(
1363
+ `DELETE FROM agent_os_sessions WHERE session_id = ?`,
1364
+ sessionId
1365
+ );
1366
+ }
1367
+ function subscribeToSession(c, agentOs2, sessionId, parsedConfig) {
1368
+ agentOs2.onSessionEvent(sessionId, (event2) => {
1369
+ c.broadcast(
1370
+ "sessionEvent",
1371
+ JSON.parse(JSON.stringify({ sessionId, event: event2 }))
1372
+ );
1373
+ persistSessionEvent(c, sessionId, event2).catch(
1374
+ (error) => c.log.error({
1375
+ msg: "agent-os failed to persist session event",
1376
+ sessionId,
1377
+ error
1378
+ })
1379
+ );
1380
+ if (parsedConfig.onSessionEvent) {
1381
+ runHook(
1382
+ c,
1383
+ "onSessionEvent",
1384
+ () => {
1385
+ var _a;
1386
+ return (_a = parsedConfig.onSessionEvent) == null ? void 0 : _a.call(parsedConfig, c, sessionId, event2);
1077
1387
  }
1078
- },
1079
- timestamp: getLogTimestamp() ? _pino.stdTimeFunctions.epochTime : false
1388
+ );
1389
+ }
1390
+ });
1391
+ agentOs2.onPermissionRequest(sessionId, (request) => {
1392
+ c.broadcast(
1393
+ "permissionRequest",
1394
+ JSON.parse(JSON.stringify({ sessionId, request }))
1395
+ );
1396
+ if (parsedConfig.onPermissionRequest) {
1397
+ runHook(
1398
+ c,
1399
+ "onPermissionRequest",
1400
+ () => {
1401
+ var _a;
1402
+ return (_a = parsedConfig.onPermissionRequest) == null ? void 0 : _a.call(parsedConfig, c, sessionId, request);
1403
+ }
1404
+ );
1405
+ }
1406
+ });
1407
+ c.vars.sessions.add(sessionId);
1408
+ }
1409
+ function buildSessionActions(config) {
1410
+ return {
1411
+ createSession: async (c, agentType, options) => {
1412
+ const agentOs2 = await ensureVm(c, config);
1413
+ const { sessionId } = await agentOs2.createSession(
1414
+ agentType,
1415
+ options
1416
+ );
1417
+ subscribeToSession(c, agentOs2, sessionId, config);
1418
+ await persistSession(c, agentOs2, sessionId, agentType);
1419
+ c.log.info({
1420
+ msg: "agent-os session created",
1421
+ sessionId,
1422
+ agentType
1423
+ });
1424
+ return toSessionRecord(agentOs2, sessionId, agentType);
1425
+ },
1426
+ listSessions: async (c) => {
1427
+ const agentOs2 = await ensureVm(c, config);
1428
+ return agentOs2.listSessions();
1429
+ },
1430
+ getSession: async (c, sessionId) => {
1431
+ assertSessionExists(c, sessionId);
1432
+ const agentOs2 = await ensureVm(c, config);
1433
+ const info = agentOs2.listSessions().find((s) => s.sessionId === sessionId);
1434
+ if (!info) {
1435
+ throw new Error(`session not found: ${sessionId}`);
1436
+ }
1437
+ return toSessionRecord(agentOs2, sessionId, info.agentType);
1438
+ },
1439
+ destroySession: async (c, sessionId) => {
1440
+ const agentOs2 = await ensureVm(c, config);
1441
+ await agentOs2.destroySession(sessionId);
1442
+ c.vars.sessions.delete(sessionId);
1443
+ c.vars.activeSessionIds.delete(sessionId);
1444
+ syncPreventSleep(c);
1445
+ await deletePersistedSession(c, sessionId);
1446
+ c.log.info({ msg: "agent-os session destroyed", sessionId });
1447
+ },
1448
+ resumeSession: async (c, sessionId) => {
1449
+ const agentOs2 = await ensureVm(c, config);
1450
+ return agentOs2.resumeSession(sessionId);
1451
+ },
1452
+ closeSession: async (c, sessionId) => {
1453
+ const agentOs2 = await ensureVm(c, config);
1454
+ agentOs2.closeSession(sessionId);
1455
+ c.vars.sessions.delete(sessionId);
1456
+ c.vars.activeSessionIds.delete(sessionId);
1457
+ syncPreventSleep(c);
1458
+ await deletePersistedSession(c, sessionId);
1459
+ c.log.info({ msg: "agent-os session closed", sessionId });
1460
+ }
1461
+ };
1462
+ }
1463
+ function buildPromptActions(_config) {
1464
+ return {
1465
+ sendPrompt: async (c, sessionId, text) => {
1466
+ if (c.aborted) {
1467
+ throw new Error(
1468
+ "actor is shutting down, cannot start new prompt"
1469
+ );
1470
+ }
1471
+ assertSessionExists(c, sessionId);
1472
+ const agentOs2 = c.vars.agentOs;
1473
+ if (!agentOs2) {
1474
+ throw new Error("VM not initialized");
1475
+ }
1476
+ c.vars.activeSessionIds.add(sessionId);
1477
+ syncPreventSleep(c);
1478
+ c.log.info({ msg: "agent-os prompt turn started", sessionId });
1479
+ const start = Date.now();
1480
+ try {
1481
+ const result = await agentOs2.prompt(sessionId, text);
1482
+ return {
1483
+ response: JSON.parse(JSON.stringify(result.response)),
1484
+ text: result.text
1485
+ };
1486
+ } finally {
1487
+ c.vars.activeSessionIds.delete(sessionId);
1488
+ syncPreventSleep(c);
1489
+ c.log.info({
1490
+ msg: "agent-os prompt turn ended",
1491
+ sessionId,
1492
+ durationMs: Date.now() - start
1493
+ });
1494
+ }
1080
1495
  },
1081
- createLogfmtDestination()
1082
- );
1083
- loggerCache.clear();
1084
- }
1085
- function getBaseLogger() {
1086
- if (!baseLogger) {
1087
- configureDefaultLogger();
1088
- }
1089
- return baseLogger;
1090
- }
1091
- function getLogger(name = "default") {
1092
- const cached = loggerCache.get(name);
1093
- if (cached) {
1094
- return cached;
1095
- }
1096
- const base = getBaseLogger();
1097
- const child = getIncludeTarget() ? base.child({ target: name }) : base;
1098
- loggerCache.set(name, child);
1099
- return child;
1496
+ cancelPrompt: async (c, sessionId) => {
1497
+ assertSessionExists(c, sessionId);
1498
+ const agentOs2 = c.vars.agentOs;
1499
+ if (!agentOs2) {
1500
+ throw new Error("VM not initialized");
1501
+ }
1502
+ return stripFunctions(
1503
+ agentOs2.cancelSession(sessionId)
1504
+ );
1505
+ },
1506
+ respondPermission: async (c, sessionId, permissionId, reply) => {
1507
+ assertSessionExists(c, sessionId);
1508
+ const agentOs2 = c.vars.agentOs;
1509
+ if (!agentOs2) {
1510
+ throw new Error("VM not initialized");
1511
+ }
1512
+ return stripFunctions(
1513
+ agentOs2.respondPermission(sessionId, permissionId, reply)
1514
+ );
1515
+ }
1516
+ };
1100
1517
  }
1101
- var PINO_LEVEL_LABELS = {
1102
- 10: "trace",
1103
- 20: "debug",
1104
- 30: "info",
1105
- 40: "warn",
1106
- 50: "error",
1107
- 60: "fatal"
1108
- };
1109
- function createLogfmtDestination() {
1518
+ function buildConfigActions(_config) {
1110
1519
  return {
1111
- write(msg) {
1112
- var _a;
1113
- const line = formatLogfmtLine(msg);
1114
- if (typeof process !== "undefined" && ((_a = process.stdout) == null ? void 0 : _a.write)) {
1115
- process.stdout.write(`${line}
1116
- `);
1117
- } else {
1118
- console.log(line);
1520
+ setMode: async (c, sessionId, modeId) => {
1521
+ assertSessionExists(c, sessionId);
1522
+ const agentOs2 = c.vars.agentOs;
1523
+ if (!agentOs2) {
1524
+ throw new Error("VM not initialized");
1525
+ }
1526
+ return stripFunctions(
1527
+ agentOs2.setSessionMode(sessionId, modeId)
1528
+ );
1529
+ },
1530
+ getModes: async (c, sessionId) => {
1531
+ assertSessionExists(c, sessionId);
1532
+ const agentOs2 = c.vars.agentOs;
1533
+ if (!agentOs2) {
1534
+ throw new Error("VM not initialized");
1535
+ }
1536
+ return agentOs2.getSessionModes(sessionId);
1537
+ },
1538
+ setModel: async (c, sessionId, model) => {
1539
+ assertSessionExists(c, sessionId);
1540
+ const agentOs2 = c.vars.agentOs;
1541
+ if (!agentOs2) {
1542
+ throw new Error("VM not initialized");
1543
+ }
1544
+ return stripFunctions(
1545
+ agentOs2.setSessionModel(sessionId, model)
1546
+ );
1547
+ },
1548
+ setThoughtLevel: async (c, sessionId, level) => {
1549
+ assertSessionExists(c, sessionId);
1550
+ const agentOs2 = c.vars.agentOs;
1551
+ if (!agentOs2) {
1552
+ throw new Error("VM not initialized");
1553
+ }
1554
+ return stripFunctions(
1555
+ agentOs2.setSessionThoughtLevel(sessionId, level)
1556
+ );
1557
+ },
1558
+ getConfigOptions: async (c, sessionId) => {
1559
+ assertSessionExists(c, sessionId);
1560
+ const agentOs2 = c.vars.agentOs;
1561
+ if (!agentOs2) {
1562
+ throw new Error("VM not initialized");
1563
+ }
1564
+ return agentOs2.getSessionConfigOptions(sessionId);
1565
+ },
1566
+ getEvents: async (c, sessionId, options) => {
1567
+ assertSessionExists(c, sessionId);
1568
+ const agentOs2 = c.vars.agentOs;
1569
+ if (!agentOs2) {
1570
+ throw new Error("VM not initialized");
1571
+ }
1572
+ return agentOs2.getSessionEvents(sessionId, options).map((e) => e.notification);
1573
+ },
1574
+ getSequencedEvents: async (c, sessionId, options) => {
1575
+ assertSessionExists(c, sessionId);
1576
+ const agentOs2 = c.vars.agentOs;
1577
+ if (!agentOs2) {
1578
+ throw new Error("VM not initialized");
1579
+ }
1580
+ return agentOs2.getSessionEvents(sessionId, options);
1581
+ },
1582
+ rawSend: async (c, sessionId, method, params) => {
1583
+ assertSessionExists(c, sessionId);
1584
+ const agentOs2 = c.vars.agentOs;
1585
+ if (!agentOs2) {
1586
+ throw new Error("VM not initialized");
1119
1587
  }
1588
+ return stripFunctions(
1589
+ agentOs2.rawSessionSend(sessionId, method, params)
1590
+ );
1120
1591
  }
1121
1592
  };
1122
1593
  }
1123
- function formatLogfmtLine(raw) {
1124
- let data;
1125
- try {
1126
- data = JSON.parse(raw);
1127
- } catch (e2) {
1128
- return raw.trimEnd();
1129
- }
1130
- const parts = [];
1131
- appendLogfmtEntry(parts, "level", formatPinoLevel(data.level));
1132
- if (data.time !== void 0) {
1133
- appendLogfmtEntry(parts, "ts", data.time);
1134
- }
1135
- for (const [key, value] of Object.entries(data)) {
1136
- if (key === "level" || key === "time") {
1137
- continue;
1594
+ function buildSessionPersistenceActions(_config) {
1595
+ return {
1596
+ listPersistedSessions: async (c) => {
1597
+ const rows = await c.db.execute(
1598
+ `SELECT session_id, agent_type, capabilities, agent_info, created_at
1599
+ FROM agent_os_sessions
1600
+ ORDER BY created_at ASC`
1601
+ );
1602
+ return rows.map((row) => ({
1603
+ sessionId: row.session_id,
1604
+ agentType: row.agent_type,
1605
+ capabilities: JSON.parse(row.capabilities),
1606
+ agentInfo: row.agent_info ? JSON.parse(row.agent_info) : null,
1607
+ createdAt: row.created_at
1608
+ }));
1609
+ },
1610
+ getSessionEvents: async (c, sessionId) => {
1611
+ const rows = await c.db.execute(
1612
+ `SELECT session_id, seq, event, created_at
1613
+ FROM agent_os_session_events
1614
+ WHERE session_id = ?
1615
+ ORDER BY seq ASC`,
1616
+ sessionId
1617
+ );
1618
+ return rows.map((row) => ({
1619
+ sessionId: row.session_id,
1620
+ seq: row.seq,
1621
+ event: JSON.parse(row.event),
1622
+ createdAt: row.created_at
1623
+ }));
1138
1624
  }
1139
- appendLogfmtEntry(parts, key, value);
1140
- }
1141
- return parts.join(" ");
1142
- }
1143
- function formatPinoLevel(level) {
1144
- if (typeof level === "number") {
1145
- return _nullishCoalesce(PINO_LEVEL_LABELS[level], () => ( level.toString()));
1146
- }
1147
- if (typeof level === "string") {
1148
- return level.toLowerCase();
1149
- }
1150
- return "info";
1151
- }
1152
- function appendLogfmtEntry(parts, key, value) {
1153
- const safeKey = key.replace(/[\s="]/g, "");
1154
- if (safeKey.length === 0) {
1155
- return;
1156
- }
1157
- parts.push(`${safeKey}=${formatLogfmtValue(value)}`);
1158
- }
1159
- function formatLogfmtValue(value) {
1160
- if (typeof value === "number" || typeof value === "boolean") {
1161
- return String(value);
1162
- }
1163
- if (value === null || value === void 0) {
1164
- return "null";
1165
- }
1166
- if (typeof value === "string") {
1167
- return quoteLogfmtString(value);
1168
- }
1169
- return quoteLogfmtString(JSON.stringify(value));
1170
- }
1171
- function quoteLogfmtString(value) {
1172
- if (!/[\s="]/.test(value)) {
1173
- return value;
1174
- }
1175
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
1176
- }
1177
-
1178
- // src/actor/log.ts
1179
- function loggerWithoutContext() {
1180
- return getLogger("actor-runtime");
1625
+ };
1181
1626
  }
1182
1627
 
1183
- // src/actor/definition.ts
1184
- var warnedDeprecatedTimeoutKeys = /* @__PURE__ */ new Set();
1185
- function warnDeprecatedShutdownTimeoutKeys(options) {
1186
- if (!options || typeof options !== "object") return;
1187
- const opts = options;
1188
- for (const key of ["onDestroyTimeout", "waitUntilTimeout"]) {
1189
- if (opts[key] !== void 0 && !warnedDeprecatedTimeoutKeys.has(key)) {
1190
- warnedDeprecatedTimeoutKeys.add(key);
1191
- loggerWithoutContext().warn({
1192
- msg: `actor option \`${key}\` is deprecated and is now ignored. Configure \`sleepGracePeriod\` instead, which bounds the entire graceful shutdown window for both sleep and destroy. Will be removed in 2.2.0.`
1628
+ // src/agent-os/actor/shell.ts
1629
+ function buildShellActions(config) {
1630
+ return {
1631
+ openShell: async (c, options) => {
1632
+ const agentOs2 = await ensureVm(c, config);
1633
+ const { shellId } = agentOs2.openShell(options);
1634
+ agentOs2.onShellData(shellId, (data) => {
1635
+ c.broadcast("shellData", { shellId, data });
1193
1636
  });
1637
+ c.vars.activeShells.add(shellId);
1638
+ syncPreventSleep(c);
1639
+ c.log.info({ msg: "agent-os shell opened", shellId });
1640
+ return { shellId };
1641
+ },
1642
+ writeShell: async (c, shellId, data) => {
1643
+ const agentOs2 = await ensureVm(c, config);
1644
+ agentOs2.writeShell(shellId, data);
1645
+ },
1646
+ resizeShell: async (c, shellId, cols, rows) => {
1647
+ const agentOs2 = await ensureVm(c, config);
1648
+ agentOs2.resizeShell(shellId, cols, rows);
1649
+ },
1650
+ closeShell: async (c, shellId) => {
1651
+ const agentOs2 = await ensureVm(c, config);
1652
+ agentOs2.closeShell(shellId);
1653
+ c.vars.activeShells.delete(shellId);
1654
+ syncPreventSleep(c);
1655
+ c.log.info({ msg: "agent-os shell closed", shellId });
1194
1656
  }
1195
- }
1196
- }
1197
- var ActorDefinition = class {
1198
- #config;
1199
- constructor(config) {
1200
- this.#config = config;
1201
- }
1202
- get config() {
1203
- return this.#config;
1204
- }
1205
- };
1206
- function actor(input) {
1207
- warnDeprecatedShutdownTimeoutKeys(
1208
- input == null ? void 0 : input.options
1209
- );
1210
- const config = ActorConfigSchema.parse(input);
1211
- return new ActorDefinition(config);
1212
- }
1213
-
1214
- // src/actor/schema.ts
1215
- function event(options) {
1216
- return _nullishCoalesce(options, () => ( {}));
1657
+ };
1217
1658
  }
1218
1659
 
1219
- // src/common/database/shared.ts
1220
- function isSqliteBindingValue(value) {
1221
- if (value === null || typeof value === "number" || typeof value === "string" || typeof value === "bigint" || value instanceof Uint8Array) {
1222
- return true;
1223
- }
1224
- if (Array.isArray(value)) {
1225
- return value.every((item) => typeof item === "number");
1226
- }
1227
- return false;
1228
- }
1229
- function isPlainObject(value) {
1230
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1231
- return false;
1660
+ // src/agent-os/actor/index.ts
1661
+ async function ensureVm(c, config) {
1662
+ if (c.vars.agentOs) {
1663
+ return c.vars.agentOs;
1232
1664
  }
1233
- return Object.getPrototypeOf(value) === Object.prototype;
1665
+ const start = Date.now();
1666
+ const options = buildVmOptions(config.options);
1667
+ const agentOs2 = await _agentoscore.AgentOs.create(options);
1668
+ c.vars.agentOs = agentOs2;
1669
+ agentOs2.onCronEvent((cronEvent) => {
1670
+ c.broadcast("cronEvent", { event: cronEvent });
1671
+ });
1672
+ c.broadcast("vmBooted", {});
1673
+ c.log.info({
1674
+ msg: "agent-os vm booted",
1675
+ bootDurationMs: Date.now() - start
1676
+ });
1677
+ return agentOs2;
1234
1678
  }
1235
- function isSqliteBindingObject(value) {
1236
- if (!isPlainObject(value)) {
1237
- return false;
1679
+ function buildVmOptions(userOptions) {
1680
+ const userMounts = _nullishCoalesce((userOptions == null ? void 0 : userOptions.mounts), () => ( []));
1681
+ const hasWorkdirMount = userMounts.some(
1682
+ (m) => m.path === "/home/user"
1683
+ );
1684
+ if (hasWorkdirMount) {
1685
+ return _nullishCoalesce(userOptions, () => ( {}));
1238
1686
  }
1239
- return Object.values(value).every((entry) => isSqliteBindingValue(entry));
1687
+ const memMount = {
1688
+ path: "/home/user",
1689
+ driver: _agentoscore.createInMemoryFileSystem.call(void 0, )
1690
+ };
1691
+ return {
1692
+ ...userOptions,
1693
+ mounts: [memMount, ...userMounts]
1694
+ };
1240
1695
  }
1241
- function toSqliteBindings(input) {
1242
- if (Array.isArray(input)) {
1243
- for (const value of input) {
1244
- if (!isSqliteBindingValue(value)) {
1245
- throw new Error(
1246
- `unsupported sqlite binding type: ${typeof value}`
1247
- );
1248
- }
1249
- }
1250
- return input;
1251
- }
1252
- if (isSqliteBindingObject(input)) {
1253
- return input;
1254
- }
1255
- throw new Error("unsupported sqlite binding collection");
1696
+ function syncPreventSleep(c) {
1697
+ const shouldPrevent = c.vars.activeSessionIds.size > 0 || c.vars.activeProcesses.size > 0 || c.vars.activeHooks.size > 0 || c.vars.activeShells.size > 0;
1698
+ c.setPreventSleep(shouldPrevent);
1699
+ c.log.info({
1700
+ msg: "agent-os prevent sleep sync",
1701
+ preventSleep: shouldPrevent,
1702
+ activeSessions: c.vars.activeSessionIds.size,
1703
+ activeProcesses: c.vars.activeProcesses.size,
1704
+ activeHooks: c.vars.activeHooks.size,
1705
+ activeShells: c.vars.activeShells.size
1706
+ });
1256
1707
  }
1257
-
1258
- // src/common/database/mod.ts
1259
- function hasMultipleStatements(query) {
1260
- const trimmed = query.trim().replace(/;+$/, "").trimEnd();
1261
- return trimmed.includes(";");
1708
+ function runHook(c, name, callback) {
1709
+ const promise = Promise.resolve(callback()).catch(
1710
+ (error) => c.log.error({ msg: "agent-os hook failed", hookName: name, error })
1711
+ ).finally(() => {
1712
+ c.vars.activeHooks.delete(promise);
1713
+ syncPreventSleep(c);
1714
+ });
1715
+ c.vars.activeHooks.add(promise);
1716
+ syncPreventSleep(c);
1717
+ c.waitUntil(promise);
1262
1718
  }
1263
- function db({
1264
- onMigrate
1265
- } = {}) {
1266
- return {
1267
- createClient: async (ctx) => {
1268
- const nativeDatabaseProvider = ctx.nativeDatabaseProvider;
1269
- if (!nativeDatabaseProvider) {
1270
- throw new Error(
1271
- "native SQLite is required, but the current runtime did not provide a native database provider"
1272
- );
1273
- }
1274
- const db2 = await nativeDatabaseProvider.open(ctx.actorId);
1275
- let closed = false;
1276
- const ensureOpen = () => {
1277
- if (closed) {
1278
- throw new Error(
1279
- "Database is closed. This usually means a background timer (setInterval, setTimeout) or a stray promise is still running after the actor stopped. Use c.abortSignal to clean up timers before the actor shuts down."
1280
- );
1281
- }
1282
- };
1283
- const client = {
1284
- execute: async (query, ...args) => {
1285
- var _a, _b, _c, _d;
1286
- ensureOpen();
1287
- const kvReadsBefore = _nullishCoalesce(((_a = ctx.metrics) == null ? void 0 : _a.totalKvReads), () => ( 0));
1288
- const kvWritesBefore = _nullishCoalesce(((_b = ctx.metrics) == null ? void 0 : _b.totalKvWrites), () => ( 0));
1289
- const start = performance.now();
1290
- try {
1291
- if (args.length > 0) {
1292
- const bindings = args.length === 1 && isSqliteBindingObject(args[0]) ? toSqliteBindings(args[0]) : toSqliteBindings(args);
1293
- const { rows, columns } = await db2.execute(
1294
- query,
1295
- bindings
1296
- );
1297
- return rows.map(
1298
- (row) => rowToObject(row, columns)
1299
- );
1300
- }
1301
- if (!hasMultipleStatements(query)) {
1302
- const { rows, columns } = await db2.execute(query);
1303
- return rows.map(
1304
- (row) => rowToObject(row, columns)
1305
- );
1306
- }
1307
- return await execMultiStatement(db2, query);
1308
- } finally {
1309
- const durationMs = performance.now() - start;
1310
- (_c = ctx.metrics) == null ? void 0 : _c.trackSql(query, durationMs);
1311
- if (ctx.metrics) {
1312
- const kvReads = ctx.metrics.totalKvReads - kvReadsBefore;
1313
- const kvWrites = ctx.metrics.totalKvWrites - kvWritesBefore;
1314
- (_d = ctx.log) == null ? void 0 : _d.debug({
1315
- msg: "sql query",
1316
- query: query.slice(0, 120),
1317
- durationMs,
1318
- kvReads,
1319
- kvWrites
1320
- });
1321
- }
1322
- }
1323
- },
1324
- close: async () => {
1325
- if (!closed) {
1326
- closed = true;
1327
- await db2.close();
1328
- }
1329
- },
1330
- nativeMetrics: () => {
1331
- var _a;
1332
- return _nullishCoalesce(((_a = db2.nativeMetrics) == null ? void 0 : _a.call(db2)), () => ( null));
1719
+ function agentOs(config) {
1720
+ const parsedConfig = agentOsActorConfigSchema.parse(
1721
+ config
1722
+ );
1723
+ const actions = {
1724
+ ...buildSessionActions(parsedConfig),
1725
+ ...buildPromptActions(parsedConfig),
1726
+ ...buildConfigActions(parsedConfig),
1727
+ ...buildSessionPersistenceActions(parsedConfig),
1728
+ ...buildProcessActions(parsedConfig),
1729
+ ...buildFilesystemActions(parsedConfig),
1730
+ ...buildPreviewActions(parsedConfig),
1731
+ ...buildShellActions(parsedConfig),
1732
+ ...buildCronActions(parsedConfig),
1733
+ ...buildNetworkActions(parsedConfig)
1734
+ };
1735
+ return actor({
1736
+ options: {
1737
+ sleepGracePeriod: 9e5,
1738
+ actionTimeout: 9e5
1739
+ },
1740
+ createState: async () => ({}),
1741
+ createVars: () => ({
1742
+ agentOs: null,
1743
+ activeSessionIds: /* @__PURE__ */ new Set(),
1744
+ activeProcesses: /* @__PURE__ */ new Set(),
1745
+ activeHooks: /* @__PURE__ */ new Set(),
1746
+ activeShells: /* @__PURE__ */ new Set(),
1747
+ sessions: /* @__PURE__ */ new Set()
1748
+ }),
1749
+ db: db({
1750
+ onMigrate: migrateAgentOsTables
1751
+ }),
1752
+ events: {
1753
+ sessionEvent: sessionEventToken,
1754
+ permissionRequest: permissionRequestToken,
1755
+ vmBooted: vmBootedToken,
1756
+ vmShutdown: vmShutdownToken,
1757
+ processOutput: processOutputToken,
1758
+ processExit: processExitToken,
1759
+ shellData: shellDataToken,
1760
+ cronEvent: cronEventToken
1761
+ },
1762
+ onBeforeConnect: parsedConfig.onBeforeConnect ? async (ctx, params) => {
1763
+ var _a;
1764
+ if (ctx.request) {
1765
+ const url = new URL(ctx.request.url);
1766
+ if (url.pathname.startsWith("/fetch/")) {
1767
+ return;
1333
1768
  }
1334
- };
1335
- return client;
1769
+ }
1770
+ await ((_a = parsedConfig.onBeforeConnect) == null ? void 0 : _a.call(parsedConfig, ctx, params));
1771
+ } : void 0,
1772
+ onRequest: buildOnRequestHandler(parsedConfig),
1773
+ onSleep: async (c) => {
1774
+ c.log.info({
1775
+ msg: "agent-os vm shutdown for sleep",
1776
+ activeSessions: c.vars.sessions.size,
1777
+ activeProcesses: c.vars.activeProcesses.size,
1778
+ activeShells: c.vars.activeShells.size
1779
+ });
1780
+ if (c.vars.agentOs) {
1781
+ await c.vars.agentOs.dispose();
1782
+ c.vars.agentOs = null;
1783
+ }
1784
+ c.broadcast("vmShutdown", { reason: "sleep" });
1336
1785
  },
1337
- onMigrate: async (client) => {
1338
- if (onMigrate) {
1339
- await withMigrationSavepoint(client, () => onMigrate(client));
1786
+ onDestroy: async (c) => {
1787
+ c.log.info({
1788
+ msg: "agent-os vm shutdown for destroy",
1789
+ activeSessions: c.vars.sessions.size,
1790
+ activeProcesses: c.vars.activeProcesses.size,
1791
+ activeShells: c.vars.activeShells.size
1792
+ });
1793
+ if (c.vars.agentOs) {
1794
+ await c.vars.agentOs.dispose();
1795
+ c.vars.agentOs = null;
1340
1796
  }
1341
- }
1342
- };
1343
- }
1344
- function rowToObject(row, columns) {
1345
- const rowObj = {};
1346
- for (let i = 0; i < columns.length; i++) {
1347
- rowObj[columns[i]] = row[i];
1348
- }
1349
- return rowObj;
1350
- }
1351
- async function execMultiStatement(db2, query) {
1352
- const results = [];
1353
- let columnNames = null;
1354
- await db2.exec(query, (row, columns) => {
1355
- if (!columnNames) {
1356
- columnNames = columns;
1357
- }
1358
- results.push(rowToObject(row, columnNames));
1797
+ c.broadcast("vmShutdown", { reason: "destroy" });
1798
+ },
1799
+ actions
1359
1800
  });
1360
- return results;
1361
- }
1362
- async function withMigrationSavepoint(client, callback) {
1363
- await client.execute("SAVEPOINT __rivet_on_migrate");
1364
- try {
1365
- const result = await callback();
1366
- await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
1367
- return result;
1368
- } catch (error) {
1369
- try {
1370
- await client.execute("ROLLBACK TO SAVEPOINT __rivet_on_migrate");
1371
- } finally {
1372
- await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
1373
- }
1374
- throw error;
1375
- }
1376
1801
  }
1377
-
1378
- // src/agent-os/config.ts
1379
-
1380
- var zFunction2 = () => _v4.z.custom((val) => typeof val === "function");
1381
- var AgentOsOptionsSchema = _v4.z.custom(
1382
- (val) => typeof val === "object" && val !== null
1383
- );
1384
- var agentOsActorConfigSchema = _v4.z.object({
1385
- options: AgentOsOptionsSchema.optional(),
1386
- preview: _v4.z.object({
1387
- defaultExpiresInSeconds: _v4.z.number().positive().default(3600),
1388
- maxExpiresInSeconds: _v4.z.number().positive().default(86400)
1389
- }).strict().prefault(() => ({})),
1390
- onBeforeConnect: zFunction2().optional(),
1391
- onSessionEvent: zFunction2().optional(),
1392
- onPermissionRequest: zFunction2().optional()
1393
- }).strict();
1802
+ var sessionEventToken = event();
1803
+ var permissionRequestToken = event();
1804
+ var vmBootedToken = event();
1805
+ var vmShutdownToken = event();
1806
+ var processOutputToken = event();
1807
+ var processExitToken = event();
1808
+ var shellDataToken = event();
1809
+ var cronEventToken = event();
1394
1810
 
1395
1811
  // src/agent-os/actor/cron.ts
1396
1812
  function serializeCronAction(action) {
@@ -1416,857 +1832,515 @@ function serializeCronAction(action) {
1416
1832
  function serializeCronJob(job) {
1417
1833
  var _a, _b;
1418
1834
  return {
1419
- id: job.id,
1420
- schedule: job.schedule,
1421
- action: serializeCronAction(job.action),
1422
- overlap: job.overlap,
1423
- lastRun: (_a = job.lastRun) == null ? void 0 : _a.toISOString(),
1424
- nextRun: (_b = job.nextRun) == null ? void 0 : _b.toISOString(),
1425
- runCount: job.runCount,
1426
- running: job.running
1427
- };
1428
- }
1429
- function buildCronActions(config) {
1430
- return {
1431
- scheduleCron: async (c, options) => {
1432
- const agentOs2 = await ensureVm(c, config);
1433
- const job = agentOs2.scheduleCron({
1434
- id: options.id,
1435
- schedule: options.schedule,
1436
- action: options.action,
1437
- overlap: options.overlap
1438
- });
1439
- c.log.info({
1440
- msg: "agent-os cron job scheduled",
1441
- jobId: job.id,
1442
- schedule: options.schedule
1443
- });
1444
- return { id: job.id };
1445
- },
1446
- listCronJobs: async (c) => {
1447
- const agentOs2 = await ensureVm(c, config);
1448
- return agentOs2.listCronJobs().map(serializeCronJob);
1449
- },
1450
- cancelCronJob: async (c, id) => {
1451
- const agentOs2 = await ensureVm(c, config);
1452
- agentOs2.cancelCronJob(id);
1453
- c.log.info({ msg: "agent-os cron job cancelled", jobId: id });
1454
- }
1455
- };
1456
- }
1457
-
1458
- // src/agent-os/actor/network.ts
1459
- function buildNetworkActions(config) {
1460
- return {
1461
- vmFetch: async (c, port, url, options) => {
1462
- const agentOs2 = await ensureVm(c, config);
1463
- const headers = new Headers(options == null ? void 0 : options.headers);
1464
- const request = new Request(url, {
1465
- method: _nullishCoalesce((options == null ? void 0 : options.method), () => ( "GET")),
1466
- headers,
1467
- body: _nullishCoalesce((options == null ? void 0 : options.body), () => ( null))
1468
- });
1469
- const response = await agentOs2.fetch(port, request);
1470
- const responseHeaders = {};
1471
- response.headers.forEach((value, key) => {
1472
- responseHeaders[key] = value;
1473
- });
1474
- const body = new Uint8Array(await response.arrayBuffer());
1475
- return {
1476
- status: response.status,
1477
- statusText: response.statusText,
1478
- headers: responseHeaders,
1479
- body
1480
- };
1481
- }
1482
- };
1483
- }
1484
-
1485
- // src/agent-os/actor/preview.ts
1486
- var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);
1487
- function generateToken() {
1488
- const bytes = _crypto2.default.randomBytes(32);
1489
- const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
1490
- let token = "";
1491
- for (let i = 0; i < 32; i++) {
1492
- token += alphabet[bytes[i] % alphabet.length];
1493
- }
1494
- return token;
1495
- }
1496
- var CORS_HEADERS = {
1497
- "Access-Control-Allow-Origin": "*",
1498
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
1499
- "Access-Control-Allow-Headers": "*"
1500
- };
1501
- function addCorsHeaders(response) {
1502
- const headers = new Headers(response.headers);
1503
- for (const [key, value] of Object.entries(CORS_HEADERS)) {
1504
- headers.set(key, value);
1505
- }
1506
- return new Response(response.body, {
1507
- status: response.status,
1508
- statusText: response.statusText,
1509
- headers
1510
- });
1511
- }
1512
- function buildOnRequestHandler(config) {
1513
- return async (c, request) => {
1514
- var _a;
1515
- const url = new URL(request.url);
1516
- const pathname = url.pathname;
1517
- const match = pathname.match(/^\/fetch\/([a-z0-9]+)(\/.*)?$/);
1518
- if (!match) {
1519
- return new Response("Not Found", { status: 404 });
1520
- }
1521
- if (request.method === "OPTIONS") {
1522
- return new Response(null, { status: 204, headers: CORS_HEADERS });
1523
- }
1524
- const token = match[1];
1525
- const remainingPath = _nullishCoalesce(match[2], () => ( "/"));
1526
- const now = Date.now();
1527
- const rows = await c.db.execute(
1528
- `SELECT port FROM agent_os_preview_tokens WHERE token = ? AND expires_at > ?`,
1529
- token,
1530
- now
1531
- );
1532
- if (rows.length === 0) {
1533
- c.log.warn({ msg: "agent-os preview auth failed", token });
1534
- return addCorsHeaders(new Response("Forbidden", { status: 403 }));
1535
- }
1536
- const port = (_a = rows[0]) == null ? void 0 : _a.port;
1537
- const agentOs2 = await ensureVm(
1538
- c,
1539
- config
1540
- );
1541
- const vmUrl = `http://localhost:${port}${remainingPath}${url.search}`;
1542
- const vmRequest = new Request(vmUrl, {
1543
- method: request.method,
1544
- headers: request.headers,
1545
- body: request.body,
1546
- duplex: "half"
1547
- });
1548
- const vmResponse = await agentOs2.fetch(port, vmRequest);
1549
- c.log.info({
1550
- msg: "agent-os preview request proxied",
1551
- port,
1552
- method: request.method,
1553
- path: remainingPath,
1554
- status: vmResponse.status
1555
- });
1556
- return addCorsHeaders(vmResponse);
1557
- };
1558
- }
1559
- function buildPreviewActions(config) {
1560
- return {
1561
- createSignedPreviewUrl: async (c, port, expiresInSeconds) => {
1562
- await ensureVm(c, config);
1563
- const effectiveExpires = _nullishCoalesce(expiresInSeconds, () => ( config.preview.defaultExpiresInSeconds));
1564
- const maxExpires = config.preview.maxExpiresInSeconds;
1565
- if (effectiveExpires < 1 || effectiveExpires > maxExpires) {
1566
- throw new Error(
1567
- `expiresInSeconds must be between 1 and ${maxExpires}`
1568
- );
1569
- }
1570
- const token = generateToken();
1571
- const now = Date.now();
1572
- const expiresAt = now + effectiveExpires * 1e3;
1573
- await c.db.execute(
1574
- `INSERT INTO agent_os_preview_tokens (token, port, created_at, expires_at)
1575
- VALUES (?, ?, ?, ?)`,
1576
- token,
1577
- port,
1578
- now,
1579
- expiresAt
1580
- );
1581
- await c.db.execute(
1582
- `DELETE FROM agent_os_preview_tokens WHERE expires_at <= ?`,
1583
- now
1584
- );
1585
- const path = `/request/fetch/${token}`;
1586
- c.log.info({
1587
- msg: "agent-os preview token created",
1588
- port,
1589
- expiresInSeconds: effectiveExpires
1590
- });
1591
- return { path, token, port, expiresAt };
1592
- },
1593
- expireSignedPreviewUrl: async (c, token) => {
1594
- await c.db.execute(
1595
- `DELETE FROM agent_os_preview_tokens WHERE token = ?`,
1596
- token
1597
- );
1598
- c.log.info({ msg: "agent-os preview token expired", token });
1599
- }
1600
- };
1601
- }
1602
-
1603
- // src/agent-os/actor/process.ts
1604
- function broadcastProcessEvent(c, name, payload) {
1605
- try {
1606
- c.broadcast(name, payload);
1607
- } catch (error) {
1608
- if (isRivetErrorCode(error, "actor", "stopping")) {
1609
- return;
1610
- }
1611
- throw error;
1612
- }
1835
+ id: job.id,
1836
+ schedule: job.schedule,
1837
+ action: serializeCronAction(job.action),
1838
+ overlap: job.overlap,
1839
+ lastRun: (_a = job.lastRun) == null ? void 0 : _a.toISOString(),
1840
+ nextRun: (_b = job.nextRun) == null ? void 0 : _b.toISOString(),
1841
+ runCount: job.runCount,
1842
+ running: job.running
1843
+ };
1613
1844
  }
1614
- function buildProcessActions(config) {
1845
+ function buildCronActions(config) {
1615
1846
  return {
1616
- exec: async (c, command, options) => {
1617
- const agentOs2 = await ensureVm(c, config);
1618
- return agentOs2.exec(command, options);
1619
- },
1620
- spawn: async (c, command, args, options) => {
1847
+ scheduleCron: async (c, options) => {
1621
1848
  const agentOs2 = await ensureVm(c, config);
1622
- const { pid } = agentOs2.spawn(command, args, {
1623
- ...options,
1624
- onStdout: (data) => {
1625
- var _a;
1626
- broadcastProcessEvent(c, "processOutput", {
1627
- pid,
1628
- stream: "stdout",
1629
- data
1630
- });
1631
- (_a = options == null ? void 0 : options.onStdout) == null ? void 0 : _a.call(options, data);
1632
- },
1633
- onStderr: (data) => {
1634
- var _a;
1635
- broadcastProcessEvent(c, "processOutput", {
1636
- pid,
1637
- stream: "stderr",
1638
- data
1639
- });
1640
- (_a = options == null ? void 0 : options.onStderr) == null ? void 0 : _a.call(options, data);
1641
- }
1849
+ const job = agentOs2.scheduleCron({
1850
+ id: options.id,
1851
+ schedule: options.schedule,
1852
+ action: options.action,
1853
+ overlap: options.overlap
1642
1854
  });
1643
- c.vars.activeProcesses.add(pid);
1644
- syncPreventSleep(c);
1645
1855
  c.log.info({
1646
- msg: "agent-os process spawned",
1647
- pid,
1648
- command
1649
- });
1650
- agentOs2.waitProcess(pid).then((exitCode) => {
1651
- broadcastProcessEvent(c, "processExit", { pid, exitCode });
1652
- c.log.info({
1653
- msg: "agent-os process exited",
1654
- pid,
1655
- exitCode
1656
- });
1657
- }).catch(() => {
1658
- }).finally(() => {
1659
- c.vars.activeProcesses.delete(pid);
1660
- syncPreventSleep(c);
1856
+ msg: "agent-os cron job scheduled",
1857
+ jobId: job.id,
1858
+ schedule: options.schedule
1661
1859
  });
1662
- return { pid };
1663
- },
1664
- writeProcessStdin: async (c, pid, data) => {
1665
- const agentOs2 = await ensureVm(c, config);
1666
- agentOs2.writeProcessStdin(pid, data);
1667
- },
1668
- closeProcessStdin: async (c, pid) => {
1669
- const agentOs2 = await ensureVm(c, config);
1670
- agentOs2.closeProcessStdin(pid);
1671
- },
1672
- waitProcess: async (c, pid) => {
1673
- const agentOs2 = await ensureVm(c, config);
1674
- return agentOs2.waitProcess(pid);
1675
- },
1676
- listProcesses: async (c) => {
1677
- const agentOs2 = await ensureVm(c, config);
1678
- return agentOs2.listProcesses();
1679
- },
1680
- allProcesses: async (c) => {
1681
- const agentOs2 = await ensureVm(c, config);
1682
- return agentOs2.allProcesses();
1683
- },
1684
- processTree: async (c) => {
1685
- const agentOs2 = await ensureVm(c, config);
1686
- return agentOs2.processTree();
1687
- },
1688
- getProcess: async (c, pid) => {
1689
- const agentOs2 = await ensureVm(c, config);
1690
- return agentOs2.getProcess(pid);
1860
+ return { id: job.id };
1691
1861
  },
1692
- stopProcess: async (c, pid) => {
1862
+ listCronJobs: async (c) => {
1693
1863
  const agentOs2 = await ensureVm(c, config);
1694
- agentOs2.stopProcess(pid);
1864
+ return agentOs2.listCronJobs().map(serializeCronJob);
1695
1865
  },
1696
- killProcess: async (c, pid) => {
1866
+ cancelCronJob: async (c, id) => {
1697
1867
  const agentOs2 = await ensureVm(c, config);
1698
- agentOs2.killProcess(pid);
1868
+ agentOs2.cancelCronJob(id);
1869
+ c.log.info({ msg: "agent-os cron job cancelled", jobId: id });
1699
1870
  }
1700
1871
  };
1701
1872
  }
1702
1873
 
1703
- // src/agent-os/actor/session.ts
1704
- function stripFunctions(value) {
1705
- if (value === null || value === void 0) return value;
1706
- if (typeof value === "function") return void 0;
1707
- if (typeof value !== "object") return value;
1708
- if (Array.isArray(value)) return value.map(stripFunctions);
1709
- const out = {};
1710
- for (const [k, v] of Object.entries(value)) {
1711
- if (typeof v !== "function") {
1712
- out[k] = stripFunctions(v);
1713
- }
1874
+ // src/agent-os/fs/database-vfs.ts
1875
+ var _posix = require('path/posix'); var posixPath = _interopRequireWildcard(_posix);
1876
+ var S_IFDIR = 16384;
1877
+ var S_IFREG = 32768;
1878
+ var S_IFLNK = 40960;
1879
+ var DEFAULT_FILE_MODE = S_IFREG | 420;
1880
+ var DEFAULT_DIR_MODE = S_IFDIR | 493;
1881
+ function normPath(p) {
1882
+ const normalized = posixPath.normalize(`/${p}`);
1883
+ if (normalized.length > 1 && normalized.endsWith("/")) {
1884
+ return normalized.slice(0, -1);
1714
1885
  }
1715
- return out;
1886
+ return normalized;
1716
1887
  }
1717
- function assertSessionExists(c, sessionId) {
1718
- if (!c.vars.sessions.has(sessionId)) {
1719
- throw new Error(`session not found: ${sessionId}`);
1720
- }
1888
+ function parentPath(p) {
1889
+ const parent = posixPath.dirname(p);
1890
+ return parent;
1721
1891
  }
1722
- function toSessionRecord(agentOs2, sessionId, agentType) {
1723
- return {
1724
- sessionId,
1725
- agentType,
1726
- capabilities: _nullishCoalesce(agentOs2.getSessionCapabilities(sessionId), () => ( {})),
1727
- agentInfo: agentOs2.getSessionAgentInfo(sessionId)
1728
- };
1892
+ function throwENOENT(path) {
1893
+ const err = new Error(`ENOENT: no such file or directory: ${path}`);
1894
+ err.name = "ENOENT";
1895
+ throw err;
1729
1896
  }
1730
- async function persistSession(c, agentOs2, sessionId, agentType) {
1731
- const now = Date.now();
1732
- const capabilities = _nullishCoalesce(agentOs2.getSessionCapabilities(sessionId), () => ( {}));
1733
- const agentInfo = agentOs2.getSessionAgentInfo(sessionId);
1734
- await c.db.execute(
1735
- `INSERT OR REPLACE INTO agent_os_sessions (session_id, agent_type, capabilities, agent_info, created_at)
1736
- VALUES (?, ?, ?, ?, ?)`,
1737
- sessionId,
1738
- agentType,
1739
- JSON.stringify(capabilities),
1740
- agentInfo ? JSON.stringify(agentInfo) : null,
1741
- now
1742
- );
1897
+ function throwEEXIST(path) {
1898
+ const err = new Error(`EEXIST: file already exists: ${path}`);
1899
+ err.name = "EEXIST";
1900
+ throw err;
1743
1901
  }
1744
- async function persistSessionEvent(c, sessionId, event2) {
1745
- var _a;
1746
- const now = Date.now();
1747
- const rows = await c.db.execute(
1748
- `SELECT MAX(seq) as max_seq FROM agent_os_session_events WHERE session_id = ?`,
1749
- sessionId
1750
- );
1751
- const nextSeq = (_nullishCoalesce(((_a = rows[0]) == null ? void 0 : _a.max_seq), () => ( -1))) + 1;
1752
- await c.db.execute(
1753
- `INSERT INTO agent_os_session_events (session_id, seq, event, created_at)
1754
- VALUES (?, ?, ?, ?)`,
1755
- sessionId,
1756
- nextSeq,
1757
- JSON.stringify(event2),
1758
- now
1759
- );
1902
+ function throwENOTDIR(path) {
1903
+ const err = new Error(`ENOTDIR: not a directory: ${path}`);
1904
+ err.name = "ENOTDIR";
1905
+ throw err;
1760
1906
  }
1761
- async function deletePersistedSession(c, sessionId) {
1762
- await c.db.execute(
1763
- `DELETE FROM agent_os_session_events WHERE session_id = ?`,
1764
- sessionId
1765
- );
1766
- await c.db.execute(
1767
- `DELETE FROM agent_os_sessions WHERE session_id = ?`,
1768
- sessionId
1769
- );
1907
+ function throwEISDIR(path) {
1908
+ const err = new Error(`EISDIR: illegal operation on a directory: ${path}`);
1909
+ err.name = "EISDIR";
1910
+ throw err;
1770
1911
  }
1771
- function subscribeToSession(c, agentOs2, sessionId, parsedConfig) {
1772
- agentOs2.onSessionEvent(sessionId, (event2) => {
1773
- c.broadcast(
1774
- "sessionEvent",
1775
- JSON.parse(JSON.stringify({ sessionId, event: event2 }))
1776
- );
1777
- persistSessionEvent(c, sessionId, event2).catch(
1778
- (error) => c.log.error({
1779
- msg: "agent-os failed to persist session event",
1780
- sessionId,
1781
- error
1782
- })
1912
+ function throwENOTEMPTY(path) {
1913
+ const err = new Error(`ENOTEMPTY: directory not empty: ${path}`);
1914
+ err.name = "ENOTEMPTY";
1915
+ throw err;
1916
+ }
1917
+ function throwENOSYS(op) {
1918
+ const err = new Error(`ENOSYS: function not implemented: ${op}`);
1919
+ err.name = "ENOSYS";
1920
+ throw err;
1921
+ }
1922
+ function rowToStat(row) {
1923
+ return {
1924
+ mode: row.mode,
1925
+ size: row.size,
1926
+ isDirectory: row.is_directory === 1,
1927
+ isSymbolicLink: row.symlink_target !== null,
1928
+ atimeMs: row.atime_ms,
1929
+ mtimeMs: row.mtime_ms,
1930
+ ctimeMs: row.ctime_ms,
1931
+ birthtimeMs: row.birthtime_ms,
1932
+ ino: 0,
1933
+ nlink: row.nlink,
1934
+ uid: row.uid,
1935
+ gid: row.gid
1936
+ };
1937
+ }
1938
+ function createDatabaseVfs(options) {
1939
+ const { db: db2 } = options;
1940
+ async function getEntry(path) {
1941
+ const rows = await db2.execute(
1942
+ "SELECT * FROM agent_os_fs_entries WHERE path = ?",
1943
+ path
1783
1944
  );
1784
- if (parsedConfig.onSessionEvent) {
1785
- runHook(
1786
- c,
1787
- "onSessionEvent",
1788
- () => {
1789
- var _a;
1790
- return (_a = parsedConfig.onSessionEvent) == null ? void 0 : _a.call(parsedConfig, c, sessionId, event2);
1791
- }
1792
- );
1945
+ return rows[0];
1946
+ }
1947
+ async function getEntryOrThrow(path) {
1948
+ const entry = await getEntry(path);
1949
+ if (!entry) {
1950
+ throwENOENT(path);
1951
+ }
1952
+ return entry;
1953
+ }
1954
+ async function ensureParentExists(path) {
1955
+ const parent = parentPath(path);
1956
+ if (parent === path) return;
1957
+ const entry = await getEntry(parent);
1958
+ if (!entry) {
1959
+ throwENOENT(parent);
1793
1960
  }
1794
- });
1795
- agentOs2.onPermissionRequest(sessionId, (request) => {
1796
- c.broadcast(
1797
- "permissionRequest",
1798
- JSON.parse(JSON.stringify({ sessionId, request }))
1961
+ if (entry.is_directory !== 1) {
1962
+ throwENOTDIR(parent);
1963
+ }
1964
+ }
1965
+ async function getChildEntries(dirPath) {
1966
+ const prefix = dirPath === "/" ? "/" : `${dirPath}/`;
1967
+ const rows = await db2.execute(
1968
+ "SELECT * FROM agent_os_fs_entries WHERE path LIKE ? AND path != ?",
1969
+ `${prefix}%`,
1970
+ dirPath
1799
1971
  );
1800
- if (parsedConfig.onPermissionRequest) {
1801
- runHook(
1802
- c,
1803
- "onPermissionRequest",
1804
- () => {
1805
- var _a;
1806
- return (_a = parsedConfig.onPermissionRequest) == null ? void 0 : _a.call(parsedConfig, c, sessionId, request);
1807
- }
1972
+ return rows.filter((row) => {
1973
+ const relative = row.path.slice(prefix.length);
1974
+ return relative.length > 0 && !relative.includes("/");
1975
+ });
1976
+ }
1977
+ const rootInit = (async () => {
1978
+ const root = await getEntry("/");
1979
+ if (!root) {
1980
+ const now = Date.now();
1981
+ await db2.execute(
1982
+ `INSERT OR IGNORE INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
1983
+ "/",
1984
+ DEFAULT_DIR_MODE,
1985
+ now,
1986
+ now,
1987
+ now,
1988
+ now
1808
1989
  );
1809
1990
  }
1810
- });
1811
- c.vars.sessions.add(sessionId);
1812
- }
1813
- function buildSessionActions(config) {
1814
- return {
1815
- createSession: async (c, agentType, options) => {
1816
- const agentOs2 = await ensureVm(c, config);
1817
- const { sessionId } = await agentOs2.createSession(
1818
- agentType,
1819
- options
1820
- );
1821
- subscribeToSession(c, agentOs2, sessionId, config);
1822
- await persistSession(c, agentOs2, sessionId, agentType);
1823
- c.log.info({
1824
- msg: "agent-os session created",
1825
- sessionId,
1826
- agentType
1827
- });
1828
- return toSessionRecord(agentOs2, sessionId, agentType);
1829
- },
1830
- listSessions: async (c) => {
1831
- const agentOs2 = await ensureVm(c, config);
1832
- return agentOs2.listSessions();
1833
- },
1834
- getSession: async (c, sessionId) => {
1835
- assertSessionExists(c, sessionId);
1836
- const agentOs2 = await ensureVm(c, config);
1837
- const info = agentOs2.listSessions().find((s) => s.sessionId === sessionId);
1838
- if (!info) {
1839
- throw new Error(`session not found: ${sessionId}`);
1991
+ })();
1992
+ const backend = {
1993
+ async readFile(p) {
1994
+ await rootInit;
1995
+ const path = normPath(p);
1996
+ const entry = await getEntryOrThrow(path);
1997
+ if (entry.is_directory === 1) {
1998
+ throwEISDIR(path);
1840
1999
  }
1841
- return toSessionRecord(agentOs2, sessionId, info.agentType);
1842
- },
1843
- destroySession: async (c, sessionId) => {
1844
- const agentOs2 = await ensureVm(c, config);
1845
- await agentOs2.destroySession(sessionId);
1846
- c.vars.sessions.delete(sessionId);
1847
- c.vars.activeSessionIds.delete(sessionId);
1848
- syncPreventSleep(c);
1849
- await deletePersistedSession(c, sessionId);
1850
- c.log.info({ msg: "agent-os session destroyed", sessionId });
1851
- },
1852
- resumeSession: async (c, sessionId) => {
1853
- const agentOs2 = await ensureVm(c, config);
1854
- return agentOs2.resumeSession(sessionId);
2000
+ return _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
1855
2001
  },
1856
- closeSession: async (c, sessionId) => {
1857
- const agentOs2 = await ensureVm(c, config);
1858
- agentOs2.closeSession(sessionId);
1859
- c.vars.sessions.delete(sessionId);
1860
- c.vars.activeSessionIds.delete(sessionId);
1861
- syncPreventSleep(c);
1862
- await deletePersistedSession(c, sessionId);
1863
- c.log.info({ msg: "agent-os session closed", sessionId });
1864
- }
1865
- };
1866
- }
1867
- function buildPromptActions(_config) {
1868
- return {
1869
- sendPrompt: async (c, sessionId, text) => {
1870
- if (c.aborted) {
1871
- throw new Error(
1872
- "actor is shutting down, cannot start new prompt"
1873
- );
1874
- }
1875
- assertSessionExists(c, sessionId);
1876
- const agentOs2 = c.vars.agentOs;
1877
- if (!agentOs2) {
1878
- throw new Error("VM not initialized");
1879
- }
1880
- c.vars.activeSessionIds.add(sessionId);
1881
- syncPreventSleep(c);
1882
- c.log.info({ msg: "agent-os prompt turn started", sessionId });
1883
- const start = Date.now();
1884
- try {
1885
- const result = await agentOs2.prompt(sessionId, text);
1886
- return {
1887
- response: JSON.parse(JSON.stringify(result.response)),
1888
- text: result.text
1889
- };
1890
- } finally {
1891
- c.vars.activeSessionIds.delete(sessionId);
1892
- syncPreventSleep(c);
1893
- c.log.info({
1894
- msg: "agent-os prompt turn ended",
1895
- sessionId,
1896
- durationMs: Date.now() - start
1897
- });
1898
- }
2002
+ async readTextFile(p) {
2003
+ const data = await backend.readFile(p);
2004
+ return new TextDecoder().decode(data);
1899
2005
  },
1900
- cancelPrompt: async (c, sessionId) => {
1901
- assertSessionExists(c, sessionId);
1902
- const agentOs2 = c.vars.agentOs;
1903
- if (!agentOs2) {
1904
- throw new Error("VM not initialized");
2006
+ async readDir(p) {
2007
+ await rootInit;
2008
+ const path = normPath(p);
2009
+ const entry = await getEntryOrThrow(path);
2010
+ if (entry.is_directory !== 1) {
2011
+ throwENOTDIR(path);
1905
2012
  }
1906
- return stripFunctions(
1907
- agentOs2.cancelSession(sessionId)
1908
- );
2013
+ const children = await getChildEntries(path);
2014
+ return children.map((child) => posixPath.basename(child.path));
1909
2015
  },
1910
- respondPermission: async (c, sessionId, permissionId, reply) => {
1911
- assertSessionExists(c, sessionId);
1912
- const agentOs2 = c.vars.agentOs;
1913
- if (!agentOs2) {
1914
- throw new Error("VM not initialized");
1915
- }
1916
- return stripFunctions(
1917
- agentOs2.respondPermission(sessionId, permissionId, reply)
1918
- );
1919
- }
1920
- };
1921
- }
1922
- function buildConfigActions(_config) {
1923
- return {
1924
- setMode: async (c, sessionId, modeId) => {
1925
- assertSessionExists(c, sessionId);
1926
- const agentOs2 = c.vars.agentOs;
1927
- if (!agentOs2) {
1928
- throw new Error("VM not initialized");
2016
+ async readDirWithTypes(p) {
2017
+ await rootInit;
2018
+ const path = normPath(p);
2019
+ const entry = await getEntryOrThrow(path);
2020
+ if (entry.is_directory !== 1) {
2021
+ throwENOTDIR(path);
1929
2022
  }
1930
- return stripFunctions(
1931
- agentOs2.setSessionMode(sessionId, modeId)
1932
- );
2023
+ const children = await getChildEntries(path);
2024
+ return children.map((child) => ({
2025
+ name: posixPath.basename(child.path),
2026
+ isDirectory: child.is_directory === 1,
2027
+ isSymbolicLink: child.symlink_target !== null,
2028
+ ino: 0
2029
+ }));
1933
2030
  },
1934
- getModes: async (c, sessionId) => {
1935
- assertSessionExists(c, sessionId);
1936
- const agentOs2 = c.vars.agentOs;
1937
- if (!agentOs2) {
1938
- throw new Error("VM not initialized");
2031
+ async writeFile(p, content) {
2032
+ await rootInit;
2033
+ const path = normPath(p);
2034
+ await ensureParentExists(path);
2035
+ const existing = await getEntry(path);
2036
+ if (existing && existing.is_directory === 1) {
2037
+ throwEISDIR(path);
1939
2038
  }
1940
- return agentOs2.getSessionModes(sessionId);
1941
- },
1942
- setModel: async (c, sessionId, model) => {
1943
- assertSessionExists(c, sessionId);
1944
- const agentOs2 = c.vars.agentOs;
1945
- if (!agentOs2) {
1946
- throw new Error("VM not initialized");
2039
+ const data = typeof content === "string" ? new TextEncoder().encode(content) : content;
2040
+ const now = Date.now();
2041
+ if (existing) {
2042
+ await db2.execute(
2043
+ `UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ?, atime_ms = ? WHERE path = ?`,
2044
+ data,
2045
+ data.byteLength,
2046
+ now,
2047
+ now,
2048
+ now,
2049
+ path
2050
+ );
2051
+ } else {
2052
+ await db2.execute(
2053
+ `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 0, ?, ?, 0, 0, ?, ?, ?, ?, ?, NULL, 1)`,
2054
+ path,
2055
+ data,
2056
+ DEFAULT_FILE_MODE,
2057
+ data.byteLength,
2058
+ now,
2059
+ now,
2060
+ now,
2061
+ now
2062
+ );
1947
2063
  }
1948
- return stripFunctions(
1949
- agentOs2.setSessionModel(sessionId, model)
1950
- );
1951
2064
  },
1952
- setThoughtLevel: async (c, sessionId, level) => {
1953
- assertSessionExists(c, sessionId);
1954
- const agentOs2 = c.vars.agentOs;
1955
- if (!agentOs2) {
1956
- throw new Error("VM not initialized");
2065
+ async createDir(p) {
2066
+ await rootInit;
2067
+ const path = normPath(p);
2068
+ await ensureParentExists(path);
2069
+ const existing = await getEntry(path);
2070
+ if (existing) {
2071
+ throwEEXIST(path);
1957
2072
  }
1958
- return stripFunctions(
1959
- agentOs2.setSessionThoughtLevel(sessionId, level)
2073
+ const now = Date.now();
2074
+ await db2.execute(
2075
+ `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
2076
+ path,
2077
+ DEFAULT_DIR_MODE,
2078
+ now,
2079
+ now,
2080
+ now,
2081
+ now
1960
2082
  );
1961
2083
  },
1962
- getConfigOptions: async (c, sessionId) => {
1963
- assertSessionExists(c, sessionId);
1964
- const agentOs2 = c.vars.agentOs;
1965
- if (!agentOs2) {
1966
- throw new Error("VM not initialized");
2084
+ async mkdir(p, options2) {
2085
+ await rootInit;
2086
+ const path = normPath(p);
2087
+ if (options2 == null ? void 0 : options2.recursive) {
2088
+ const parts = path.split("/").filter(Boolean);
2089
+ let current = "";
2090
+ for (const part of parts) {
2091
+ current += `/${part}`;
2092
+ const existing = await getEntry(current);
2093
+ if (!existing) {
2094
+ const now = Date.now();
2095
+ await db2.execute(
2096
+ `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 1, NULL, ?, 0, 0, 0, ?, ?, ?, ?, NULL, 2)`,
2097
+ current,
2098
+ DEFAULT_DIR_MODE,
2099
+ now,
2100
+ now,
2101
+ now,
2102
+ now
2103
+ );
2104
+ } else if (existing.is_directory !== 1) {
2105
+ throwENOTDIR(current);
2106
+ }
2107
+ }
2108
+ } else {
2109
+ await backend.createDir(p);
1967
2110
  }
1968
- return agentOs2.getSessionConfigOptions(sessionId);
1969
2111
  },
1970
- getEvents: async (c, sessionId, options) => {
1971
- assertSessionExists(c, sessionId);
1972
- const agentOs2 = c.vars.agentOs;
1973
- if (!agentOs2) {
1974
- throw new Error("VM not initialized");
1975
- }
1976
- return agentOs2.getSessionEvents(sessionId, options).map((e) => e.notification);
2112
+ async exists(p) {
2113
+ await rootInit;
2114
+ const path = normPath(p);
2115
+ const entry = await getEntry(path);
2116
+ return entry !== void 0;
1977
2117
  },
1978
- getSequencedEvents: async (c, sessionId, options) => {
1979
- assertSessionExists(c, sessionId);
1980
- const agentOs2 = c.vars.agentOs;
1981
- if (!agentOs2) {
1982
- throw new Error("VM not initialized");
1983
- }
1984
- return agentOs2.getSessionEvents(sessionId, options);
2118
+ async stat(p) {
2119
+ await rootInit;
2120
+ const path = normPath(p);
2121
+ const entry = await getEntryOrThrow(path);
2122
+ return rowToStat(entry);
1985
2123
  },
1986
- rawSend: async (c, sessionId, method, params) => {
1987
- assertSessionExists(c, sessionId);
1988
- const agentOs2 = c.vars.agentOs;
1989
- if (!agentOs2) {
1990
- throw new Error("VM not initialized");
2124
+ async removeFile(p) {
2125
+ await rootInit;
2126
+ const path = normPath(p);
2127
+ const entry = await getEntryOrThrow(path);
2128
+ if (entry.is_directory === 1) {
2129
+ throwEISDIR(path);
1991
2130
  }
1992
- return stripFunctions(
1993
- agentOs2.rawSessionSend(sessionId, method, params)
1994
- );
1995
- }
1996
- };
1997
- }
1998
- function buildSessionPersistenceActions(_config) {
1999
- return {
2000
- listPersistedSessions: async (c) => {
2001
- const rows = await c.db.execute(
2002
- `SELECT session_id, agent_type, capabilities, agent_info, created_at
2003
- FROM agent_os_sessions
2004
- ORDER BY created_at ASC`
2131
+ await db2.execute(
2132
+ "DELETE FROM agent_os_fs_entries WHERE path = ?",
2133
+ path
2005
2134
  );
2006
- return rows.map((row) => ({
2007
- sessionId: row.session_id,
2008
- agentType: row.agent_type,
2009
- capabilities: JSON.parse(row.capabilities),
2010
- agentInfo: row.agent_info ? JSON.parse(row.agent_info) : null,
2011
- createdAt: row.created_at
2012
- }));
2013
2135
  },
2014
- getSessionEvents: async (c, sessionId) => {
2015
- const rows = await c.db.execute(
2016
- `SELECT session_id, seq, event, created_at
2017
- FROM agent_os_session_events
2018
- WHERE session_id = ?
2019
- ORDER BY seq ASC`,
2020
- sessionId
2136
+ async removeDir(p) {
2137
+ await rootInit;
2138
+ const path = normPath(p);
2139
+ const entry = await getEntryOrThrow(path);
2140
+ if (entry.is_directory !== 1) {
2141
+ throwENOTDIR(path);
2142
+ }
2143
+ const children = await getChildEntries(path);
2144
+ if (children.length > 0) {
2145
+ throwENOTEMPTY(path);
2146
+ }
2147
+ await db2.execute(
2148
+ "DELETE FROM agent_os_fs_entries WHERE path = ?",
2149
+ path
2021
2150
  );
2022
- return rows.map((row) => ({
2023
- sessionId: row.session_id,
2024
- seq: row.seq,
2025
- event: JSON.parse(row.event),
2026
- createdAt: row.created_at
2027
- }));
2028
- }
2029
- };
2030
- }
2031
-
2032
- // src/agent-os/actor/shell.ts
2033
- function buildShellActions(config) {
2034
- return {
2035
- openShell: async (c, options) => {
2036
- const agentOs2 = await ensureVm(c, config);
2037
- const { shellId } = agentOs2.openShell(options);
2038
- agentOs2.onShellData(shellId, (data) => {
2039
- c.broadcast("shellData", { shellId, data });
2040
- });
2041
- c.vars.activeShells.add(shellId);
2042
- syncPreventSleep(c);
2043
- c.log.info({ msg: "agent-os shell opened", shellId });
2044
- return { shellId };
2045
- },
2046
- writeShell: async (c, shellId, data) => {
2047
- const agentOs2 = await ensureVm(c, config);
2048
- agentOs2.writeShell(shellId, data);
2049
- },
2050
- resizeShell: async (c, shellId, cols, rows) => {
2051
- const agentOs2 = await ensureVm(c, config);
2052
- agentOs2.resizeShell(shellId, cols, rows);
2053
- },
2054
- closeShell: async (c, shellId) => {
2055
- const agentOs2 = await ensureVm(c, config);
2056
- agentOs2.closeShell(shellId);
2057
- c.vars.activeShells.delete(shellId);
2058
- syncPreventSleep(c);
2059
- c.log.info({ msg: "agent-os shell closed", shellId });
2060
- }
2061
- };
2062
- }
2063
-
2064
- // src/agent-os/actor/index.ts
2065
- async function ensureVm(c, config) {
2066
- if (c.vars.agentOs) {
2067
- return c.vars.agentOs;
2068
- }
2069
- const start = Date.now();
2070
- const options = buildVmOptions(config.options);
2071
- const agentOs2 = await _agentoscore.AgentOs.create(options);
2072
- c.vars.agentOs = agentOs2;
2073
- agentOs2.onCronEvent((cronEvent) => {
2074
- c.broadcast("cronEvent", { event: cronEvent });
2075
- });
2076
- c.broadcast("vmBooted", {});
2077
- c.log.info({
2078
- msg: "agent-os vm booted",
2079
- bootDurationMs: Date.now() - start
2080
- });
2081
- return agentOs2;
2082
- }
2083
- function buildVmOptions(userOptions) {
2084
- const userMounts = _nullishCoalesce((userOptions == null ? void 0 : userOptions.mounts), () => ( []));
2085
- const hasWorkdirMount = userMounts.some(
2086
- (m) => m.path === "/home/user"
2087
- );
2088
- if (hasWorkdirMount) {
2089
- return _nullishCoalesce(userOptions, () => ( {}));
2090
- }
2091
- const memMount = {
2092
- path: "/home/user",
2093
- driver: _agentoscore.createInMemoryFileSystem.call(void 0, )
2094
- };
2095
- return {
2096
- ...userOptions,
2097
- mounts: [memMount, ...userMounts]
2098
- };
2099
- }
2100
- function syncPreventSleep(c) {
2101
- const shouldPrevent = c.vars.activeSessionIds.size > 0 || c.vars.activeProcesses.size > 0 || c.vars.activeHooks.size > 0 || c.vars.activeShells.size > 0;
2102
- c.setPreventSleep(shouldPrevent);
2103
- c.log.info({
2104
- msg: "agent-os prevent sleep sync",
2105
- preventSleep: shouldPrevent,
2106
- activeSessions: c.vars.activeSessionIds.size,
2107
- activeProcesses: c.vars.activeProcesses.size,
2108
- activeHooks: c.vars.activeHooks.size,
2109
- activeShells: c.vars.activeShells.size
2110
- });
2111
- }
2112
- function runHook(c, name, callback) {
2113
- const promise = Promise.resolve(callback()).catch(
2114
- (error) => c.log.error({ msg: "agent-os hook failed", hookName: name, error })
2115
- ).finally(() => {
2116
- c.vars.activeHooks.delete(promise);
2117
- syncPreventSleep(c);
2118
- });
2119
- c.vars.activeHooks.add(promise);
2120
- syncPreventSleep(c);
2121
- c.waitUntil(promise);
2122
- }
2123
- function agentOs(config) {
2124
- const parsedConfig = agentOsActorConfigSchema.parse(
2125
- config
2126
- );
2127
- return actor({
2128
- options: {
2129
- sleepGracePeriod: 9e5,
2130
- actionTimeout: 9e5
2131
- },
2132
- createState: async () => ({}),
2133
- createVars: () => ({
2134
- agentOs: null,
2135
- activeSessionIds: /* @__PURE__ */ new Set(),
2136
- activeProcesses: /* @__PURE__ */ new Set(),
2137
- activeHooks: /* @__PURE__ */ new Set(),
2138
- activeShells: /* @__PURE__ */ new Set(),
2139
- sessions: /* @__PURE__ */ new Set()
2140
- }),
2141
- db: db({
2142
- onMigrate: migrateAgentOsTables
2143
- }),
2144
- events: {
2145
- sessionEvent: sessionEventToken,
2146
- permissionRequest: permissionRequestToken,
2147
- vmBooted: vmBootedToken,
2148
- vmShutdown: vmShutdownToken,
2149
- processOutput: processOutputToken,
2150
- processExit: processExitToken,
2151
- shellData: shellDataToken,
2152
- cronEvent: cronEventToken
2153
2151
  },
2154
- onBeforeConnect: parsedConfig.onBeforeConnect ? async (ctx, params) => {
2155
- var _a;
2156
- if (ctx.request) {
2157
- const url = new URL(ctx.request.url);
2158
- if (url.pathname.startsWith("/fetch/")) {
2159
- return;
2152
+ async rename(oldPath, newPath) {
2153
+ await rootInit;
2154
+ const from = normPath(oldPath);
2155
+ const to = normPath(newPath);
2156
+ const entry = await getEntryOrThrow(from);
2157
+ await ensureParentExists(to);
2158
+ const destEntry = await getEntry(to);
2159
+ if (destEntry) {
2160
+ if (destEntry.is_directory === 1) {
2161
+ const children = await getChildEntries(to);
2162
+ if (children.length > 0) {
2163
+ throwENOTEMPTY(to);
2164
+ }
2160
2165
  }
2166
+ await db2.execute(
2167
+ "DELETE FROM agent_os_fs_entries WHERE path = ?",
2168
+ to
2169
+ );
2161
2170
  }
2162
- await ((_a = parsedConfig.onBeforeConnect) == null ? void 0 : _a.call(parsedConfig, ctx, params));
2163
- } : void 0,
2164
- onRequest: buildOnRequestHandler(parsedConfig),
2165
- onSleep: async (c) => {
2166
- c.log.info({
2167
- msg: "agent-os vm shutdown for sleep",
2168
- activeSessions: c.vars.sessions.size,
2169
- activeProcesses: c.vars.activeProcesses.size,
2170
- activeShells: c.vars.activeShells.size
2171
- });
2172
- if (c.vars.agentOs) {
2173
- await c.vars.agentOs.dispose();
2174
- c.vars.agentOs = null;
2171
+ if (entry.is_directory === 1) {
2172
+ const prefix = from === "/" ? "/" : `${from}/`;
2173
+ const newPrefix = to === "/" ? "/" : `${to}/`;
2174
+ const descendants = await db2.execute(
2175
+ "SELECT path FROM agent_os_fs_entries WHERE path LIKE ?",
2176
+ `${prefix}%`
2177
+ );
2178
+ for (const desc of descendants) {
2179
+ const newDescPath = newPrefix + desc.path.slice(prefix.length);
2180
+ await db2.execute(
2181
+ "UPDATE agent_os_fs_entries SET path = ? WHERE path = ?",
2182
+ newDescPath,
2183
+ desc.path
2184
+ );
2185
+ }
2175
2186
  }
2176
- c.broadcast("vmShutdown", { reason: "sleep" });
2187
+ const now = Date.now();
2188
+ await db2.execute(
2189
+ "UPDATE agent_os_fs_entries SET path = ?, ctime_ms = ? WHERE path = ?",
2190
+ to,
2191
+ now,
2192
+ from
2193
+ );
2177
2194
  },
2178
- onDestroy: async (c) => {
2179
- c.log.info({
2180
- msg: "agent-os vm shutdown for destroy",
2181
- activeSessions: c.vars.sessions.size,
2182
- activeProcesses: c.vars.activeProcesses.size,
2183
- activeShells: c.vars.activeShells.size
2184
- });
2185
- if (c.vars.agentOs) {
2186
- await c.vars.agentOs.dispose();
2187
- c.vars.agentOs = null;
2195
+ async realpath(p) {
2196
+ await rootInit;
2197
+ const path = normPath(p);
2198
+ const entry = await getEntryOrThrow(path);
2199
+ if (entry.symlink_target !== null) {
2200
+ return normPath(entry.symlink_target);
2188
2201
  }
2189
- c.broadcast("vmShutdown", { reason: "destroy" });
2190
- },
2191
- actions: {
2192
- ...buildSessionActions(parsedConfig),
2193
- ...buildPromptActions(parsedConfig),
2194
- ...buildConfigActions(parsedConfig),
2195
- ...buildSessionPersistenceActions(parsedConfig),
2196
- ...buildProcessActions(parsedConfig),
2197
- ...buildFilesystemActions(parsedConfig),
2198
- ...buildPreviewActions(parsedConfig),
2199
- ...buildShellActions(parsedConfig),
2200
- ...buildCronActions(parsedConfig),
2201
- ...buildNetworkActions(parsedConfig)
2202
- }
2203
- });
2204
- }
2205
- var sessionEventToken = event();
2206
- var permissionRequestToken = event();
2207
- var vmBootedToken = event();
2208
- var vmShutdownToken = event();
2209
- var processOutputToken = event();
2210
- var processExitToken = event();
2211
- var shellDataToken = event();
2212
- var cronEventToken = event();
2213
-
2214
- // src/agent-os/actor/filesystem.ts
2215
- function buildFilesystemActions(config) {
2216
- return {
2217
- readFile: async (c, path) => {
2218
- const agentOs2 = await ensureVm(c, config);
2219
- return agentOs2.readFile(path);
2220
- },
2221
- writeFile: async (c, path, content) => {
2222
- const agentOs2 = await ensureVm(c, config);
2223
- await agentOs2.writeFile(path, content);
2202
+ return path;
2224
2203
  },
2225
- readFiles: async (c, paths) => {
2226
- const agentOs2 = await ensureVm(c, config);
2227
- return agentOs2.readFiles(paths);
2204
+ async symlink(target, linkPath) {
2205
+ await rootInit;
2206
+ const link = normPath(linkPath);
2207
+ await ensureParentExists(link);
2208
+ const existing = await getEntry(link);
2209
+ if (existing) {
2210
+ throwEEXIST(link);
2211
+ }
2212
+ const now = Date.now();
2213
+ await db2.execute(
2214
+ `INSERT INTO agent_os_fs_entries (path, is_directory, content, mode, uid, gid, size, atime_ms, mtime_ms, ctime_ms, birthtime_ms, symlink_target, nlink) VALUES (?, 0, NULL, ?, 0, 0, ?, ?, ?, ?, ?, ?, 1)`,
2215
+ link,
2216
+ S_IFLNK | 511,
2217
+ target.length,
2218
+ now,
2219
+ now,
2220
+ now,
2221
+ now,
2222
+ target
2223
+ );
2228
2224
  },
2229
- writeFiles: async (c, entries) => {
2230
- const agentOs2 = await ensureVm(c, config);
2231
- return agentOs2.writeFiles(entries);
2225
+ async readlink(p) {
2226
+ await rootInit;
2227
+ const path = normPath(p);
2228
+ const entry = await getEntryOrThrow(path);
2229
+ if (entry.symlink_target === null) {
2230
+ const err = new Error(`EINVAL: not a symlink: ${path}`);
2231
+ err.name = "EINVAL";
2232
+ throw err;
2233
+ }
2234
+ return entry.symlink_target;
2232
2235
  },
2233
- mkdir: async (c, path, options) => {
2234
- const agentOs2 = await ensureVm(c, config);
2235
- await agentOs2.mkdir(path, options);
2236
+ async lstat(p) {
2237
+ return backend.stat(p);
2236
2238
  },
2237
- readdir: async (c, path) => {
2238
- const agentOs2 = await ensureVm(c, config);
2239
- return agentOs2.readdir(path);
2239
+ async link(_oldPath, _newPath) {
2240
+ throwENOSYS("link");
2240
2241
  },
2241
- readdirRecursive: async (c, path, options) => {
2242
- const agentOs2 = await ensureVm(c, config);
2243
- return agentOs2.readdirRecursive(path, options);
2242
+ async chmod(p, mode) {
2243
+ await rootInit;
2244
+ const path = normPath(p);
2245
+ await getEntryOrThrow(path);
2246
+ const now = Date.now();
2247
+ await db2.execute(
2248
+ "UPDATE agent_os_fs_entries SET mode = ?, ctime_ms = ? WHERE path = ?",
2249
+ mode,
2250
+ now,
2251
+ path
2252
+ );
2244
2253
  },
2245
- stat: async (c, path) => {
2246
- const agentOs2 = await ensureVm(c, config);
2247
- return agentOs2.stat(path);
2254
+ async chown(p, uid, gid) {
2255
+ await rootInit;
2256
+ const path = normPath(p);
2257
+ await getEntryOrThrow(path);
2258
+ const now = Date.now();
2259
+ await db2.execute(
2260
+ "UPDATE agent_os_fs_entries SET uid = ?, gid = ?, ctime_ms = ? WHERE path = ?",
2261
+ uid,
2262
+ gid,
2263
+ now,
2264
+ path
2265
+ );
2248
2266
  },
2249
- exists: async (c, path) => {
2250
- const agentOs2 = await ensureVm(c, config);
2251
- return agentOs2.exists(path);
2267
+ async utimes(p, atime, mtime) {
2268
+ await rootInit;
2269
+ const path = normPath(p);
2270
+ await getEntryOrThrow(path);
2271
+ const now = Date.now();
2272
+ await db2.execute(
2273
+ "UPDATE agent_os_fs_entries SET atime_ms = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?",
2274
+ atime,
2275
+ mtime,
2276
+ now,
2277
+ path
2278
+ );
2252
2279
  },
2253
- move: async (c, from, to) => {
2254
- const agentOs2 = await ensureVm(c, config);
2255
- await agentOs2.move(from, to);
2280
+ async truncate(p, length) {
2281
+ await rootInit;
2282
+ const path = normPath(p);
2283
+ const entry = await getEntryOrThrow(path);
2284
+ if (entry.is_directory === 1) {
2285
+ throwEISDIR(path);
2286
+ }
2287
+ const existing = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
2288
+ let newContent;
2289
+ if (length >= existing.byteLength) {
2290
+ newContent = new Uint8Array(length);
2291
+ newContent.set(existing);
2292
+ } else {
2293
+ newContent = existing.slice(0, length);
2294
+ }
2295
+ const now = Date.now();
2296
+ await db2.execute(
2297
+ "UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?",
2298
+ newContent,
2299
+ length,
2300
+ now,
2301
+ now,
2302
+ path
2303
+ );
2256
2304
  },
2257
- deleteFile: async (c, path, options) => {
2258
- const agentOs2 = await ensureVm(c, config);
2259
- await agentOs2.delete(path, options);
2305
+ async pread(p, offset, length) {
2306
+ await rootInit;
2307
+ const path = normPath(p);
2308
+ const entry = await getEntryOrThrow(path);
2309
+ if (entry.is_directory === 1) {
2310
+ throwEISDIR(path);
2311
+ }
2312
+ const content = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
2313
+ const end = Math.min(offset + length, content.byteLength);
2314
+ if (offset >= content.byteLength) {
2315
+ return new Uint8Array(0);
2316
+ }
2317
+ return content.slice(offset, end);
2260
2318
  },
2261
- // TODO: mountFs and unmountFs are not exposed as actor actions because
2262
- // filesystem drivers (VirtualFileSystem) are not serializable over the
2263
- // network. Mount filesystems via the `options.mounts` config in agentOs()
2264
- // instead. See: https://github.com/rivet-dev/rivet/issues/XXXX
2265
- listAgents: async (c) => {
2266
- const agentOs2 = await ensureVm(c, config);
2267
- return agentOs2.listAgents();
2319
+ async pwrite(p, offset, data) {
2320
+ await rootInit;
2321
+ const path = normPath(p);
2322
+ const entry = await getEntryOrThrow(path);
2323
+ if (entry.is_directory === 1) {
2324
+ throwEISDIR(path);
2325
+ }
2326
+ const content = _nullishCoalesce(entry.content, () => ( new Uint8Array(0)));
2327
+ const end = offset + data.byteLength;
2328
+ const newSize = Math.max(content.byteLength, end);
2329
+ const buf = new Uint8Array(newSize);
2330
+ buf.set(content);
2331
+ buf.set(data, offset);
2332
+ const now = Date.now();
2333
+ await db2.execute(
2334
+ `UPDATE agent_os_fs_entries SET content = ?, size = ?, mtime_ms = ?, ctime_ms = ? WHERE path = ?`,
2335
+ buf,
2336
+ newSize,
2337
+ now,
2338
+ now,
2339
+ path
2340
+ );
2268
2341
  }
2269
2342
  };
2343
+ return backend;
2270
2344
  }
2271
2345
 
2272
2346