rivetkit 2.3.0-rc.9 → 2.3.1

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 (226) hide show
  1. package/dist/browser/client.d.ts +511 -62
  2. package/dist/browser/client.js +230 -174
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +53 -23
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +4 -2
  7. package/dist/tsup/actor/errors.cjs.map +1 -1
  8. package/dist/tsup/actor/errors.d.cts +1 -1
  9. package/dist/tsup/actor/errors.d.ts +1 -1
  10. package/dist/tsup/actor/errors.js +3 -1
  11. package/dist/tsup/agent-os/index.cjs +2163 -2087
  12. package/dist/tsup/agent-os/index.cjs.map +1 -1
  13. package/dist/tsup/agent-os/index.d.cts +509 -69
  14. package/dist/tsup/agent-os/index.d.ts +509 -69
  15. package/dist/tsup/agent-os/index.js +2163 -2087
  16. package/dist/tsup/agent-os/index.js.map +1 -1
  17. package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-3MHDOUD7.cjs} +73 -3
  18. package/dist/tsup/chunk-3MHDOUD7.cjs.map +1 -0
  19. package/dist/tsup/{chunk-QAZLM4WT.cjs → chunk-4FC7TVS6.cjs} +8 -4
  20. package/dist/tsup/chunk-4FC7TVS6.cjs.map +1 -0
  21. package/dist/tsup/{chunk-4CGA6QJO.cjs → chunk-4UUEB43Y.cjs} +24 -9
  22. package/dist/tsup/chunk-4UUEB43Y.cjs.map +1 -0
  23. package/dist/tsup/{chunk-GVTOE34S.cjs → chunk-5IWLUJ6W.cjs} +222 -235
  24. package/dist/tsup/chunk-5IWLUJ6W.cjs.map +1 -0
  25. package/dist/tsup/{chunk-MMMEZM5J.js → chunk-H6VVZMWN.js} +4 -4
  26. package/dist/tsup/chunk-H6VVZMWN.js.map +1 -0
  27. package/dist/tsup/{chunk-3YY5S6TV.js → chunk-HXUEHHJF.js} +2 -2
  28. package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
  29. package/dist/tsup/{chunk-H7P7WR2Y.js → chunk-I35VSLEM.js} +6 -6
  30. package/dist/tsup/chunk-I35VSLEM.js.map +1 -0
  31. package/dist/tsup/{chunk-H37XQU3I.js → chunk-JBUZRPY5.js} +2 -2
  32. package/dist/tsup/{chunk-CPA4Y3RG.cjs → chunk-JLJJZYCJ.cjs} +10 -10
  33. package/dist/tsup/chunk-JLJJZYCJ.cjs.map +1 -0
  34. package/dist/tsup/{chunk-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
  35. package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
  36. package/dist/tsup/{chunk-VRCIXJRN.js → chunk-L2X3YFER.js} +64 -10
  37. package/dist/tsup/chunk-L2X3YFER.js.map +1 -0
  38. package/dist/tsup/{chunk-Y5NSCZA2.cjs → chunk-MNHKOS6L.cjs} +72 -18
  39. package/dist/tsup/chunk-MNHKOS6L.cjs.map +1 -0
  40. package/dist/tsup/{chunk-KJTA3ATT.js → chunk-NERUIBOT.js} +22 -7
  41. package/dist/tsup/chunk-NERUIBOT.js.map +1 -0
  42. package/dist/tsup/{chunk-4WPEZBK4.cjs → chunk-OST76LRW.cjs} +10 -10
  43. package/dist/tsup/chunk-OST76LRW.cjs.map +1 -0
  44. package/dist/tsup/{chunk-MALSPBAF.cjs → chunk-OZBCXBVP.cjs} +3 -3
  45. package/dist/tsup/{chunk-MALSPBAF.cjs.map → chunk-OZBCXBVP.cjs.map} +1 -1
  46. package/dist/tsup/{chunk-F3Q5BFQ6.js → chunk-PT6OIW5E.js} +66 -79
  47. package/dist/tsup/chunk-PT6OIW5E.js.map +1 -0
  48. package/dist/tsup/{chunk-W7EYSYVI.js → chunk-R6KPN5EW.js} +134 -20
  49. package/dist/tsup/chunk-R6KPN5EW.js.map +1 -0
  50. package/dist/tsup/{chunk-VJFRBJVQ.cjs → chunk-V5KMAMX3.cjs} +138 -24
  51. package/dist/tsup/chunk-V5KMAMX3.cjs.map +1 -0
  52. package/dist/tsup/{chunk-LD5YASJU.cjs → chunk-VE2X4KMG.cjs} +2 -2
  53. package/dist/tsup/{chunk-LD5YASJU.cjs.map → chunk-VE2X4KMG.cjs.map} +1 -1
  54. package/dist/tsup/{chunk-T6YVRM4K.js → chunk-XIX5DOZN.js} +72 -2
  55. package/dist/tsup/chunk-XIX5DOZN.js.map +1 -0
  56. package/dist/tsup/{chunk-2NDZ7JCR.cjs → chunk-ZA7FLHKH.cjs} +1 -1
  57. package/dist/tsup/chunk-ZA7FLHKH.cjs.map +1 -0
  58. package/dist/tsup/{chunk-KIWH5H3K.js → chunk-ZZ3WBRPD.js} +7 -3
  59. package/dist/tsup/chunk-ZZ3WBRPD.js.map +1 -0
  60. package/dist/tsup/client/mod.cjs +9 -9
  61. package/dist/tsup/client/mod.d.cts +5 -5
  62. package/dist/tsup/client/mod.d.ts +5 -5
  63. package/dist/tsup/client/mod.js +8 -8
  64. package/dist/tsup/common/log.cjs +3 -3
  65. package/dist/tsup/common/log.js +2 -2
  66. package/dist/tsup/common/websocket.cjs +4 -4
  67. package/dist/tsup/common/websocket.js +3 -3
  68. package/dist/tsup/{config-Ca8dN4cS.d.cts → config-CzvopP5m.d.cts} +544 -23
  69. package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.cts} +1 -2
  70. package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.ts} +1 -2
  71. package/dist/tsup/{config-0Ta55UV0.d.ts → config-DZuT7tcp.d.ts} +544 -23
  72. package/dist/tsup/context-CyAdY-aA.d.ts +128 -0
  73. package/dist/tsup/context-sNB28g0N.d.cts +128 -0
  74. package/dist/tsup/db/drizzle.cjs +3 -3
  75. package/dist/tsup/db/drizzle.d.cts +1 -1
  76. package/dist/tsup/db/drizzle.d.ts +1 -1
  77. package/dist/tsup/db/drizzle.js +1 -1
  78. package/dist/tsup/db/mod.cjs +2 -2
  79. package/dist/tsup/db/mod.d.cts +2 -2
  80. package/dist/tsup/db/mod.d.ts +2 -2
  81. package/dist/tsup/db/mod.js +1 -1
  82. package/dist/tsup/dynamic/mod.cjs +24 -0
  83. package/dist/tsup/dynamic/mod.cjs.map +1 -0
  84. package/dist/tsup/dynamic/mod.d.cts +37 -0
  85. package/dist/tsup/dynamic/mod.d.ts +37 -0
  86. package/dist/tsup/dynamic/mod.js +24 -0
  87. package/dist/tsup/dynamic/mod.js.map +1 -0
  88. package/dist/tsup/inspector/mod.cjs +6 -6
  89. package/dist/tsup/inspector/mod.js +5 -5
  90. package/dist/tsup/inspector-tab/mod.cjs +173 -0
  91. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  92. package/dist/tsup/inspector-tab/mod.d.cts +250 -0
  93. package/dist/tsup/inspector-tab/mod.d.ts +250 -0
  94. package/dist/tsup/inspector-tab/mod.js +173 -0
  95. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  96. package/dist/tsup/mod.cjs +758 -348
  97. package/dist/tsup/mod.cjs.map +1 -1
  98. package/dist/tsup/mod.d.cts +5 -5
  99. package/dist/tsup/mod.d.ts +5 -5
  100. package/dist/tsup/mod.js +662 -252
  101. package/dist/tsup/mod.js.map +1 -1
  102. package/dist/tsup/test/mod.cjs +21 -18
  103. package/dist/tsup/test/mod.cjs.map +1 -1
  104. package/dist/tsup/test/mod.d.cts +4 -4
  105. package/dist/tsup/test/mod.d.ts +4 -4
  106. package/dist/tsup/test/mod.js +18 -15
  107. package/dist/tsup/test/mod.js.map +1 -1
  108. package/dist/tsup/{utils-DVekpm4I.d.cts → utils-CqDnC_PS.d.cts} +2 -1
  109. package/dist/tsup/{utils-DVekpm4I.d.ts → utils-CqDnC_PS.d.ts} +2 -1
  110. package/dist/tsup/utils.cjs +3 -3
  111. package/dist/tsup/utils.d.cts +1 -1
  112. package/dist/tsup/utils.d.ts +1 -1
  113. package/dist/tsup/utils.js +2 -2
  114. package/dist/tsup/workflow/mod.cjs +383 -322
  115. package/dist/tsup/workflow/mod.cjs.map +1 -1
  116. package/dist/tsup/workflow/mod.d.cts +8 -8
  117. package/dist/tsup/workflow/mod.d.ts +8 -8
  118. package/dist/tsup/workflow/mod.js +360 -299
  119. package/dist/tsup/workflow/mod.js.map +1 -1
  120. package/package.json +35 -14
  121. package/src/actor/config.ts +173 -51
  122. package/src/actor/contexts/index.ts +7 -2
  123. package/src/actor/definition.ts +17 -19
  124. package/src/actor/driver.ts +3 -3
  125. package/src/actor/errors.ts +20 -3
  126. package/src/actor/instance/mod.ts +26 -34
  127. package/src/actor/keys.ts +1 -1
  128. package/src/actor/mod.ts +22 -20
  129. package/src/actor/schema.ts +2 -2
  130. package/src/agent-os/actor/index.ts +38 -18
  131. package/src/agent-os/actor/preview.ts +1 -2
  132. package/src/agent-os/actor/session.ts +2 -2
  133. package/src/agent-os/config.ts +1 -1
  134. package/src/agent-os/fs/database-vfs.ts +1 -1
  135. package/src/agent-os/index.ts +16 -15
  136. package/src/client/actor-common.ts +87 -54
  137. package/src/client/actor-conn.ts +8 -36
  138. package/src/client/actor-handle.ts +69 -51
  139. package/src/client/actor-query.ts +5 -5
  140. package/src/client/errors.ts +1 -1
  141. package/src/client/lifecycle-errors.ts +2 -4
  142. package/src/client/query.ts +1 -1
  143. package/src/client/queue.ts +8 -3
  144. package/src/client/raw-utils.ts +8 -6
  145. package/src/client/resolve-gateway-target.ts +1 -1
  146. package/src/client/utils.ts +2 -7
  147. package/src/common/actor-websocket.ts +3 -1
  148. package/src/common/bare/actor-persist/v1.ts +205 -163
  149. package/src/common/bare/actor-persist/v2.ts +265 -213
  150. package/src/common/bare/actor-persist/v3.ts +176 -172
  151. package/src/common/bare/actor-persist/v4.ts +254 -253
  152. package/src/common/bare/transport/v1.ts +659 -543
  153. package/src/common/client-protocol-versioned.ts +66 -64
  154. package/src/common/database/config.ts +2 -8
  155. package/src/common/database/native-database.ts +1 -1
  156. package/src/common/database/shared.ts +1 -0
  157. package/src/common/encoding.ts +250 -16
  158. package/src/common/engine.ts +28 -1
  159. package/src/common/eventsource.ts +1 -1
  160. package/src/common/inline-websocket-adapter.ts +14 -13
  161. package/src/common/log.ts +1 -0
  162. package/src/common/router.ts +13 -17
  163. package/src/common/utils.ts +1 -150
  164. package/src/common/websocket-interface.ts +1 -1
  165. package/src/db/mod.ts +1 -1
  166. package/src/devtools-loader/index.ts +4 -7
  167. package/src/devtools-loader/serve-devtools.ts +26 -0
  168. package/src/drivers/engine/actor-driver.ts +58 -56
  169. package/src/dynamic/instance.ts +32 -0
  170. package/src/dynamic/internal.ts +50 -0
  171. package/src/dynamic/isolate-runtime.ts +66 -0
  172. package/src/dynamic/mod.ts +32 -0
  173. package/src/engine-client/actor-http-client.ts +3 -3
  174. package/src/engine-client/actor-websocket-client.ts +6 -5
  175. package/src/engine-client/api-endpoints.ts +51 -2
  176. package/src/engine-client/api-utils.ts +2 -2
  177. package/src/engine-client/driver.ts +1 -1
  178. package/src/engine-client/mod.ts +6 -3
  179. package/src/engine-client/ws-proxy.ts +9 -4
  180. package/src/inspector/client.browser.ts +5 -11
  181. package/src/inspector/mod.ts +1 -3
  182. package/src/inspector-tab/mod.ts +315 -0
  183. package/src/registry/config/envoy.ts +1 -2
  184. package/src/registry/config/index.ts +40 -16
  185. package/src/registry/index.ts +209 -73
  186. package/src/registry/napi-runtime.ts +29 -2
  187. package/src/registry/native-validation.ts +10 -12
  188. package/src/registry/native.ts +433 -198
  189. package/src/registry/process-metrics.ts +250 -0
  190. package/src/registry/runtime.ts +52 -1
  191. package/src/registry/wasm-runtime.ts +29 -2
  192. package/src/registry/write-through-proxy.ts +40 -0
  193. package/src/serde.ts +2 -2
  194. package/src/serverless/configure.ts +18 -7
  195. package/src/test/mod.ts +11 -8
  196. package/src/utils/endpoint-parser.ts +1 -1
  197. package/src/utils/env-vars.ts +37 -0
  198. package/src/utils/router.ts +1 -1
  199. package/src/utils.ts +1 -2
  200. package/src/workflow/context.ts +699 -240
  201. package/src/workflow/driver.ts +23 -12
  202. package/src/workflow/inspector.ts +4 -3
  203. package/src/workflow/mod.ts +37 -23
  204. package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
  205. package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
  206. package/dist/tsup/chunk-4CGA6QJO.cjs.map +0 -1
  207. package/dist/tsup/chunk-4WPEZBK4.cjs.map +0 -1
  208. package/dist/tsup/chunk-CPA4Y3RG.cjs.map +0 -1
  209. package/dist/tsup/chunk-F3Q5BFQ6.js.map +0 -1
  210. package/dist/tsup/chunk-GVTOE34S.cjs.map +0 -1
  211. package/dist/tsup/chunk-H7P7WR2Y.js.map +0 -1
  212. package/dist/tsup/chunk-KIWH5H3K.js.map +0 -1
  213. package/dist/tsup/chunk-KJTA3ATT.js.map +0 -1
  214. package/dist/tsup/chunk-MMMEZM5J.js.map +0 -1
  215. package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
  216. package/dist/tsup/chunk-QAZLM4WT.cjs.map +0 -1
  217. package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
  218. package/dist/tsup/chunk-VJFRBJVQ.cjs.map +0 -1
  219. package/dist/tsup/chunk-VRCIXJRN.js.map +0 -1
  220. package/dist/tsup/chunk-W7EYSYVI.js.map +0 -1
  221. package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
  222. package/dist/tsup/chunk-Y5NSCZA2.cjs.map +0 -1
  223. package/dist/tsup/context-B_IWbWne.d.ts +0 -92
  224. package/dist/tsup/context-CUrQ9MHc.d.cts +0 -92
  225. package/src/utils/serve.ts +0 -217
  226. /package/dist/tsup/{chunk-H37XQU3I.js.map → chunk-JBUZRPY5.js.map} +0 -0
