@rivet-dev/agentos-browser 0.0.0-integrate-dylib-into-main.815fcda → 0.0.0-main.5bf5901

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/driver.js DELETED
@@ -1,473 +0,0 @@
1
- import { createCommandExecutorStub, createEnosysError, createFsStub, createInMemoryFileSystem, createNetworkStub, wrapFileSystem, wrapNetworkAdapter, } from "./runtime.js";
2
- const S_IFREG = 0o100000;
3
- const S_IFDIR = 0o040000;
4
- /**
5
- * Captured reference to the platform `fetch` taken at module load, before any
6
- * guest code runs and before the worker shadows the guest-visible `fetch`
7
- * global (see worker.ts dangerousApis lockdown, F-012). The gated network
8
- * adapter must keep working after the ambient `fetch` global is removed for the
9
- * guest, so the adapter calls this private reference instead of the (now
10
- * shadowed) global identifier. Bound to `globalThis` to preserve the correct
11
- * `this` for the platform fetch implementation.
12
- */
13
- const platformFetch = typeof fetch === "function" ? fetch.bind(globalThis) : undefined;
14
- const BROWSER_SYSTEM_DRIVER_OPTIONS = Symbol.for("agent-os.browserSystemDriverOptions");
15
- function normalizePath(path) {
16
- if (!path)
17
- return "/";
18
- let normalized = path.startsWith("/") ? path : `/${path}`;
19
- normalized = normalized.replace(/\/+/g, "/");
20
- if (normalized.length > 1 && normalized.endsWith("/")) {
21
- normalized = normalized.slice(0, -1);
22
- }
23
- return normalized;
24
- }
25
- function splitPath(path) {
26
- const normalized = normalizePath(path);
27
- return normalized === "/" ? [] : normalized.slice(1).split("/");
28
- }
29
- function dirname(path) {
30
- const parts = splitPath(path);
31
- if (parts.length <= 1)
32
- return "/";
33
- return `/${parts.slice(0, -1).join("/")}`;
34
- }
35
- /**
36
- * OPFS subdirectory under which every namespaced runtime root is created. The
37
- * origin-wide OPFS root (`navigator.storage.getDirectory()`) is shared by all
38
- * runtimes on the origin, so writing a runtime's files directly to it lets
39
- * co-resident runtimes read each other's data (F-015). Each runtime instead
40
- * gets its own subdirectory under this prefix.
41
- */
42
- const OPFS_RUNTIME_NAMESPACE_ROOT = ".agentos-runtimes";
43
- /**
44
- * Translate an OPFS "not found" error into a Node-style ENOENT error so missing
45
- * paths report consistently with the in-memory filesystem (and so callers see
46
- * ENOENT rather than a raw DOMException). Non-not-found errors pass through
47
- * unchanged to preserve existing behavior.
48
- */
49
- function toEnoent(error, op, path) {
50
- const name = error?.name;
51
- if (name === "NotFoundError") {
52
- const enoent = new Error(`ENOENT: no such file or directory, ${op} '${path}'`);
53
- enoent.code = "ENOENT";
54
- return enoent;
55
- }
56
- return error;
57
- }
58
- /** Generate a unique, stable-for-this-instance OPFS namespace id. */
59
- function generateOpfsNamespace() {
60
- const cryptoObj = globalThis.crypto;
61
- if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
62
- return cryptoObj.randomUUID();
63
- }
64
- return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
65
- }
66
- async function getOriginRootHandle() {
67
- if (!("storage" in navigator) || !("getDirectory" in navigator.storage)) {
68
- throw createEnosysError("opfs");
69
- }
70
- return navigator.storage.getDirectory();
71
- }
72
- /**
73
- * Resolve the per-runtime OPFS root, namespaced under
74
- * `OPFS_RUNTIME_NAMESPACE_ROOT/<namespace>` so that two runtimes on the same
75
- * origin never share storage (F-015). All of a runtime's paths resolve under
76
- * this handle, so its own reads/writes work and persist for its lifetime while
77
- * remaining invisible to other tenants.
78
- */
79
- async function getRootHandle(namespace) {
80
- const originRoot = await getOriginRootHandle();
81
- const namespaceContainer = await originRoot.getDirectoryHandle(OPFS_RUNTIME_NAMESPACE_ROOT, { create: true });
82
- return namespaceContainer.getDirectoryHandle(namespace, { create: true });
83
- }
84
- async function getNamespaceContainerHandle(create = false) {
85
- const originRoot = await getOriginRootHandle();
86
- return originRoot.getDirectoryHandle(OPFS_RUNTIME_NAMESPACE_ROOT, {
87
- create,
88
- });
89
- }
90
- function isNotFoundError(error) {
91
- return error?.name === "NotFoundError";
92
- }
93
- export async function releaseOpfsNamespace(namespace) {
94
- try {
95
- const namespaceContainer = await getNamespaceContainerHandle(false);
96
- await namespaceContainer.removeEntry(namespace, { recursive: true });
97
- }
98
- catch (error) {
99
- if (isNotFoundError(error)) {
100
- return;
101
- }
102
- throw error;
103
- }
104
- }
105
- export async function listOpfsNamespaces() {
106
- try {
107
- const namespaceContainer = await getNamespaceContainerHandle(false);
108
- const namespaces = [];
109
- for await (const [name, handle] of namespaceContainer.entries()) {
110
- if (handle.kind === "directory") {
111
- namespaces.push(name);
112
- }
113
- }
114
- return namespaces.sort();
115
- }
116
- catch (error) {
117
- if (isNotFoundError(error)) {
118
- return [];
119
- }
120
- throw error;
121
- }
122
- }
123
- /**
124
- * VFS backed by the Origin Private File System (OPFS) API. Falls back to
125
- * InMemoryFileSystem when OPFS is unavailable. Rename is not supported
126
- * (throws ENOSYS) since OPFS doesn't provide atomic rename.
127
- */
128
- export class OpfsFileSystem {
129
- rootPromise;
130
- namespace;
131
- /**
132
- * @param namespace Unique per-runtime/tenant OPFS namespace. Defaults to a
133
- * freshly generated id so co-resident runtimes never share storage (F-015).
134
- * Pass a stable id to persist a runtime's data across instances.
135
- */
136
- constructor(namespace = generateOpfsNamespace()) {
137
- this.namespace = namespace;
138
- this.rootPromise = getRootHandle(namespace);
139
- }
140
- async getDirHandle(path, create = false) {
141
- const root = await this.rootPromise;
142
- const parts = splitPath(path);
143
- let current = root;
144
- for (const part of parts) {
145
- try {
146
- current = await current.getDirectoryHandle(part, { create });
147
- }
148
- catch (error) {
149
- throw toEnoent(error, "stat", normalizePath(path));
150
- }
151
- }
152
- return current;
153
- }
154
- async getFileHandle(path, create = false) {
155
- const normalized = normalizePath(path);
156
- const parent = dirname(normalized);
157
- const name = normalized.split("/").pop() || "";
158
- const dir = await this.getDirHandle(parent, create);
159
- try {
160
- return await dir.getFileHandle(name, { create });
161
- }
162
- catch (error) {
163
- throw toEnoent(error, "open", normalized);
164
- }
165
- }
166
- async readFile(path) {
167
- const handle = await this.getFileHandle(path);
168
- const file = await handle.getFile();
169
- const buffer = await file.arrayBuffer();
170
- return new Uint8Array(buffer);
171
- }
172
- async readTextFile(path) {
173
- const handle = await this.getFileHandle(path);
174
- const file = await handle.getFile();
175
- return file.text();
176
- }
177
- async readDir(path) {
178
- const dir = await this.getDirHandle(path);
179
- const entries = [];
180
- for await (const [name] of dir.entries()) {
181
- entries.push(name);
182
- }
183
- return entries;
184
- }
185
- async readDirWithTypes(path) {
186
- const dir = await this.getDirHandle(path);
187
- const entries = [];
188
- for await (const [name, handle] of dir.entries()) {
189
- entries.push({
190
- name,
191
- isDirectory: handle.kind === "directory",
192
- });
193
- }
194
- return entries;
195
- }
196
- async writeFile(path, content) {
197
- const normalized = normalizePath(path);
198
- await this.mkdir(dirname(normalized));
199
- const handle = await this.getFileHandle(normalized, true);
200
- const writable = await handle.createWritable();
201
- if (typeof content === "string") {
202
- await writable.write(content);
203
- }
204
- else {
205
- await writable.write(content);
206
- }
207
- await writable.close();
208
- }
209
- async createDir(path) {
210
- const normalized = normalizePath(path);
211
- const parent = dirname(normalized);
212
- await this.getDirHandle(parent, false);
213
- await this.getDirHandle(normalized, true);
214
- }
215
- async mkdir(path, _options) {
216
- const parts = splitPath(path);
217
- let current = "";
218
- for (const part of parts) {
219
- current += `/${part}`;
220
- await this.getDirHandle(current, true);
221
- }
222
- }
223
- async exists(path) {
224
- try {
225
- await this.getFileHandle(path);
226
- return true;
227
- }
228
- catch {
229
- try {
230
- await this.getDirHandle(path);
231
- return true;
232
- }
233
- catch {
234
- return false;
235
- }
236
- }
237
- }
238
- async stat(path) {
239
- try {
240
- const handle = await this.getFileHandle(path);
241
- const file = await handle.getFile();
242
- return {
243
- mode: S_IFREG | 0o644,
244
- size: file.size,
245
- blocks: file.size === 0 ? 0 : Math.ceil(file.size / 512),
246
- dev: 1,
247
- rdev: 0,
248
- isDirectory: false,
249
- isSymbolicLink: false,
250
- atimeMs: file.lastModified,
251
- mtimeMs: file.lastModified,
252
- ctimeMs: file.lastModified,
253
- birthtimeMs: file.lastModified,
254
- ino: 0,
255
- nlink: 1,
256
- uid: 0,
257
- gid: 0,
258
- };
259
- }
260
- catch {
261
- const normalized = normalizePath(path);
262
- try {
263
- await this.getDirHandle(normalized);
264
- const now = Date.now();
265
- return {
266
- mode: S_IFDIR | 0o755,
267
- size: 4096,
268
- blocks: 8,
269
- dev: 1,
270
- rdev: 0,
271
- isDirectory: true,
272
- isSymbolicLink: false,
273
- atimeMs: now,
274
- mtimeMs: now,
275
- ctimeMs: now,
276
- birthtimeMs: now,
277
- ino: 0,
278
- nlink: 2,
279
- uid: 0,
280
- gid: 0,
281
- };
282
- }
283
- catch {
284
- throw new Error(`ENOENT: no such file or directory, stat '${normalized}'`);
285
- }
286
- }
287
- }
288
- async removeFile(path) {
289
- const normalized = normalizePath(path);
290
- const parent = dirname(normalized);
291
- const name = normalized.split("/").pop() || "";
292
- const dir = await this.getDirHandle(parent);
293
- await dir.removeEntry(name);
294
- }
295
- async removeDir(path) {
296
- const normalized = normalizePath(path);
297
- if (normalized === "/") {
298
- throw new Error("EPERM: operation not permitted, rmdir '/'");
299
- }
300
- const parent = dirname(normalized);
301
- const name = normalized.split("/").pop() || "";
302
- const dir = await this.getDirHandle(parent);
303
- await dir.removeEntry(name);
304
- }
305
- async rename(_oldPath, _newPath) {
306
- throw createEnosysError("rename");
307
- }
308
- async symlink(_target, _linkPath) {
309
- throw createEnosysError("symlink");
310
- }
311
- async readlink(_path) {
312
- throw createEnosysError("readlink");
313
- }
314
- async lstat(path) {
315
- return this.stat(path);
316
- }
317
- async link(_oldPath, _newPath) {
318
- throw createEnosysError("link");
319
- }
320
- async chmod(_path, _mode) {
321
- // No-op: OPFS does not support POSIX permissions
322
- }
323
- async chown(_path, _uid, _gid) {
324
- // No-op: OPFS does not support POSIX ownership
325
- }
326
- async utimes(_path, _atime, _mtime) {
327
- // No-op: OPFS does not support timestamp manipulation
328
- }
329
- async truncate(path, length) {
330
- const handle = await this.getFileHandle(path);
331
- const writable = await handle.createWritable({ keepExistingData: true });
332
- await writable.truncate(length);
333
- await writable.close();
334
- }
335
- async realpath(path) {
336
- const normalized = normalizePath(path);
337
- if (await this.exists(normalized))
338
- return normalized;
339
- throw new Error(`ENOENT: no such file or directory, realpath '${normalized}'`);
340
- }
341
- async pread(path, offset, length) {
342
- const data = await this.readFile(path);
343
- return data.slice(offset, offset + length);
344
- }
345
- async pwrite(path, offset, data) {
346
- const content = await this.readFile(path);
347
- const endPos = offset + data.length;
348
- const newContent = new Uint8Array(Math.max(content.length, endPos));
349
- newContent.set(content);
350
- newContent.set(data, offset);
351
- await this.writeFile(path, newContent);
352
- }
353
- }
354
- /**
355
- * Create an OPFS-backed filesystem, falling back to in-memory if OPFS is
356
- * unavailable. Each instance is namespaced under a unique per-runtime
357
- * subdirectory (F-015); pass `namespace` to use a stable, persistent namespace.
358
- */
359
- export async function createOpfsFileSystem(namespace) {
360
- if (!("storage" in navigator) ||
361
- typeof navigator.storage.getDirectory !== "function") {
362
- return createInMemoryFileSystem();
363
- }
364
- return new OpfsFileSystem(namespace);
365
- }
366
- /** Network adapter that delegates to the browser's native `fetch`. DNS and http2 are unsupported. */
367
- export function createBrowserNetworkAdapter() {
368
- // Use the reference captured at module load (platformFetch) so the gated
369
- // adapter keeps working after worker.ts shadows the guest-visible `fetch`
370
- // global (F-012). Fall back to the current global only if none was captured.
371
- const fetchImpl = platformFetch ?? ((...args) => fetch(...args));
372
- return {
373
- async fetch(url, options) {
374
- const response = await fetchImpl(url, {
375
- method: options?.method || "GET",
376
- headers: options?.headers,
377
- body: options?.body,
378
- // Untrusted guest requests must never ride the embedding page's
379
- // ambient cookies / HTTP-auth (F-008). Omit all credentials.
380
- credentials: "omit",
381
- });
382
- const headers = {};
383
- response.headers.forEach((v, k) => {
384
- headers[k] = v;
385
- });
386
- const contentType = response.headers.get("content-type") || "";
387
- const isBinary = contentType.includes("octet-stream") ||
388
- contentType.includes("gzip") ||
389
- url.endsWith(".tgz");
390
- let body;
391
- if (isBinary) {
392
- const buffer = await response.arrayBuffer();
393
- body = btoa(String.fromCharCode(...new Uint8Array(buffer)));
394
- headers["x-body-encoding"] = "base64";
395
- }
396
- else {
397
- body = await response.text();
398
- }
399
- return {
400
- ok: response.ok,
401
- status: response.status,
402
- statusText: response.statusText,
403
- headers,
404
- body,
405
- url: response.url,
406
- redirected: response.redirected,
407
- };
408
- },
409
- async dnsLookup(_hostname) {
410
- return { error: "DNS not supported in browser", code: "ENOSYS" };
411
- },
412
- async httpRequest(url, options) {
413
- const response = await fetchImpl(url, {
414
- method: options?.method || "GET",
415
- headers: options?.headers,
416
- body: options?.body,
417
- // Untrusted guest requests must never ride the embedding page's
418
- // ambient cookies / HTTP-auth (F-008). Omit all credentials.
419
- credentials: "omit",
420
- });
421
- const headers = {};
422
- response.headers.forEach((v, k) => {
423
- headers[k] = v;
424
- });
425
- const body = await response.text();
426
- return {
427
- status: response.status,
428
- statusText: response.statusText,
429
- headers,
430
- body,
431
- url: response.url,
432
- };
433
- },
434
- };
435
- }
436
- /** Recover runtime-driver options from a browser SystemDriver instance. */
437
- export function getBrowserSystemDriverOptions(systemDriver) {
438
- const options = systemDriver[BROWSER_SYSTEM_DRIVER_OPTIONS];
439
- if (options) {
440
- return options;
441
- }
442
- return {
443
- filesystem: "opfs",
444
- networkEnabled: Boolean(systemDriver.network),
445
- };
446
- }
447
- /** Assemble a browser-side SystemDriver with permission-wrapped adapters. */
448
- export async function createBrowserDriver(options = {}) {
449
- const permissions = options.permissions;
450
- const filesystemMode = options.filesystem ?? "opfs";
451
- const filesystem = filesystemMode === "memory"
452
- ? createInMemoryFileSystem()
453
- : await createOpfsFileSystem(options.opfsNamespace);
454
- const networkAdapter = options.useDefaultNetwork
455
- ? wrapNetworkAdapter(createBrowserNetworkAdapter(), permissions)
456
- : undefined;
457
- const systemDriver = {
458
- filesystem: wrapFileSystem(filesystem, permissions),
459
- network: networkAdapter,
460
- commandExecutor: createCommandExecutorStub(),
461
- permissions,
462
- runtime: {
463
- process: {},
464
- os: {},
465
- },
466
- };
467
- systemDriver[BROWSER_SYSTEM_DRIVER_OPTIONS] = {
468
- filesystem: filesystemMode,
469
- networkEnabled: Boolean(networkAdapter),
470
- };
471
- return systemDriver;
472
- }
473
- export { createCommandExecutorStub, createFsStub, createNetworkStub };
@@ -1,47 +0,0 @@
1
- /**
2
- * In-memory filesystem for browser environments.
3
- *
4
- * In-memory filesystem with POSIX extensions (symlinks, hard links, chmod,
5
- * chown, utimes, truncate) needed by the kernel VFS interface.
6
- */
7
- import type { VirtualDirEntry, VirtualFileSystem, VirtualStat } from "./runtime.js";
8
- export declare class InMemoryFileSystem implements VirtualFileSystem {
9
- private entries;
10
- constructor();
11
- readFile(path: string): Promise<Uint8Array>;
12
- readTextFile(path: string): Promise<string>;
13
- readDir(path: string): Promise<string[]>;
14
- readDirWithTypes(path: string): Promise<VirtualDirEntry[]>;
15
- writeFile(path: string, content: string | Uint8Array): Promise<void>;
16
- createDir(path: string): Promise<void>;
17
- mkdir(path: string, options?: {
18
- recursive?: boolean;
19
- }): Promise<void>;
20
- exists(path: string): Promise<boolean>;
21
- stat(path: string): Promise<VirtualStat>;
22
- removeFile(path: string): Promise<void>;
23
- removeDir(path: string): Promise<void>;
24
- realpath(path: string): Promise<string>;
25
- rename(oldPath: string, newPath: string): Promise<void>;
26
- symlink(target: string, linkPath: string): Promise<void>;
27
- readlink(path: string): Promise<string>;
28
- lstat(path: string): Promise<VirtualStat>;
29
- link(oldPath: string, newPath: string): Promise<void>;
30
- chmod(path: string, mode: number): Promise<void>;
31
- chown(path: string, uid: number, gid: number): Promise<void>;
32
- utimes(path: string, atime: number, mtime: number): Promise<void>;
33
- truncate(path: string, length: number): Promise<void>;
34
- pread(path: string, offset: number, length: number): Promise<Uint8Array>;
35
- pwrite(path: string, offset: number, data: Uint8Array): Promise<void>;
36
- /**
37
- * Resolve symlinks to get the final path. Returns the normalized path
38
- * after following all symlinks.
39
- */
40
- private resolvePath;
41
- /** Resolve a path and return the entry (following symlinks). */
42
- private resolveEntry;
43
- private newDir;
44
- private toStat;
45
- private enoent;
46
- }
47
- export declare function createInMemoryFileSystem(): InMemoryFileSystem;