@@ -1,1394 +1,1812 @@
1
- // 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
+ // src/agent-os/actor/index.ts
2
+ import { AgentOs, createInMemoryFileSystem } from "@rivet-dev/agent-os-core";
54
3
 
55
- // src/agent-os/fs/database-vfs.ts
56
- import * as posixPath from "path/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
+ import { z } from "zod/v4";
6
+ var DEFAULT_SLEEP_GRACE_PERIOD = 15e3;
7
+ var zFunction = () => z.custom((val) => typeof val === "function");
8
+ var WorkflowInspectorConfigSchema = z.object({
9
+ getHistory: zFunction(),
10
+ onHistoryUpdated: zFunction().optional(),
11
+ replayFromStep: zFunction().optional()
12
+ });
13
+ var RunInspectorConfigSchema = 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 = z.enum(BUILTIN_INSPECTOR_TAB_IDS);
25
+ var CUSTOM_INSPECTOR_TAB_ID_RE = /^[A-Za-z0-9_-]+$/;
26
+ var CustomInspectorTabEntrySchema = z.object({
27
+ id: z.string().regex(
28
+ CUSTOM_INSPECTOR_TAB_ID_RE,
29
+ "inspector.tabs[].id must contain only letters, digits, underscore, or dash"
30
+ ),
31
+ label: z.string().min(1),
32
+ source: 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: z.string().min(1).optional(),
38
+ hidden: z.literal(false).optional()
39
+ }).strict();
40
+ var HideInspectorTabEntrySchema = z.object({
41
+ id: BuiltinInspectorTabIdSchema,
42
+ hidden: z.literal(true)
43
+ }).strict();
44
+ var InspectorTabEntrySchema = z.union([
45
+ CustomInspectorTabEntrySchema,
46
+ HideInspectorTabEntrySchema
47
+ ]);
48
+ var ActorInspectorConfigSchema = z.object({
49
+ tabs: 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];
127
- }
128
- async function getEntryOrThrow(path) {
129
- const entry = await getEntry(path);
130
- if (!entry) {
131
- throwENOENT(path);
132
- }
133
- return entry;
62
+ },
63
+ {
64
+ message: "Custom inspector tab id collides with a built-in (use hidden: true to hide a built-in)",
65
+ path: ["tabs"]
134
66
  }
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
- }
67
+ );
68
+ var RunConfigSchema = z.object({
69
+ /** Display name for the actor in the Inspector UI. */
70
+ name: z.string().optional(),
71
+ /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
72
+ icon: 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 = z.union([zFunction(), RunConfigSchema]).optional();
79
+ var GlobalActorOptionsBaseSchema = z.object({
80
+ /** Display name for the actor in the Inspector UI. */
81
+ name: z.string().optional(),
82
+ /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
83
+ icon: 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: z.union([z.boolean(), zFunction()]).default(false)
92
+ }).strict();
93
+ var GlobalActorOptionsSchema = GlobalActorOptionsBaseSchema.prefault(
94
+ () => ({})
95
+ );
96
+ var InstanceActorOptionsBaseSchema = z.object({
97
+ createVarsTimeout: z.number().positive().default(5e3),
98
+ createConnStateTimeout: z.number().positive().default(5e3),
99
+ onBeforeConnectTimeout: z.number().positive().default(5e3),
100
+ onConnectTimeout: z.number().positive().default(5e3),
101
+ onMigrateTimeout: z.number().positive().default(3e4),
102
+ sleepGracePeriod: 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: 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: z.number().positive().optional(),
107
+ stateSaveInterval: z.number().positive().default(1e3),
108
+ actionTimeout: z.number().positive().default(6e4),
109
+ connectionLivenessTimeout: z.number().positive().default(2500),
110
+ connectionLivenessInterval: 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: z.boolean().default(false),
113
+ sleepTimeout: z.number().positive().default(3e4),
114
+ maxQueueSize: z.number().positive().default(1e3),
115
+ maxQueueMessageSize: 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: z.number().nonnegative().optional(),
118
+ /** Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading. */
119
+ preloadMaxConnectionsBytes: 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 = 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: z.record(z.string(), zFunction()).default(() => ({})),
140
+ actionInputSchemas: z.record(z.string(), z.any()).optional(),
141
+ connParamsSchema: z.any().optional(),
142
+ events: z.record(z.string(), z.any()).optional(),
143
+ queues: z.record(z.string(), z.any()).optional(),
144
+ state: z.any().optional(),
145
+ createState: zFunction().optional(),
146
+ connState: z.any().optional(),
147
+ createConnState: zFunction().optional(),
148
+ vars: z.any().optional(),
149
+ db: 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"]
145
158
  }
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
- });
159
+ ).refine(
160
+ (data) => !(data.connState !== void 0 && data.createConnState !== void 0),
161
+ {
162
+ message: "Cannot define both 'connState' and 'createConnState'",
163
+ path: ["connState"]
157
164
  }
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);
165
+ ).refine(
166
+ (data) => !(data.vars !== void 0 && data.createVars !== void 0),
167
+ {
168
+ message: "Cannot define both 'vars' and 'createVars'",
169
+ path: ["vars"]
170
+ }
171
+ );
172
+ var DocActorOptionsSchema = z.object({
173
+ name: z.string().optional().describe("Display name for the actor in the Inspector UI."),
174
+ icon: 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: z.number().optional().describe("Timeout in ms for createVars handler. Default: 5000"),
178
+ createConnStateTimeout: z.number().optional().describe(
179
+ "Timeout in ms for createConnState handler. Default: 5000"
180
+ ),
181
+ onMigrateTimeout: z.number().optional().describe("Timeout in ms for onMigrate handler. Default: 30000"),
182
+ onBeforeConnectTimeout: z.number().optional().describe(
183
+ "Timeout in ms for onBeforeConnect handler. Default: 5000"
184
+ ),
185
+ onConnectTimeout: z.number().optional().describe("Timeout in ms for onConnect handler. Default: 5000"),
186
+ sleepGracePeriod: 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: 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: 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: z.number().optional().describe(
196
+ "Interval in ms between automatic state saves. Default: 1000"
197
+ ),
198
+ actionTimeout: z.number().optional().describe("Timeout in ms for action handlers. Default: 60000"),
199
+ connectionLivenessTimeout: z.number().optional().describe(
200
+ "Timeout in ms for connection liveness checks. Default: 2500"
201
+ ),
202
+ connectionLivenessInterval: z.number().optional().describe(
203
+ "Interval in ms between connection liveness checks. Default: 5000"
204
+ ),
205
+ noSleep: 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: z.number().optional().describe(
209
+ "Time in ms of inactivity before the actor sleeps. Default: 30000"
210
+ ),
211
+ maxQueueSize: z.number().optional().describe(
212
+ "Maximum number of queue messages before rejecting new messages. Default: 1000"
213
+ ),
214
+ maxQueueMessageSize: z.number().optional().describe(
215
+ "Maximum size of each queue message in bytes. Default: 65536"
216
+ ),
217
+ canHibernateWebSocket: 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: z.number().optional().describe(
221
+ "Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading."
222
+ ),
223
+ preloadMaxConnectionsBytes: 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 = z.object({
228
+ state: z.unknown().optional().describe(
229
+ "Initial state value for the actor. Cannot be used with createState."
230
+ ),
231
+ createState: z.unknown().optional().describe(
232
+ "Function to create initial state. Receives context and input. Cannot be used with state."
233
+ ),
234
+ connState: z.unknown().optional().describe(
235
+ "Initial connection state value. Cannot be used with createConnState."
236
+ ),
237
+ createConnState: 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: z.unknown().optional().describe(
241
+ "Initial ephemeral variables value. Cannot be used with createVars."
242
+ ),
243
+ createVars: z.unknown().optional().describe(
244
+ "Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars."
245
+ ),
246
+ db: z.unknown().optional().describe("Database provider instance for the actor."),
247
+ onCreate: z.unknown().optional().describe(
248
+ "Called when the actor is first initialized. Use to initialize state."
249
+ ),
250
+ onDestroy: z.unknown().optional().describe("Called when the actor is destroyed."),
251
+ onMigrate: 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: z.unknown().optional().describe(
255
+ "Called when the actor wakes up and is ready to receive connections and actions."
256
+ ),
257
+ onSleep: z.unknown().optional().describe(
258
+ "Called when the actor is stopping or sleeping. Use to clean up resources."
259
+ ),
260
+ run: 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: z.unknown().optional().describe(
264
+ "Called when the actor's state changes. State changes within this hook won't trigger recursion."
265
+ ),
266
+ onBeforeConnect: 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: z.unknown().optional().describe(
270
+ "Called when a client successfully connects. The connection is visible in c.conns before this runs."
271
+ ),
272
+ onDisconnect: z.unknown().optional().describe("Called when a client disconnects."),
273
+ onBeforeActionResponse: z.unknown().optional().describe(
274
+ "Called before sending an action response. Use to transform output."
275
+ ),
276
+ onRequest: z.unknown().optional().describe(
277
+ "Called for raw HTTP requests to /actors/{name}/http/* endpoints."
278
+ ),
279
+ onWebSocket: z.unknown().optional().describe(
280
+ "Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints."
281
+ ),
282
+ actions: z.record(z.string(), z.unknown()).optional().describe(
283
+ "Map of action name to handler function. Defaults to an empty object."
284
+ ),
285
+ actionInputSchemas: z.record(z.string(), z.unknown()).optional().describe(
286
+ "Optional schema map for validating action argument tuples in native runtimes."
287
+ ),
288
+ connParamsSchema: z.unknown().optional().describe(
289
+ "Optional schema for validating connection params in native runtimes."
290
+ ),
291
+ events: z.record(z.string(), z.unknown()).optional().describe("Map of event names to schemas."),
292
+ queues: z.record(z.string(), 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
+ import {
298
+ pino,
299
+ stdTimeFunctions
300
+ } from "pino";
301
+ import { z as z2 } from "zod/v4";
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.1",
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"
180
347
  }
181
- return entry.content ?? new Uint8Array(0);
182
- },
183
- async readTextFile(p) {
184
- const data = await backend.readFile(p);
185
- return new TextDecoder().decode(data);
186
348
  },
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);
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"
193
357
  }
194
- const children = await getChildEntries(path);
195
- return children.map((child) => posixPath.basename(child.path));
196
358
  },
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);
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"
203
367
  }
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
368
  },
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
- );
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"
244
377
  }
245
378
  },
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);
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"
253
387
  }
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
388
  },
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);
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"
291
397
  }
292
398
  },
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);
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"
311
411
  }
312
- await db2.execute(
313
- "DELETE FROM agent_os_fs_entries WHERE path = ?",
314
- path
315
- );
316
412
  },
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);
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"
327
421
  }
328
- await db2.execute(
329
- "DELETE FROM agent_os_fs_entries WHERE path = ?",
330
- path
331
- );
332
422
  },
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
- }
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"
367
431
  }
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
432
  },
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);
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"
382
441
  }
383
- return path;
384
442
  },
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);
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"
392
451
  }
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
452
  },
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;
453
+ "./inspector/client": {
454
+ import: {
455
+ types: "./dist/browser/inspector/client.d.ts",
456
+ default: "./dist/browser/inspector/client.js"
414
457
  }
415
- return entry.symlink_target;
416
458
  },
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
- },
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
- );
447
- },
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
- );
460
- },
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);
467
- }
468
- const existing = 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);
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"
475
467
  }
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
468
  },
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);
492
- }
493
- const content = entry.content ?? new Uint8Array(0);
494
- const end = Math.min(offset + length, content.byteLength);
495
- if (offset >= content.byteLength) {
496
- return new Uint8Array(0);
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/zod-openapi": "^1.1.5",
506
+ "@rivet-dev/agent-os-core": "^0.1.1",
507
+ "@rivetkit/bare-ts": "^0.6.2",
508
+ "@rivetkit/engine-cli": "workspace:*",
509
+ "@rivetkit/engine-envoy-protocol": "workspace:*",
510
+ "@rivetkit/on-change": "6.0.1",
511
+ "@rivetkit/rivetkit-napi": "workspace:*",
512
+ "@rivetkit/rivetkit-wasm": "workspace:*",
513
+ "@rivetkit/traces": "workspace:*",
514
+ "@rivetkit/virtual-websocket": "workspace:*",
515
+ "@rivetkit/workflow-engine": "workspace:*",
516
+ "cbor-x": "^1.6.0",
517
+ "drizzle-orm": "^0.44.2",
518
+ hono: "^4.7.0",
519
+ invariant: "^2.2.4",
520
+ "p-retry": "^6.2.1",
521
+ pino: "^9.5.0",
522
+ uuid: "^12.0.0",
523
+ vbare: "^0.0.4",
524
+ zod: "^4.1.0"
525
+ },
526
+ devDependencies: {
527
+ "@biomejs/biome": "^2.3",
528
+ "@copilotkit/llmock": "^1.6.0",
529
+ "@hono/node-server": "^1.18.2",
530
+ "@hono/node-ws": "^1.1.1",
531
+ "@rivet-dev/agent-os-common": "*",
532
+ "@rivet-dev/agent-os-pi": "^0.1.1",
533
+ "@standard-schema/spec": "^1.0.0",
534
+ "@types/invariant": "^2",
535
+ "@types/node": "^22.13.1",
536
+ eventsource: "^4.0.0",
537
+ "get-port": "^7.1.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);
506
- }
507
- const content = 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
- );
554
+ eventsource: {
555
+ optional: true
556
+ },
557
+ ws: {
558
+ optional: true
522
559
  }
523
- };
524
- return backend;
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
+ }
525
572
  }
526
573
 
527
- // src/agent-os/actor/index.ts
528
- import { AgentOs, createInMemoryFileSystem } from "@rivet-dev/agent-os-core";
574
+ // src/utils/env-vars.ts
575
+ var getLogLevel = () => getEnvUniversal("RIVET_LOG_LEVEL") ?? getEnvUniversal("LOG_LEVEL");
576
+ var getLogTarget = () => getEnvUniversal("RIVET_LOG_TARGET") === "1";
577
+ var getLogTimestamp = () => getEnvUniversal("RIVET_LOG_TIMESTAMP") === "1";
529
578
 
530
- // src/actor/config.ts
531
- import { z } from "zod/v4";
532
- var DEFAULT_SLEEP_GRACE_PERIOD = 15e3;
533
- var zFunction = () => z.custom((val) => typeof val === "function");
534
- var WorkflowInspectorConfigSchema = z.object({
535
- getHistory: zFunction(),
536
- onHistoryUpdated: zFunction().optional(),
537
- replayFromStep: zFunction().optional()
538
- });
539
- var RunInspectorConfigSchema = z.object({
540
- workflow: WorkflowInspectorConfigSchema.optional()
541
- }).optional();
542
- var RunConfigSchema = z.object({
543
- /** Display name for the actor in the Inspector UI. */
544
- name: z.string().optional(),
545
- /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
546
- icon: 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 = z.union([zFunction(), RunConfigSchema]).optional();
553
- var GlobalActorOptionsBaseSchema = z.object({
554
- /** Display name for the actor in the Inspector UI. */
555
- name: z.string().optional(),
556
- /** Icon for the actor in the Inspector UI. Can be an emoji or FontAwesome icon name. */
557
- icon: 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: z.union([z.boolean(), zFunction()]).default(false)
566
- }).strict();
567
- var GlobalActorOptionsSchema = GlobalActorOptionsBaseSchema.prefault(
568
- () => ({})
569
- );
570
- var InstanceActorOptionsBaseSchema = z.object({
571
- createVarsTimeout: z.number().positive().default(5e3),
572
- createConnStateTimeout: z.number().positive().default(5e3),
573
- onBeforeConnectTimeout: z.number().positive().default(5e3),
574
- onConnectTimeout: z.number().positive().default(5e3),
575
- onMigrateTimeout: z.number().positive().default(3e4),
576
- sleepGracePeriod: 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: 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: z.number().positive().optional(),
581
- stateSaveInterval: z.number().positive().default(1e3),
582
- actionTimeout: z.number().positive().default(6e4),
583
- connectionLivenessTimeout: z.number().positive().default(2500),
584
- connectionLivenessInterval: 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: z.boolean().default(false),
587
- sleepTimeout: z.number().positive().default(3e4),
588
- maxQueueSize: z.number().positive().default(1e3),
589
- maxQueueMessageSize: 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: z.number().nonnegative().optional(),
592
- /** Override RivetKit's connections preload budget for this actor. Set to 0 to disable connections preloading. */
593
- preloadMaxConnectionsBytes: 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 = 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: z.record(z.string(), zFunction()).default(() => ({})),
614
- actionInputSchemas: z.record(z.string(), z.any()).optional(),
615
- connParamsSchema: z.any().optional(),
616
- events: z.record(z.string(), z.any()).optional(),
617
- queues: z.record(z.string(), z.any()).optional(),
618
- state: z.any().optional(),
619
- createState: zFunction().optional(),
620
- connState: z.any().optional(),
621
- createConnState: zFunction().optional(),
622
- vars: z.any().optional(),
623
- db: 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"]
579
+ // src/common/log.ts
580
+ var baseLogger;
581
+ var configuredLogLevel;
582
+ var loggerCache = /* @__PURE__ */ new Map();
583
+ var LogLevelSchema = z2.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;
631
595
  }
632
- ).refine(
633
- (data) => !(data.connState !== void 0 && data.createConnState !== void 0),
634
- {
635
- message: "Cannot define both 'connState' and 'createConnState'",
636
- path: ["connState"]
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(
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() ? 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);
666
+ }
667
+ }
668
+ };
669
+ }
670
+ function formatLogfmtLine(raw) {
671
+ let data;
672
+ try {
673
+ data = JSON.parse(raw);
674
+ } catch {
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 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")}"`;
723
+ }
724
+
725
+ // src/actor/log.ts
726
+ function loggerWithoutContext() {
727
+ return getLogger("actor-runtime");
728
+ }
729
+
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
+ }
742
+ }
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 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 = ((_a = ctx.metrics) == null ? void 0 : _a.totalKvReads) ?? 0;
835
+ const kvWritesBefore = ((_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 ((_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
+ import { z as z3 } from "zod/v4";
927
+ var zFunction2 = () => z3.custom((val) => typeof val === "function");
928
+ var AgentOsOptionsSchema = z3.custom(
929
+ (val) => typeof val === "object" && val !== null
644
930
  );
645
- var DocActorOptionsSchema = z.object({
646
- name: z.string().optional().describe("Display name for the actor in the Inspector UI."),
647
- icon: 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: z.number().optional().describe("Timeout in ms for createVars handler. Default: 5000"),
651
- createConnStateTimeout: z.number().optional().describe(
652
- "Timeout in ms for createConnState handler. Default: 5000"
653
- ),
654
- onMigrateTimeout: z.number().optional().describe("Timeout in ms for onMigrate handler. Default: 30000"),
655
- onBeforeConnectTimeout: z.number().optional().describe(
656
- "Timeout in ms for onBeforeConnect handler. Default: 5000"
657
- ),
658
- onConnectTimeout: z.number().optional().describe("Timeout in ms for onConnect handler. Default: 5000"),
659
- sleepGracePeriod: 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: 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: 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: z.number().optional().describe(
669
- "Interval in ms between automatic state saves. Default: 1000"
670
- ),
671
- actionTimeout: z.number().optional().describe("Timeout in ms for action handlers. Default: 60000"),
672
- connectionLivenessTimeout: z.number().optional().describe(
673
- "Timeout in ms for connection liveness checks. Default: 2500"
674
- ),
675
- connectionLivenessInterval: z.number().optional().describe(
676
- "Interval in ms between connection liveness checks. Default: 5000"
677
- ),
678
- noSleep: 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: z.number().optional().describe(
682
- "Time in ms of inactivity before the actor sleeps. Default: 30000"
683
- ),
684
- maxQueueSize: z.number().optional().describe(
685
- "Maximum number of queue messages before rejecting new messages. Default: 1000"
686
- ),
687
- maxQueueMessageSize: z.number().optional().describe(
688
- "Maximum size of each queue message in bytes. Default: 65536"
689
- ),
690
- canHibernateWebSocket: 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: z.number().optional().describe(
694
- "Override RivetKit's workflow preload budget for this actor. Set to 0 to disable workflow preloading."
695
- ),
696
- preloadMaxConnectionsBytes: 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 = z.object({
701
- state: z.unknown().optional().describe(
702
- "Initial state value for the actor. Cannot be used with createState."
703
- ),
704
- createState: z.unknown().optional().describe(
705
- "Function to create initial state. Receives context and input. Cannot be used with state."
706
- ),
707
- connState: z.unknown().optional().describe(
708
- "Initial connection state value. Cannot be used with createConnState."
709
- ),
710
- createConnState: 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: z.unknown().optional().describe(
714
- "Initial ephemeral variables value. Cannot be used with createVars."
715
- ),
716
- createVars: z.unknown().optional().describe(
717
- "Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars."
718
- ),
719
- db: z.unknown().optional().describe("Database provider instance for the actor."),
720
- onCreate: z.unknown().optional().describe(
721
- "Called when the actor is first initialized. Use to initialize state."
722
- ),
723
- onDestroy: z.unknown().optional().describe("Called when the actor is destroyed."),
724
- onMigrate: 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: z.unknown().optional().describe(
728
- "Called when the actor wakes up and is ready to receive connections and actions."
729
- ),
730
- onSleep: z.unknown().optional().describe(
731
- "Called when the actor is stopping or sleeping. Use to clean up resources."
732
- ),
733
- run: 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: z.unknown().optional().describe(
737
- "Called when the actor's state changes. State changes within this hook won't trigger recursion."
738
- ),
739
- onBeforeConnect: 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: z.unknown().optional().describe(
743
- "Called when a client successfully connects. The connection is visible in c.conns before this runs."
744
- ),
745
- onDisconnect: z.unknown().optional().describe("Called when a client disconnects."),
746
- onBeforeActionResponse: z.unknown().optional().describe(
747
- "Called before sending an action response. Use to transform output."
748
- ),
749
- onRequest: z.unknown().optional().describe(
750
- "Called for raw HTTP requests to /actors/{name}/http/* endpoints."
751
- ),
752
- onWebSocket: z.unknown().optional().describe(
753
- "Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints."
754
- ),
755
- actions: z.record(z.string(), z.unknown()).optional().describe(
756
- "Map of action name to handler function. Defaults to an empty object."
757
- ),
758
- actionInputSchemas: z.record(z.string(), z.unknown()).optional().describe(
759
- "Optional schema map for validating action argument tuples in native runtimes."
760
- ),
761
- connParamsSchema: z.unknown().optional().describe(
762
- "Optional schema for validating connection params in native runtimes."
763
- ),
764
- events: z.record(z.string(), z.unknown()).optional().describe("Map of event names to schemas."),
765
- queues: z.record(z.string(), 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 = z3.object({
932
+ options: AgentOsOptionsSchema.optional(),
933
+ preview: z3.object({
934
+ defaultExpiresInSeconds: z3.number().positive().default(3600),
935
+ maxExpiresInSeconds: z3.number().positive().default(86400)
936
+ }).strict().prefault(() => ({})),
937
+ onBeforeConnect: zFunction2().optional(),
938
+ onSessionEvent: zFunction2().optional(),
939
+ onPermissionRequest: zFunction2().optional()
940
+ }).strict();
941
+
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);
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
+ );
970
+
971
+ CREATE INDEX IF NOT EXISTS idx_fs_entries_parent
972
+ ON agent_os_fs_entries(path);
973
+
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
+ );
768
981
 
769
- // src/common/log.ts
770
- import {
771
- pino,
772
- stdTimeFunctions
773
- } from "pino";
774
- import { z as z2 } from "zod/v4";
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.9",
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: (options == null ? void 0 : options.method) ?? "GET",
1062
+ headers,
1063
+ body: (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
+ import crypto from "crypto";
1083
+ function generateToken() {
1084
+ const bytes = crypto.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 = 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 = 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
- "@rivet-dev/agent-os-core": "^0.1.1",
959
- "@hono/node-server": "^1.18.2",
960
- "@hono/node-ws": "^1.1.1",
961
- "@hono/zod-openapi": "^1.1.5",
962
- "@rivetkit/bare-ts": "^0.6.2",
963
- "@rivetkit/engine-cli": "workspace:*",
964
- "@rivetkit/engine-envoy-protocol": "workspace:*",
965
- "@rivetkit/rivetkit-napi": "workspace:*",
966
- "@rivetkit/rivetkit-wasm": "workspace:*",
967
- "@rivetkit/traces": "workspace:*",
968
- "@rivetkit/virtual-websocket": "workspace:*",
969
- "@rivetkit/workflow-engine": "workspace:*",
970
- "cbor-x": "^1.6.0",
971
- "drizzle-orm": "^0.44.2",
972
- "get-port": "^7.1.0",
973
- hono: "^4.7.0",
974
- invariant: "^2.2.4",
975
- "p-retry": "^6.2.1",
976
- pino: "^9.5.0",
977
- uuid: "^12.0.0",
978
- vbare: "^0.0.4",
979
- zod: "^4.1.0"
980
- },
981
- devDependencies: {
982
- "@copilotkit/llmock": "^1.6.0",
983
- "@rivet-dev/agent-os-common": "*",
984
- "@rivet-dev/agent-os-pi": "^0.1.1",
985
- "@biomejs/biome": "^2.3",
986
- "@standard-schema/spec": "^1.0.0",
987
- "@types/invariant": "^2",
988
- "@types/node": "^22.13.1",
989
- eventsource: "^4.0.0",
990
- tsup: "^8.4.0",
991
- tsx: "^4.19.4",
992
- typescript: "^5.7.3",
993
- "vite-tsconfig-paths": "^5.1.4",
994
- vitest: "^3.1.1",
995
- ws: "^8.18.1"
996
- },
997
- peerDependencies: {
998
- "drizzle-kit": "^0.31.2",
999
- eventsource: "^4.0.0",
1000
- ws: "^8.0.0"
1001
- },
1002
- peerDependenciesMeta: {
1003
- "drizzle-kit": {
1004
- 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);
1005
1287
  },
1006
- eventsource: {
1007
- optional: true
1288
+ stopProcess: async (c, pid) => {
1289
+ const agentOs2 = await ensureVm(c, config);
1290
+ agentOs2.stopProcess(pid);
1008
1291
  },
1009
- ws: {
1010
- optional: true
1292
+ killProcess: async (c, pid) => {
1293
+ const agentOs2 = await ensureVm(c, config);
1294
+ agentOs2.killProcess(pid);
1011
1295
  }
1012
- },
1013
- stableVersion: "0.8.0"
1014
- };
1015
-
1016
- // src/utils.ts
1017
- var VERSION = package_default.version;
1018
- function getEnvUniversal(key) {
1019
- if (typeof Deno !== "undefined") {
1020
- return Deno.env.get(key);
1021
- } else if (typeof process !== "undefined") {
1022
- return process.env[key];
1023
- }
1296
+ };
1024
1297
  }
1025
1298
 
1026
- // src/utils/env-vars.ts
1027
- var getLogLevel = () => getEnvUniversal("RIVET_LOG_LEVEL") ?? getEnvUniversal("LOG_LEVEL");
1028
- var getLogTarget = () => getEnvUniversal("RIVET_LOG_TARGET") === "1";
1029
- var getLogTimestamp = () => getEnvUniversal("RIVET_LOG_TIMESTAMP") === "1";
1030
-
1031
- // src/common/log.ts
1032
- var baseLogger;
1033
- var configuredLogLevel;
1034
- var loggerCache = /* @__PURE__ */ new Map();
1035
- var LogLevelSchema = z2.enum([
1036
- "trace",
1037
- "debug",
1038
- "info",
1039
- "warn",
1040
- "error",
1041
- "fatal",
1042
- "silent"
1043
- ]);
1044
- function getPinoLevel(logLevel) {
1045
- if (logLevel) {
1046
- return logLevel;
1047
- }
1048
- if (configuredLogLevel) {
1049
- 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
+ }
1050
1310
  }
1051
- const raw = (getLogLevel() || "warn").toString().toLowerCase();
1052
- const parsed = LogLevelSchema.safeParse(raw);
1053
- if (parsed.success) {
1054
- 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}`);
1055
1316
  }
1056
- return "info";
1057
1317
  }
1058
- function getIncludeTarget() {
1059
- return getLogTarget();
1318
+ function toSessionRecord(agentOs2, sessionId, agentType) {
1319
+ return {
1320
+ sessionId,
1321
+ agentType,
1322
+ capabilities: agentOs2.getSessionCapabilities(sessionId) ?? {},
1323
+ agentInfo: agentOs2.getSessionAgentInfo(sessionId)
1324
+ };
1060
1325
  }
1061
- function configureDefaultLogger(logLevel) {
1062
- if (logLevel) {
1063
- configuredLogLevel = logLevel;
1064
- }
1065
- baseLogger = pino(
1066
- {
1067
- level: getPinoLevel(logLevel),
1068
- messageKey: "msg",
1069
- // Do not include pid/hostname in output
1070
- base: {},
1071
- // Keep the numeric level so the logfmt sink can match Pino's levels.
1072
- formatters: {
1073
- level(_label, number) {
1074
- return { level: number };
1326
+ async function persistSession(c, agentOs2, sessionId, agentType) {
1327
+ const now = Date.now();
1328
+ const capabilities = 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 = (((_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);
1075
1387
  }
1076
- },
1077
- timestamp: getLogTimestamp() ? 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
+ }
1078
1495
  },
1079
- createLogfmtDestination()
1080
- );
1081
- loggerCache.clear();
1082
- }
1083
- function getBaseLogger() {
1084
- if (!baseLogger) {
1085
- configureDefaultLogger();
1086
- }
1087
- return baseLogger;
1088
- }
1089
- function getLogger(name = "default") {
1090
- const cached = loggerCache.get(name);
1091
- if (cached) {
1092
- return cached;
1093
- }
1094
- const base = getBaseLogger();
1095
- const child = getIncludeTarget() ? base.child({ target: name }) : base;
1096
- loggerCache.set(name, child);
1097
- 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
+ };
1098
1517
  }
1099
- var PINO_LEVEL_LABELS = {
1100
- 10: "trace",
1101
- 20: "debug",
1102
- 30: "info",
1103
- 40: "warn",
1104
- 50: "error",
1105
- 60: "fatal"
1106
- };
1107
- function createLogfmtDestination() {
1518
+ function buildConfigActions(_config) {
1108
1519
  return {
1109
- write(msg) {
1110
- var _a;
1111
- const line = formatLogfmtLine(msg);
1112
- if (typeof process !== "undefined" && ((_a = process.stdout) == null ? void 0 : _a.write)) {
1113
- process.stdout.write(`${line}
1114
- `);
1115
- } else {
1116
- 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");
1117
1587
  }
1588
+ return stripFunctions(
1589
+ agentOs2.rawSessionSend(sessionId, method, params)
1590
+ );
1118
1591
  }
1119
1592
  };
1120
1593
  }
1121
- function formatLogfmtLine(raw) {
1122
- let data;
1123
- try {
1124
- data = JSON.parse(raw);
1125
- } catch {
1126
- return raw.trimEnd();
1127
- }
1128
- const parts = [];
1129
- appendLogfmtEntry(parts, "level", formatPinoLevel(data.level));
1130
- if (data.time !== void 0) {
1131
- appendLogfmtEntry(parts, "ts", data.time);
1132
- }
1133
- for (const [key, value] of Object.entries(data)) {
1134
- if (key === "level" || key === "time") {
1135
- 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
+ }));
1136
1624
  }
1137
- appendLogfmtEntry(parts, key, value);
1138
- }
1139
- return parts.join(" ");
1140
- }
1141
- function formatPinoLevel(level) {
1142
- if (typeof level === "number") {
1143
- return PINO_LEVEL_LABELS[level] ?? level.toString();
1144
- }
1145
- if (typeof level === "string") {
1146
- return level.toLowerCase();
1147
- }
1148
- return "info";
1149
- }
1150
- function appendLogfmtEntry(parts, key, value) {
1151
- const safeKey = key.replace(/[\s="]/g, "");
1152
- if (safeKey.length === 0) {
1153
- return;
1154
- }
1155
- parts.push(`${safeKey}=${formatLogfmtValue(value)}`);
1156
- }
1157
- function formatLogfmtValue(value) {
1158
- if (typeof value === "number" || typeof value === "boolean") {
1159
- return String(value);
1160
- }
1161
- if (value === null || value === void 0) {
1162
- return "null";
1163
- }
1164
- if (typeof value === "string") {
1165
- return quoteLogfmtString(value);
1166
- }
1167
- return quoteLogfmtString(JSON.stringify(value));
1168
- }
1169
- function quoteLogfmtString(value) {
1170
- if (!/[\s="]/.test(value)) {
1171
- return value;
1172
- }
1173
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
1174
- }
1175
-
1176
- // src/actor/log.ts
1177
- function loggerWithoutContext() {
1178
- return getLogger("actor-runtime");
1625
+ };
1179
1626
  }
1180
1627
 
1181
- // src/actor/definition.ts
1182
- var warnedDeprecatedTimeoutKeys = /* @__PURE__ */ new Set();
1183
- function warnDeprecatedShutdownTimeoutKeys(options) {
1184
- if (!options || typeof options !== "object") return;
1185
- const opts = options;
1186
- for (const key of ["onDestroyTimeout", "waitUntilTimeout"]) {
1187
- if (opts[key] !== void 0 && !warnedDeprecatedTimeoutKeys.has(key)) {
1188
- warnedDeprecatedTimeoutKeys.add(key);
1189
- loggerWithoutContext().warn({
1190
- 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 });
1191
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 });
1192
1656
  }
1193
- }
1194
- }
1195
- var ActorDefinition = class {
1196
- #config;
1197
- constructor(config) {
1198
- this.#config = config;
1199
- }
1200
- get config() {
1201
- return this.#config;
1202
- }
1203
- };
1204
- function actor(input) {
1205
- warnDeprecatedShutdownTimeoutKeys(
1206
- input == null ? void 0 : input.options
1207
- );
1208
- const config = ActorConfigSchema.parse(input);
1209
- return new ActorDefinition(config);
1210
- }
1211
-
1212
- // src/actor/schema.ts
1213
- function event(options) {
1214
- return options ?? {};
1657
+ };
1215
1658
  }
1216
1659
 
1217
- // src/common/database/shared.ts
1218
- function isSqliteBindingValue(value) {
1219
- if (value === null || typeof value === "number" || typeof value === "string" || typeof value === "bigint" || value instanceof Uint8Array) {
1220
- return true;
1221
- }
1222
- if (Array.isArray(value)) {
1223
- return value.every((item) => typeof item === "number");
1224
- }
1225
- return false;
1226
- }
1227
- function isPlainObject(value) {
1228
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1229
- 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;
1230
1664
  }
1231
- return Object.getPrototypeOf(value) === Object.prototype;
1665
+ const start = Date.now();
1666
+ const options = buildVmOptions(config.options);
1667
+ const agentOs2 = await 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;
1232
1678
  }
1233
- function isSqliteBindingObject(value) {
1234
- if (!isPlainObject(value)) {
1235
- return false;
1679
+ function buildVmOptions(userOptions) {
1680
+ const userMounts = (userOptions == null ? void 0 : userOptions.mounts) ?? [];
1681
+ const hasWorkdirMount = userMounts.some(
1682
+ (m) => m.path === "/home/user"
1683
+ );
1684
+ if (hasWorkdirMount) {
1685
+ return userOptions ?? {};
1236
1686
  }
1237
- return Object.values(value).every((entry) => isSqliteBindingValue(entry));
1687
+ const memMount = {
1688
+ path: "/home/user",
1689
+ driver: createInMemoryFileSystem()
1690
+ };
1691
+ return {
1692
+ ...userOptions,
1693
+ mounts: [memMount, ...userMounts]
1694
+ };
1238
1695
  }
1239
- function toSqliteBindings(input) {
1240
- if (Array.isArray(input)) {
1241
- for (const value of input) {
1242
- if (!isSqliteBindingValue(value)) {
1243
- throw new Error(
1244
- `unsupported sqlite binding type: ${typeof value}`
1245
- );
1246
- }
1247
- }
1248
- return input;
1249
- }
1250
- if (isSqliteBindingObject(input)) {
1251
- return input;
1252
- }
1253
- 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
+ });
1254
1707
  }
1255
-
1256
- // src/common/database/mod.ts
1257
- function hasMultipleStatements(query) {
1258
- const trimmed = query.trim().replace(/;+$/, "").trimEnd();
1259
- 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);
1260
1718
  }
1261
- function db({
1262
- onMigrate
1263
- } = {}) {
1264
- return {
1265
- createClient: async (ctx) => {
1266
- const nativeDatabaseProvider = ctx.nativeDatabaseProvider;
1267
- if (!nativeDatabaseProvider) {
1268
- throw new Error(
1269
- "native SQLite is required, but the current runtime did not provide a native database provider"
1270
- );
1271
- }
1272
- const db2 = await nativeDatabaseProvider.open(ctx.actorId);
1273
- let closed = false;
1274
- const ensureOpen = () => {
1275
- if (closed) {
1276
- throw new Error(
1277
- "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."
1278
- );
1279
- }
1280
- };
1281
- const client = {
1282
- execute: async (query, ...args) => {
1283
- var _a, _b, _c, _d;
1284
- ensureOpen();
1285
- const kvReadsBefore = ((_a = ctx.metrics) == null ? void 0 : _a.totalKvReads) ?? 0;
1286
- const kvWritesBefore = ((_b = ctx.metrics) == null ? void 0 : _b.totalKvWrites) ?? 0;
1287
- const start = performance.now();
1288
- try {
1289
- if (args.length > 0) {
1290
- const bindings = args.length === 1 && isSqliteBindingObject(args[0]) ? toSqliteBindings(args[0]) : toSqliteBindings(args);
1291
- const { rows, columns } = await db2.execute(
1292
- query,
1293
- bindings
1294
- );
1295
- return rows.map(
1296
- (row) => rowToObject(row, columns)
1297
- );
1298
- }
1299
- if (!hasMultipleStatements(query)) {
1300
- const { rows, columns } = await db2.execute(query);
1301
- return rows.map(
1302
- (row) => rowToObject(row, columns)
1303
- );
1304
- }
1305
- return await execMultiStatement(db2, query);
1306
- } finally {
1307
- const durationMs = performance.now() - start;
1308
- (_c = ctx.metrics) == null ? void 0 : _c.trackSql(query, durationMs);
1309
- if (ctx.metrics) {
1310
- const kvReads = ctx.metrics.totalKvReads - kvReadsBefore;
1311
- const kvWrites = ctx.metrics.totalKvWrites - kvWritesBefore;
1312
- (_d = ctx.log) == null ? void 0 : _d.debug({
1313
- msg: "sql query",
1314
- query: query.slice(0, 120),
1315
- durationMs,
1316
- kvReads,
1317
- kvWrites
1318
- });
1319
- }
1320
- }
1321
- },
1322
- close: async () => {
1323
- if (!closed) {
1324
- closed = true;
1325
- await db2.close();
1326
- }
1327
- },
1328
- nativeMetrics: () => {
1329
- var _a;
1330
- return ((_a = db2.nativeMetrics) == null ? void 0 : _a.call(db2)) ?? null;
1331
- }
1332
- };
1333
- return client;
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
1334
1739
  },
1335
- onMigrate: async (client) => {
1336
- if (onMigrate) {
1337
- await withMigrationSavepoint(client, () => onMigrate(client));
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;
1768
+ }
1338
1769
  }
1339
- }
1340
- };
1341
- }
1342
- function rowToObject(row, columns) {
1343
- const rowObj = {};
1344
- for (let i = 0; i < columns.length; i++) {
1345
- rowObj[columns[i]] = row[i];
1346
- }
1347
- return rowObj;
1348
- }
1349
- async function execMultiStatement(db2, query) {
1350
- const results = [];
1351
- let columnNames = null;
1352
- await db2.exec(query, (row, columns) => {
1353
- if (!columnNames) {
1354
- columnNames = columns;
1355
- }
1356
- results.push(rowToObject(row, columnNames));
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" });
1785
+ },
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;
1796
+ }
1797
+ c.broadcast("vmShutdown", { reason: "destroy" });
1798
+ },
1799
+ actions
1357
1800
  });
1358
- return results;
1359
- }
1360
- async function withMigrationSavepoint(client, callback) {
1361
- await client.execute("SAVEPOINT __rivet_on_migrate");
1362
- try {
1363
- const result = await callback();
1364
- await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
1365
- return result;
1366
- } catch (error) {
1367
- try {
1368
- await client.execute("ROLLBACK TO SAVEPOINT __rivet_on_migrate");
1369
- } finally {
1370
- await client.execute("RELEASE SAVEPOINT __rivet_on_migrate");
1371
- }
1372
- throw error;
1373
- }
1374
1801
  }
1375
-
1376
- // src/agent-os/config.ts
1377
- import { z as z3 } from "zod/v4";
1378
- var zFunction2 = () => z3.custom((val) => typeof val === "function");
1379
- var AgentOsOptionsSchema = z3.custom(
1380
- (val) => typeof val === "object" && val !== null
1381
- );
1382
- var agentOsActorConfigSchema = z3.object({
1383
- options: AgentOsOptionsSchema.optional(),
1384
- preview: z3.object({
1385
- defaultExpiresInSeconds: z3.number().positive().default(3600),
1386
- maxExpiresInSeconds: z3.number().positive().default(86400)
1387
- }).strict().prefault(() => ({})),
1388
- onBeforeConnect: zFunction2().optional(),
1389
- onSessionEvent: zFunction2().optional(),
1390
- onPermissionRequest: zFunction2().optional()
1391
- }).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();
1392
1810
 
1393
1811
  // src/agent-os/actor/cron.ts
1394
1812
  function serializeCronAction(action) {
@@ -1412,859 +1830,517 @@ function serializeCronAction(action) {
1412
1830
  }
1413
1831
  }
1414
1832
  function serializeCronJob(job) {
1415
- var _a, _b;
1416
- return {
1417
- id: job.id,
1418
- schedule: job.schedule,
1419
- action: serializeCronAction(job.action),
1420
- overlap: job.overlap,
1421
- lastRun: (_a = job.lastRun) == null ? void 0 : _a.toISOString(),
1422
- nextRun: (_b = job.nextRun) == null ? void 0 : _b.toISOString(),
1423
- runCount: job.runCount,
1424
- running: job.running
1425
- };
1426
- }
1427
- function buildCronActions(config) {
1428
- return {
1429
- scheduleCron: async (c, options) => {
1430
- const agentOs2 = await ensureVm(c, config);
1431
- const job = agentOs2.scheduleCron({
1432
- id: options.id,
1433
- schedule: options.schedule,
1434
- action: options.action,
1435
- overlap: options.overlap
1436
- });
1437
- c.log.info({
1438
- msg: "agent-os cron job scheduled",
1439
- jobId: job.id,
1440
- schedule: options.schedule
1441
- });
1442
- return { id: job.id };
1443
- },
1444
- listCronJobs: async (c) => {
1445
- const agentOs2 = await ensureVm(c, config);
1446
- return agentOs2.listCronJobs().map(serializeCronJob);
1447
- },
1448
- cancelCronJob: async (c, id) => {
1449
- const agentOs2 = await ensureVm(c, config);
1450
- agentOs2.cancelCronJob(id);
1451
- c.log.info({ msg: "agent-os cron job cancelled", jobId: id });
1452
- }
1453
- };
1454
- }
1455
-
1456
- // src/agent-os/actor/network.ts
1457
- function buildNetworkActions(config) {
1458
- return {
1459
- vmFetch: async (c, port, url, options) => {
1460
- const agentOs2 = await ensureVm(c, config);
1461
- const headers = new Headers(options == null ? void 0 : options.headers);
1462
- const request = new Request(url, {
1463
- method: (options == null ? void 0 : options.method) ?? "GET",
1464
- headers,
1465
- body: (options == null ? void 0 : options.body) ?? null
1466
- });
1467
- const response = await agentOs2.fetch(port, request);
1468
- const responseHeaders = {};
1469
- response.headers.forEach((value, key) => {
1470
- responseHeaders[key] = value;
1471
- });
1472
- const body = new Uint8Array(await response.arrayBuffer());
1473
- return {
1474
- status: response.status,
1475
- statusText: response.statusText,
1476
- headers: responseHeaders,
1477
- body
1478
- };
1479
- }
1480
- };
1481
- }
1482
-
1483
- // src/agent-os/actor/preview.ts
1484
- import crypto from "crypto";
1485
- function generateToken() {
1486
- const bytes = crypto.randomBytes(32);
1487
- const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
1488
- let token = "";
1489
- for (let i = 0; i < 32; i++) {
1490
- token += alphabet[bytes[i] % alphabet.length];
1491
- }
1492
- return token;
1493
- }
1494
- var CORS_HEADERS = {
1495
- "Access-Control-Allow-Origin": "*",
1496
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
1497
- "Access-Control-Allow-Headers": "*"
1498
- };
1499
- function addCorsHeaders(response) {
1500
- const headers = new Headers(response.headers);
1501
- for (const [key, value] of Object.entries(CORS_HEADERS)) {
1502
- headers.set(key, value);
1503
- }
1504
- return new Response(response.body, {
1505
- status: response.status,
1506
- statusText: response.statusText,
1507
- headers
1508
- });
1509
- }
1510
- function buildOnRequestHandler(config) {
1511
- return async (c, request) => {
1512
- var _a;
1513
- const url = new URL(request.url);
1514
- const pathname = url.pathname;
1515
- const match = pathname.match(/^\/fetch\/([a-z0-9]+)(\/.*)?$/);
1516
- if (!match) {
1517
- return new Response("Not Found", { status: 404 });
1518
- }
1519
- if (request.method === "OPTIONS") {
1520
- return new Response(null, { status: 204, headers: CORS_HEADERS });
1521
- }
1522
- const token = match[1];
1523
- const remainingPath = match[2] ?? "/";
1524
- const now = Date.now();
1525
- const rows = await c.db.execute(
1526
- `SELECT port FROM agent_os_preview_tokens WHERE token = ? AND expires_at > ?`,
1527
- token,
1528
- now
1529
- );
1530
- if (rows.length === 0) {
1531
- c.log.warn({ msg: "agent-os preview auth failed", token });
1532
- return addCorsHeaders(new Response("Forbidden", { status: 403 }));
1533
- }
1534
- const port = (_a = rows[0]) == null ? void 0 : _a.port;
1535
- const agentOs2 = await ensureVm(
1536
- c,
1537
- config
1538
- );
1539
- const vmUrl = `http://localhost:${port}${remainingPath}${url.search}`;
1540
- const vmRequest = new Request(vmUrl, {
1541
- method: request.method,
1542
- headers: request.headers,
1543
- body: request.body,
1544
- duplex: "half"
1545
- });
1546
- const vmResponse = await agentOs2.fetch(port, vmRequest);
1547
- c.log.info({
1548
- msg: "agent-os preview request proxied",
1549
- port,
1550
- method: request.method,
1551
- path: remainingPath,
1552
- status: vmResponse.status
1553
- });
1554
- return addCorsHeaders(vmResponse);
1555
- };
1556
- }
1557
- function buildPreviewActions(config) {
1558
- return {
1559
- createSignedPreviewUrl: async (c, port, expiresInSeconds) => {
1560
- await ensureVm(c, config);
1561
- const effectiveExpires = expiresInSeconds ?? config.preview.defaultExpiresInSeconds;
1562
- const maxExpires = config.preview.maxExpiresInSeconds;
1563
- if (effectiveExpires < 1 || effectiveExpires > maxExpires) {
1564
- throw new Error(
1565
- `expiresInSeconds must be between 1 and ${maxExpires}`
1566
- );
1567
- }
1568
- const token = generateToken();
1569
- const now = Date.now();
1570
- const expiresAt = now + effectiveExpires * 1e3;
1571
- await c.db.execute(
1572
- `INSERT INTO agent_os_preview_tokens (token, port, created_at, expires_at)
1573
- VALUES (?, ?, ?, ?)`,
1574
- token,
1575
- port,
1576
- now,
1577
- expiresAt
1578
- );
1579
- await c.db.execute(
1580
- `DELETE FROM agent_os_preview_tokens WHERE expires_at <= ?`,
1581
- now
1582
- );
1583
- const path = `/request/fetch/${token}`;
1584
- c.log.info({
1585
- msg: "agent-os preview token created",
1586
- port,
1587
- expiresInSeconds: effectiveExpires
1588
- });
1589
- return { path, token, port, expiresAt };
1590
- },
1591
- expireSignedPreviewUrl: async (c, token) => {
1592
- await c.db.execute(
1593
- `DELETE FROM agent_os_preview_tokens WHERE token = ?`,
1594
- token
1595
- );
1596
- c.log.info({ msg: "agent-os preview token expired", token });
1597
- }
1598
- };
1599
- }
1600
-
1601
- // src/agent-os/actor/process.ts
1602
- function broadcastProcessEvent(c, name, payload) {
1603
- try {
1604
- c.broadcast(name, payload);
1605
- } catch (error) {
1606
- if (isRivetErrorCode(error, "actor", "stopping")) {
1607
- return;
1608
- }
1609
- throw error;
1610
- }
1833
+ var _a, _b;
1834
+ return {
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
+ };
1611
1844
  }
1612
- function buildProcessActions(config) {
1845
+ function buildCronActions(config) {
1613
1846
  return {
1614
- exec: async (c, command, options) => {
1615
- const agentOs2 = await ensureVm(c, config);
1616
- return agentOs2.exec(command, options);
1617
- },
1618
- spawn: async (c, command, args, options) => {
1847
+ scheduleCron: async (c, options) => {
1619
1848
  const agentOs2 = await ensureVm(c, config);
1620
- const { pid } = agentOs2.spawn(command, args, {
1621
- ...options,
1622
- onStdout: (data) => {
1623
- var _a;
1624
- broadcastProcessEvent(c, "processOutput", {
1625
- pid,
1626
- stream: "stdout",
1627
- data
1628
- });
1629
- (_a = options == null ? void 0 : options.onStdout) == null ? void 0 : _a.call(options, data);
1630
- },
1631
- onStderr: (data) => {
1632
- var _a;
1633
- broadcastProcessEvent(c, "processOutput", {
1634
- pid,
1635
- stream: "stderr",
1636
- data
1637
- });
1638
- (_a = options == null ? void 0 : options.onStderr) == null ? void 0 : _a.call(options, data);
1639
- }
1849
+ const job = agentOs2.scheduleCron({
1850
+ id: options.id,
1851
+ schedule: options.schedule,
1852
+ action: options.action,
1853
+ overlap: options.overlap
1640
1854
  });
1641
- c.vars.activeProcesses.add(pid);
1642
- syncPreventSleep(c);
1643
1855
  c.log.info({
1644
- msg: "agent-os process spawned",
1645
- pid,
1646
- command
1647
- });
1648
- agentOs2.waitProcess(pid).then((exitCode) => {
1649
- broadcastProcessEvent(c, "processExit", { pid, exitCode });
1650
- c.log.info({
1651
- msg: "agent-os process exited",
1652
- pid,
1653
- exitCode
1654
- });
1655
- }).catch(() => {
1656
- }).finally(() => {
1657
- c.vars.activeProcesses.delete(pid);
1658
- syncPreventSleep(c);
1856
+ msg: "agent-os cron job scheduled",
1857
+ jobId: job.id,
1858
+ schedule: options.schedule
1659
1859
  });
1660
- return { pid };
1661
- },
1662
- writeProcessStdin: async (c, pid, data) => {
1663
- const agentOs2 = await ensureVm(c, config);
1664
- agentOs2.writeProcessStdin(pid, data);
1665
- },
1666
- closeProcessStdin: async (c, pid) => {
1667
- const agentOs2 = await ensureVm(c, config);
1668
- agentOs2.closeProcessStdin(pid);
1669
- },
1670
- waitProcess: async (c, pid) => {
1671
- const agentOs2 = await ensureVm(c, config);
1672
- return agentOs2.waitProcess(pid);
1673
- },
1674
- listProcesses: async (c) => {
1675
- const agentOs2 = await ensureVm(c, config);
1676
- return agentOs2.listProcesses();
1677
- },
1678
- allProcesses: async (c) => {
1679
- const agentOs2 = await ensureVm(c, config);
1680
- return agentOs2.allProcesses();
1681
- },
1682
- processTree: async (c) => {
1683
- const agentOs2 = await ensureVm(c, config);
1684
- return agentOs2.processTree();
1685
- },
1686
- getProcess: async (c, pid) => {
1687
- const agentOs2 = await ensureVm(c, config);
1688
- return agentOs2.getProcess(pid);
1860
+ return { id: job.id };
1689
1861
  },
1690
- stopProcess: async (c, pid) => {
1862
+ listCronJobs: async (c) => {
1691
1863
  const agentOs2 = await ensureVm(c, config);
1692
- agentOs2.stopProcess(pid);
1864
+ return agentOs2.listCronJobs().map(serializeCronJob);
1693
1865
  },
1694
- killProcess: async (c, pid) => {
1866
+ cancelCronJob: async (c, id) => {
1695
1867
  const agentOs2 = await ensureVm(c, config);
1696
- agentOs2.killProcess(pid);
1868
+ agentOs2.cancelCronJob(id);
1869
+ c.log.info({ msg: "agent-os cron job cancelled", jobId: id });
1697
1870
  }
1698
1871
  };
1699
1872
  }
1700
1873
 
1701
- // src/agent-os/actor/session.ts
1702
- function stripFunctions(value) {
1703
- if (value === null || value === void 0) return value;
1704
- if (typeof value === "function") return void 0;
1705
- if (typeof value !== "object") return value;
1706
- if (Array.isArray(value)) return value.map(stripFunctions);
1707
- const out = {};
1708
- for (const [k, v] of Object.entries(value)) {
1709
- if (typeof v !== "function") {
1710
- out[k] = stripFunctions(v);
1711
- }
1874
+ // src/agent-os/fs/database-vfs.ts
1875
+ import * as posixPath from "path/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);
1712
1885
  }
1713
- return out;
1886
+ return normalized;
1714
1887
  }
1715
- function assertSessionExists(c, sessionId) {
1716
- if (!c.vars.sessions.has(sessionId)) {
1717
- throw new Error(`session not found: ${sessionId}`);
1718
- }
1888
+ function parentPath(p) {
1889
+ const parent = posixPath.dirname(p);
1890
+ return parent;
1719
1891
  }
1720
- function toSessionRecord(agentOs2, sessionId, agentType) {
1721
- return {
1722
- sessionId,
1723
- agentType,
1724
- capabilities: agentOs2.getSessionCapabilities(sessionId) ?? {},
1725
- agentInfo: agentOs2.getSessionAgentInfo(sessionId)
1726
- };
1892
+ function throwENOENT(path) {
1893
+ const err = new Error(`ENOENT: no such file or directory: ${path}`);
1894
+ err.name = "ENOENT";
1895
+ throw err;
1727
1896
  }
1728
- async function persistSession(c, agentOs2, sessionId, agentType) {
1729
- const now = Date.now();
1730
- const capabilities = agentOs2.getSessionCapabilities(sessionId) ?? {};
1731
- const agentInfo = agentOs2.getSessionAgentInfo(sessionId);
1732
- await c.db.execute(
1733
- `INSERT OR REPLACE INTO agent_os_sessions (session_id, agent_type, capabilities, agent_info, created_at)
1734
- VALUES (?, ?, ?, ?, ?)`,
1735
- sessionId,
1736
- agentType,
1737
- JSON.stringify(capabilities),
1738
- agentInfo ? JSON.stringify(agentInfo) : null,
1739
- now
1740
- );
1897
+ function throwEEXIST(path) {
1898
+ const err = new Error(`EEXIST: file already exists: ${path}`);
1899
+ err.name = "EEXIST";
1900
+ throw err;
1741
1901
  }
1742
- async function persistSessionEvent(c, sessionId, event2) {
1743
- var _a;
1744
- const now = Date.now();
1745
- const rows = await c.db.execute(
1746
- `SELECT MAX(seq) as max_seq FROM agent_os_session_events WHERE session_id = ?`,
1747
- sessionId
1748
- );
1749
- const nextSeq = (((_a = rows[0]) == null ? void 0 : _a.max_seq) ?? -1) + 1;
1750
- await c.db.execute(
1751
- `INSERT INTO agent_os_session_events (session_id, seq, event, created_at)
1752
- VALUES (?, ?, ?, ?)`,
1753
- sessionId,
1754
- nextSeq,
1755
- JSON.stringify(event2),
1756
- now
1757
- );
1902
+ function throwENOTDIR(path) {
1903
+ const err = new Error(`ENOTDIR: not a directory: ${path}`);
1904
+ err.name = "ENOTDIR";
1905
+ throw err;
1758
1906
  }
1759
- async function deletePersistedSession(c, sessionId) {
1760
- await c.db.execute(
1761
- `DELETE FROM agent_os_session_events WHERE session_id = ?`,
1762
- sessionId
1763
- );
1764
- await c.db.execute(
1765
- `DELETE FROM agent_os_sessions WHERE session_id = ?`,
1766
- sessionId
1767
- );
1907
+ function throwEISDIR(path) {
1908
+ const err = new Error(`EISDIR: illegal operation on a directory: ${path}`);
1909
+ err.name = "EISDIR";
1910
+ throw err;
1768
1911
  }
1769
- function subscribeToSession(c, agentOs2, sessionId, parsedConfig) {
1770
- agentOs2.onSessionEvent(sessionId, (event2) => {
1771
- c.broadcast(
1772
- "sessionEvent",
1773
- JSON.parse(JSON.stringify({ sessionId, event: event2 }))
1774
- );
1775
- persistSessionEvent(c, sessionId, event2).catch(
1776
- (err) => c.log.error({
1777
- msg: "agent-os failed to persist session event",
1778
- sessionId,
1779
- error: err
1780
- })
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
1781
1944
  );
1782
- if (parsedConfig.onSessionEvent) {
1783
- runHook(
1784
- c,
1785
- "onSessionEvent",
1786
- () => {
1787
- var _a;
1788
- return (_a = parsedConfig.onSessionEvent) == null ? void 0 : _a.call(parsedConfig, c, sessionId, event2);
1789
- }
1790
- );
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);
1791
1960
  }
1792
- });
1793
- agentOs2.onPermissionRequest(sessionId, (request) => {
1794
- c.broadcast(
1795
- "permissionRequest",
1796
- 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
1797
1971
  );
1798
- if (parsedConfig.onPermissionRequest) {
1799
- runHook(
1800
- c,
1801
- "onPermissionRequest",
1802
- () => {
1803
- var _a;
1804
- return (_a = parsedConfig.onPermissionRequest) == null ? void 0 : _a.call(parsedConfig, c, sessionId, request);
1805
- }
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
1806
1989
  );
1807
1990
  }
1808
- });
1809
- c.vars.sessions.add(sessionId);
1810
- }
1811
- function buildSessionActions(config) {
1812
- return {
1813
- createSession: async (c, agentType, options) => {
1814
- const agentOs2 = await ensureVm(c, config);
1815
- const { sessionId } = await agentOs2.createSession(
1816
- agentType,
1817
- options
1818
- );
1819
- subscribeToSession(c, agentOs2, sessionId, config);
1820
- await persistSession(c, agentOs2, sessionId, agentType);
1821
- c.log.info({
1822
- msg: "agent-os session created",
1823
- sessionId,
1824
- agentType
1825
- });
1826
- return toSessionRecord(agentOs2, sessionId, agentType);
1827
- },
1828
- listSessions: async (c) => {
1829
- const agentOs2 = await ensureVm(c, config);
1830
- return agentOs2.listSessions();
1831
- },
1832
- getSession: async (c, sessionId) => {
1833
- assertSessionExists(c, sessionId);
1834
- const agentOs2 = await ensureVm(c, config);
1835
- const info = agentOs2.listSessions().find((s) => s.sessionId === sessionId);
1836
- if (!info) {
1837
- 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);
1838
1999
  }
1839
- return toSessionRecord(agentOs2, sessionId, info.agentType);
1840
- },
1841
- destroySession: async (c, sessionId) => {
1842
- const agentOs2 = await ensureVm(c, config);
1843
- await agentOs2.destroySession(sessionId);
1844
- c.vars.sessions.delete(sessionId);
1845
- c.vars.activeSessionIds.delete(sessionId);
1846
- syncPreventSleep(c);
1847
- await deletePersistedSession(c, sessionId);
1848
- c.log.info({ msg: "agent-os session destroyed", sessionId });
1849
- },
1850
- resumeSession: async (c, sessionId) => {
1851
- const agentOs2 = await ensureVm(c, config);
1852
- return agentOs2.resumeSession(sessionId);
2000
+ return entry.content ?? new Uint8Array(0);
1853
2001
  },
1854
- closeSession: async (c, sessionId) => {
1855
- const agentOs2 = await ensureVm(c, config);
1856
- agentOs2.closeSession(sessionId);
1857
- c.vars.sessions.delete(sessionId);
1858
- c.vars.activeSessionIds.delete(sessionId);
1859
- syncPreventSleep(c);
1860
- await deletePersistedSession(c, sessionId);
1861
- c.log.info({ msg: "agent-os session closed", sessionId });
1862
- }
1863
- };
1864
- }
1865
- function buildPromptActions(_config) {
1866
- return {
1867
- sendPrompt: async (c, sessionId, text) => {
1868
- if (c.aborted) {
1869
- throw new Error(
1870
- "actor is shutting down, cannot start new prompt"
1871
- );
1872
- }
1873
- assertSessionExists(c, sessionId);
1874
- const agentOs2 = c.vars.agentOs;
1875
- if (!agentOs2) {
1876
- throw new Error("VM not initialized");
1877
- }
1878
- c.vars.activeSessionIds.add(sessionId);
1879
- syncPreventSleep(c);
1880
- c.log.info({ msg: "agent-os prompt turn started", sessionId });
1881
- const start = Date.now();
1882
- try {
1883
- const result = await agentOs2.prompt(sessionId, text);
1884
- return {
1885
- response: JSON.parse(JSON.stringify(result.response)),
1886
- text: result.text
1887
- };
1888
- } finally {
1889
- c.vars.activeSessionIds.delete(sessionId);
1890
- syncPreventSleep(c);
1891
- c.log.info({
1892
- msg: "agent-os prompt turn ended",
1893
- sessionId,
1894
- durationMs: Date.now() - start
1895
- });
1896
- }
2002
+ async readTextFile(p) {
2003
+ const data = await backend.readFile(p);
2004
+ return new TextDecoder().decode(data);
1897
2005
  },
1898
- cancelPrompt: async (c, sessionId) => {
1899
- assertSessionExists(c, sessionId);
1900
- const agentOs2 = c.vars.agentOs;
1901
- if (!agentOs2) {
1902
- 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);
1903
2012
  }
1904
- return stripFunctions(
1905
- agentOs2.cancelSession(sessionId)
1906
- );
2013
+ const children = await getChildEntries(path);
2014
+ return children.map((child) => posixPath.basename(child.path));
1907
2015
  },
1908
- respondPermission: async (c, sessionId, permissionId, reply) => {
1909
- assertSessionExists(c, sessionId);
1910
- const agentOs2 = c.vars.agentOs;
1911
- if (!agentOs2) {
1912
- throw new Error("VM not initialized");
1913
- }
1914
- return stripFunctions(
1915
- agentOs2.respondPermission(sessionId, permissionId, reply)
1916
- );
1917
- }
1918
- };
1919
- }
1920
- function buildConfigActions(_config) {
1921
- return {
1922
- setMode: async (c, sessionId, modeId) => {
1923
- assertSessionExists(c, sessionId);
1924
- const agentOs2 = c.vars.agentOs;
1925
- if (!agentOs2) {
1926
- 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);
1927
2022
  }
1928
- return stripFunctions(
1929
- agentOs2.setSessionMode(sessionId, modeId)
1930
- );
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
+ }));
1931
2030
  },
1932
- getModes: async (c, sessionId) => {
1933
- assertSessionExists(c, sessionId);
1934
- const agentOs2 = c.vars.agentOs;
1935
- if (!agentOs2) {
1936
- 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);
1937
2038
  }
1938
- return agentOs2.getSessionModes(sessionId);
1939
- },
1940
- setModel: async (c, sessionId, model) => {
1941
- assertSessionExists(c, sessionId);
1942
- const agentOs2 = c.vars.agentOs;
1943
- if (!agentOs2) {
1944
- 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
+ );
1945
2063
  }
1946
- return stripFunctions(
1947
- agentOs2.setSessionModel(sessionId, model)
1948
- );
1949
2064
  },
1950
- setThoughtLevel: async (c, sessionId, level) => {
1951
- assertSessionExists(c, sessionId);
1952
- const agentOs2 = c.vars.agentOs;
1953
- if (!agentOs2) {
1954
- 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);
1955
2072
  }
1956
- return stripFunctions(
1957
- 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
1958
2082
  );
1959
2083
  },
1960
- getConfigOptions: async (c, sessionId) => {
1961
- assertSessionExists(c, sessionId);
1962
- const agentOs2 = c.vars.agentOs;
1963
- if (!agentOs2) {
1964
- 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);
1965
2110
  }
1966
- return agentOs2.getSessionConfigOptions(sessionId);
1967
2111
  },
1968
- getEvents: async (c, sessionId, options) => {
1969
- assertSessionExists(c, sessionId);
1970
- const agentOs2 = c.vars.agentOs;
1971
- if (!agentOs2) {
1972
- throw new Error("VM not initialized");
1973
- }
1974
- 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;
1975
2117
  },
1976
- getSequencedEvents: async (c, sessionId, options) => {
1977
- assertSessionExists(c, sessionId);
1978
- const agentOs2 = c.vars.agentOs;
1979
- if (!agentOs2) {
1980
- throw new Error("VM not initialized");
1981
- }
1982
- 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);
1983
2123
  },
1984
- rawSend: async (c, sessionId, method, params) => {
1985
- assertSessionExists(c, sessionId);
1986
- const agentOs2 = c.vars.agentOs;
1987
- if (!agentOs2) {
1988
- 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);
1989
2130
  }
1990
- return stripFunctions(
1991
- agentOs2.rawSessionSend(sessionId, method, params)
1992
- );
1993
- }
1994
- };
1995
- }
1996
- function buildSessionPersistenceActions(_config) {
1997
- return {
1998
- listPersistedSessions: async (c) => {
1999
- const rows = await c.db.execute(
2000
- `SELECT session_id, agent_type, capabilities, agent_info, created_at
2001
- FROM agent_os_sessions
2002
- ORDER BY created_at ASC`
2131
+ await db2.execute(
2132
+ "DELETE FROM agent_os_fs_entries WHERE path = ?",
2133
+ path
2003
2134
  );
2004
- return rows.map((row) => ({
2005
- sessionId: row.session_id,
2006
- agentType: row.agent_type,
2007
- capabilities: JSON.parse(row.capabilities),
2008
- agentInfo: row.agent_info ? JSON.parse(row.agent_info) : null,
2009
- createdAt: row.created_at
2010
- }));
2011
2135
  },
2012
- getSessionEvents: async (c, sessionId) => {
2013
- const rows = await c.db.execute(
2014
- `SELECT session_id, seq, event, created_at
2015
- FROM agent_os_session_events
2016
- WHERE session_id = ?
2017
- ORDER BY seq ASC`,
2018
- 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
2019
2150
  );
2020
- return rows.map((row) => ({
2021
- sessionId: row.session_id,
2022
- seq: row.seq,
2023
- event: JSON.parse(row.event),
2024
- createdAt: row.created_at
2025
- }));
2026
- }
2027
- };
2028
- }
2029
-
2030
- // src/agent-os/actor/shell.ts
2031
- function buildShellActions(config) {
2032
- return {
2033
- openShell: async (c, options) => {
2034
- const agentOs2 = await ensureVm(c, config);
2035
- const { shellId } = agentOs2.openShell(options);
2036
- agentOs2.onShellData(shellId, (data) => {
2037
- c.broadcast("shellData", { shellId, data });
2038
- });
2039
- c.vars.activeShells.add(shellId);
2040
- syncPreventSleep(c);
2041
- c.log.info({ msg: "agent-os shell opened", shellId });
2042
- return { shellId };
2043
- },
2044
- writeShell: async (c, shellId, data) => {
2045
- const agentOs2 = await ensureVm(c, config);
2046
- agentOs2.writeShell(shellId, data);
2047
- },
2048
- resizeShell: async (c, shellId, cols, rows) => {
2049
- const agentOs2 = await ensureVm(c, config);
2050
- agentOs2.resizeShell(shellId, cols, rows);
2051
- },
2052
- closeShell: async (c, shellId) => {
2053
- const agentOs2 = await ensureVm(c, config);
2054
- agentOs2.closeShell(shellId);
2055
- c.vars.activeShells.delete(shellId);
2056
- syncPreventSleep(c);
2057
- c.log.info({ msg: "agent-os shell closed", shellId });
2058
- }
2059
- };
2060
- }
2061
-
2062
- // src/agent-os/actor/index.ts
2063
- async function ensureVm(c, config) {
2064
- if (c.vars.agentOs) {
2065
- return c.vars.agentOs;
2066
- }
2067
- const start = Date.now();
2068
- const options = buildVmOptions(config.options);
2069
- const agentOs2 = await AgentOs.create(options);
2070
- c.vars.agentOs = agentOs2;
2071
- agentOs2.onCronEvent((cronEvent) => {
2072
- c.broadcast("cronEvent", { event: cronEvent });
2073
- });
2074
- c.broadcast("vmBooted", {});
2075
- c.log.info({
2076
- msg: "agent-os vm booted",
2077
- bootDurationMs: Date.now() - start
2078
- });
2079
- return agentOs2;
2080
- }
2081
- function buildVmOptions(userOptions) {
2082
- const userMounts = (userOptions == null ? void 0 : userOptions.mounts) ?? [];
2083
- const hasWorkdirMount = userMounts.some(
2084
- (m) => m.path === "/home/user"
2085
- );
2086
- if (hasWorkdirMount) {
2087
- return userOptions ?? {};
2088
- }
2089
- const memMount = {
2090
- path: "/home/user",
2091
- driver: createInMemoryFileSystem()
2092
- };
2093
- return {
2094
- ...userOptions,
2095
- mounts: [memMount, ...userMounts]
2096
- };
2097
- }
2098
- function syncPreventSleep(c) {
2099
- const shouldPrevent = c.vars.activeSessionIds.size > 0 || c.vars.activeProcesses.size > 0 || c.vars.activeHooks.size > 0 || c.vars.activeShells.size > 0;
2100
- c.setPreventSleep(shouldPrevent);
2101
- c.log.info({
2102
- msg: "agent-os prevent sleep sync",
2103
- preventSleep: shouldPrevent,
2104
- activeSessions: c.vars.activeSessionIds.size,
2105
- activeProcesses: c.vars.activeProcesses.size,
2106
- activeHooks: c.vars.activeHooks.size,
2107
- activeShells: c.vars.activeShells.size
2108
- });
2109
- }
2110
- function runHook(c, name, callback) {
2111
- const promise = Promise.resolve(callback()).catch(
2112
- (error) => c.log.error({ msg: "agent-os hook failed", hookName: name, error })
2113
- ).finally(() => {
2114
- c.vars.activeHooks.delete(promise);
2115
- syncPreventSleep(c);
2116
- });
2117
- c.vars.activeHooks.add(promise);
2118
- syncPreventSleep(c);
2119
- c.waitUntil(promise);
2120
- }
2121
- function agentOs(config) {
2122
- const parsedConfig = agentOsActorConfigSchema.parse(
2123
- config
2124
- );
2125
- return actor({
2126
- options: {
2127
- sleepGracePeriod: 9e5,
2128
- actionTimeout: 9e5
2129
- },
2130
- createState: async () => ({}),
2131
- createVars: () => ({
2132
- agentOs: null,
2133
- activeSessionIds: /* @__PURE__ */ new Set(),
2134
- activeProcesses: /* @__PURE__ */ new Set(),
2135
- activeHooks: /* @__PURE__ */ new Set(),
2136
- activeShells: /* @__PURE__ */ new Set(),
2137
- sessions: /* @__PURE__ */ new Set()
2138
- }),
2139
- db: db({
2140
- onMigrate: migrateAgentOsTables
2141
- }),
2142
- events: {
2143
- sessionEvent: sessionEventToken,
2144
- permissionRequest: permissionRequestToken,
2145
- vmBooted: vmBootedToken,
2146
- vmShutdown: vmShutdownToken,
2147
- processOutput: processOutputToken,
2148
- processExit: processExitToken,
2149
- shellData: shellDataToken,
2150
- cronEvent: cronEventToken
2151
2151
  },
2152
- onBeforeConnect: parsedConfig.onBeforeConnect ? async (ctx, params) => {
2153
- var _a;
2154
- if (ctx.request) {
2155
- const url = new URL(ctx.request.url);
2156
- if (url.pathname.startsWith("/fetch/")) {
2157
- 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
+ }
2158
2165
  }
2166
+ await db2.execute(
2167
+ "DELETE FROM agent_os_fs_entries WHERE path = ?",
2168
+ to
2169
+ );
2159
2170
  }
2160
- await ((_a = parsedConfig.onBeforeConnect) == null ? void 0 : _a.call(parsedConfig, ctx, params));
2161
- } : void 0,
2162
- onRequest: buildOnRequestHandler(parsedConfig),
2163
- onSleep: async (c) => {
2164
- c.log.info({
2165
- msg: "agent-os vm shutdown for sleep",
2166
- activeSessions: c.vars.sessions.size,
2167
- activeProcesses: c.vars.activeProcesses.size,
2168
- activeShells: c.vars.activeShells.size
2169
- });
2170
- if (c.vars.agentOs) {
2171
- await c.vars.agentOs.dispose();
2172
- 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
+ }
2173
2186
  }
2174
- 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
+ );
2175
2194
  },
2176
- onDestroy: async (c) => {
2177
- c.log.info({
2178
- msg: "agent-os vm shutdown for destroy",
2179
- activeSessions: c.vars.sessions.size,
2180
- activeProcesses: c.vars.activeProcesses.size,
2181
- activeShells: c.vars.activeShells.size
2182
- });
2183
- if (c.vars.agentOs) {
2184
- await c.vars.agentOs.dispose();
2185
- 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);
2186
2201
  }
2187
- c.broadcast("vmShutdown", { reason: "destroy" });
2188
- },
2189
- actions: {
2190
- ...buildSessionActions(parsedConfig),
2191
- ...buildPromptActions(parsedConfig),
2192
- ...buildConfigActions(parsedConfig),
2193
- ...buildSessionPersistenceActions(parsedConfig),
2194
- ...buildProcessActions(parsedConfig),
2195
- ...buildFilesystemActions(parsedConfig),
2196
- ...buildPreviewActions(parsedConfig),
2197
- ...buildShellActions(parsedConfig),
2198
- ...buildCronActions(parsedConfig),
2199
- ...buildNetworkActions(parsedConfig)
2200
- }
2201
- });
2202
- }
2203
- var sessionEventToken = event();
2204
- var permissionRequestToken = event();
2205
- var vmBootedToken = event();
2206
- var vmShutdownToken = event();
2207
- var processOutputToken = event();
2208
- var processExitToken = event();
2209
- var shellDataToken = event();
2210
- var cronEventToken = event();
2211
-
2212
- // src/agent-os/actor/filesystem.ts
2213
- function buildFilesystemActions(config) {
2214
- return {
2215
- readFile: async (c, path) => {
2216
- const agentOs2 = await ensureVm(c, config);
2217
- return agentOs2.readFile(path);
2218
- },
2219
- writeFile: async (c, path, content) => {
2220
- const agentOs2 = await ensureVm(c, config);
2221
- await agentOs2.writeFile(path, content);
2202
+ return path;
2222
2203
  },
2223
- readFiles: async (c, paths) => {
2224
- const agentOs2 = await ensureVm(c, config);
2225
- 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
+ );
2226
2224
  },
2227
- writeFiles: async (c, entries) => {
2228
- const agentOs2 = await ensureVm(c, config);
2229
- 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;
2230
2235
  },
2231
- mkdir: async (c, path, options) => {
2232
- const agentOs2 = await ensureVm(c, config);
2233
- await agentOs2.mkdir(path, options);
2236
+ async lstat(p) {
2237
+ return backend.stat(p);
2234
2238
  },
2235
- readdir: async (c, path) => {
2236
- const agentOs2 = await ensureVm(c, config);
2237
- return agentOs2.readdir(path);
2239
+ async link(_oldPath, _newPath) {
2240
+ throwENOSYS("link");
2238
2241
  },
2239
- readdirRecursive: async (c, path, options) => {
2240
- const agentOs2 = await ensureVm(c, config);
2241
- 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
+ );
2242
2253
  },
2243
- stat: async (c, path) => {
2244
- const agentOs2 = await ensureVm(c, config);
2245
- 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
+ );
2246
2266
  },
2247
- exists: async (c, path) => {
2248
- const agentOs2 = await ensureVm(c, config);
2249
- 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
+ );
2250
2279
  },
2251
- move: async (c, from, to) => {
2252
- const agentOs2 = await ensureVm(c, config);
2253
- 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 = 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
+ );
2254
2304
  },
2255
- deleteFile: async (c, path, options) => {
2256
- const agentOs2 = await ensureVm(c, config);
2257
- 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 = 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);
2258
2318
  },
2259
- // TODO: mountFs and unmountFs are not exposed as actor actions because
2260
- // filesystem drivers (VirtualFileSystem) are not serializable over the
2261
- // network. Mount filesystems via the `options.mounts` config in agentOs()
2262
- // instead. See: https://github.com/rivet-dev/rivet/issues/XXXX
2263
- listAgents: async (c) => {
2264
- const agentOs2 = await ensureVm(c, config);
2265
- 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 = 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
+ );
2266
2341
  }
2267
2342
  };
2343
+ return backend;
2268
2344
  }
2269
2345
  export {
2270
2346
  agentOs,