@secure-exec/browser 0.0.0-agentos-dylib-base.edaa4a4

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 (66) hide show
  1. package/README.md +6 -0
  2. package/dist/child-process-bridge.d.ts +25 -0
  3. package/dist/child-process-bridge.js +50 -0
  4. package/dist/converged-base64.d.ts +2 -0
  5. package/dist/converged-base64.js +41 -0
  6. package/dist/converged-dgram-bridge.d.ts +11 -0
  7. package/dist/converged-dgram-bridge.js +147 -0
  8. package/dist/converged-driver-setup.d.ts +22 -0
  9. package/dist/converged-driver-setup.js +72 -0
  10. package/dist/converged-execution-host-bridge.d.ts +7 -0
  11. package/dist/converged-execution-host-bridge.js +85 -0
  12. package/dist/converged-executor-session.d.ts +60 -0
  13. package/dist/converged-executor-session.js +127 -0
  14. package/dist/converged-fs-bridge.d.ts +42 -0
  15. package/dist/converged-fs-bridge.js +245 -0
  16. package/dist/converged-module-servicer.d.ts +8 -0
  17. package/dist/converged-module-servicer.js +79 -0
  18. package/dist/converged-net-bridge.d.ts +28 -0
  19. package/dist/converged-net-bridge.js +155 -0
  20. package/dist/converged-permissions.d.ts +9 -0
  21. package/dist/converged-permissions.js +46 -0
  22. package/dist/converged-sync-bridge-handler.d.ts +47 -0
  23. package/dist/converged-sync-bridge-handler.js +140 -0
  24. package/dist/converged-sync-bridge-router.d.ts +33 -0
  25. package/dist/converged-sync-bridge-router.js +41 -0
  26. package/dist/driver.d.ts +91 -0
  27. package/dist/driver.js +386 -0
  28. package/dist/encoding.d.ts +4 -0
  29. package/dist/encoding.js +102 -0
  30. package/dist/generated/util-polyfill.d.ts +1 -0
  31. package/dist/generated/util-polyfill.js +2 -0
  32. package/dist/index.d.ts +9 -0
  33. package/dist/index.js +5 -0
  34. package/dist/kernel-backed-filesystem.d.ts +33 -0
  35. package/dist/kernel-backed-filesystem.js +205 -0
  36. package/dist/os-filesystem.d.ts +47 -0
  37. package/dist/os-filesystem.js +409 -0
  38. package/dist/permission-validation.d.ts +15 -0
  39. package/dist/permission-validation.js +62 -0
  40. package/dist/root-filesystem-from-vfs.d.ts +13 -0
  41. package/dist/root-filesystem-from-vfs.js +95 -0
  42. package/dist/runtime-driver.d.ts +66 -0
  43. package/dist/runtime-driver.js +611 -0
  44. package/dist/runtime.d.ts +248 -0
  45. package/dist/runtime.js +2296 -0
  46. package/dist/sidecar-wasm-module.d.ts +62 -0
  47. package/dist/sidecar-wasm-module.js +28 -0
  48. package/dist/sidecar-worker-protocol.d.ts +14 -0
  49. package/dist/sidecar-worker-protocol.js +9 -0
  50. package/dist/sidecar-worker.d.ts +19 -0
  51. package/dist/sidecar-worker.js +63 -0
  52. package/dist/signals.d.ts +13 -0
  53. package/dist/signals.js +89 -0
  54. package/dist/sync-bridge.d.ts +50 -0
  55. package/dist/sync-bridge.js +93 -0
  56. package/dist/wasi-polyfill.d.ts +1 -0
  57. package/dist/wasi-polyfill.js +2154 -0
  58. package/dist/worker-adapter.d.ts +21 -0
  59. package/dist/worker-adapter.js +41 -0
  60. package/dist/worker-protocol.d.ts +104 -0
  61. package/dist/worker-protocol.js +1 -0
  62. package/dist/worker-sidecar-client.d.ts +71 -0
  63. package/dist/worker-sidecar-client.js +152 -0
  64. package/dist/worker.d.ts +1 -0
  65. package/dist/worker.js +2125 -0
  66. package/package.json +111 -0
@@ -0,0 +1,2154 @@
1
+ // @generated by packages/browser/scripts/generate-wasi-polyfill.mjs
2
+ // Source: crates/execution/assets/runners/wasi-module.js (the single shared
3
+ // WASI preview1 runner). DO NOT EDIT BY HAND. Run `pnpm generate:wasi-polyfill`.
4
+ export const BROWSER_WASI_POLYFILL_CODE = `
5
+ globalThis.__agentOsWasiHost = {
6
+ requireBuiltin: (name) =>
7
+ globalThis.require(String(name).replace(/^node:/, "")),
8
+ syncReadLimitBytes: 16777216,
9
+ };
10
+ const Buffer =
11
+ (typeof globalThis !== "undefined" && globalThis.Buffer) ||
12
+ (class __AgentOsWasiBuffer extends Uint8Array {
13
+ static alloc(size) { return new __AgentOsWasiBuffer(size >>> 0); }
14
+ static allocUnsafe(size) { return new __AgentOsWasiBuffer(size >>> 0); }
15
+ static isBuffer(value) { return value instanceof Uint8Array; }
16
+ static byteLength(value, encoding) {
17
+ if (value instanceof Uint8Array) return value.length;
18
+ if (encoding === "base64") return Math.floor((String(value).replace(/=+$/, "").length * 3) / 4);
19
+ if (encoding === "hex") return String(value).length >> 1;
20
+ return new TextEncoder().encode(String(value)).length;
21
+ }
22
+ static from(value, encodingOrOffset, length) {
23
+ if (typeof value === "string") {
24
+ const encoding = encodingOrOffset || "utf8";
25
+ if (encoding === "base64") {
26
+ const binary = atob(value);
27
+ const out = new __AgentOsWasiBuffer(binary.length);
28
+ for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i) & 0xff;
29
+ return out;
30
+ }
31
+ if (encoding === "hex") {
32
+ const clean = String(value);
33
+ const out = new __AgentOsWasiBuffer(clean.length >> 1);
34
+ for (let i = 0; i < out.length; i += 1) out[i] = parseInt(clean.substr(i * 2, 2), 16);
35
+ return out;
36
+ }
37
+ const encoded = new TextEncoder().encode(value);
38
+ const out = new __AgentOsWasiBuffer(encoded.length);
39
+ out.set(encoded);
40
+ return out;
41
+ }
42
+ if (value instanceof ArrayBuffer) {
43
+ const offset = encodingOrOffset || 0;
44
+ const len = length === undefined ? value.byteLength - offset : length;
45
+ const view = new Uint8Array(value, offset, len);
46
+ const out = new __AgentOsWasiBuffer(view.length);
47
+ out.set(view);
48
+ return out;
49
+ }
50
+ if (ArrayBuffer.isView(value)) {
51
+ const view = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
52
+ const out = new __AgentOsWasiBuffer(view.length);
53
+ out.set(view);
54
+ return out;
55
+ }
56
+ const arr = Array.from(value || []);
57
+ const out = new __AgentOsWasiBuffer(arr.length);
58
+ for (let i = 0; i < arr.length; i += 1) out[i] = arr[i] & 0xff;
59
+ return out;
60
+ }
61
+ static concat(list, totalLength) {
62
+ const chunks = Array.from(list || []);
63
+ if (totalLength === undefined) {
64
+ totalLength = 0;
65
+ for (const chunk of chunks) totalLength += chunk.length;
66
+ }
67
+ const out = new __AgentOsWasiBuffer(totalLength >>> 0);
68
+ let offset = 0;
69
+ for (const chunk of chunks) {
70
+ if (offset >= out.length) break;
71
+ const slice = offset + chunk.length > out.length ? chunk.subarray(0, out.length - offset) : chunk;
72
+ out.set(slice, offset);
73
+ offset += slice.length;
74
+ }
75
+ return out;
76
+ }
77
+ toString(encoding, start, end) {
78
+ const view = this.subarray(start || 0, end === undefined ? this.length : end);
79
+ if (encoding === "base64") {
80
+ let binary = "";
81
+ for (let i = 0; i < view.length; i += 1) binary += String.fromCharCode(view[i]);
82
+ return btoa(binary);
83
+ }
84
+ if (encoding === "hex") {
85
+ let hex = "";
86
+ for (let i = 0; i < view.length; i += 1) hex += view[i].toString(16).padStart(2, "0");
87
+ return hex;
88
+ }
89
+ return new TextDecoder().decode(view);
90
+ }
91
+ });
92
+ if (typeof globalThis !== "undefined" && typeof globalThis.__agentOsWasiModule === "undefined") {
93
+ // Per-backend host seam (C / convergence): native populates it from its own
94
+ // host globals (the \`|| __agentOs*\` fallbacks below); a non-native backend
95
+ // (the browser converged worker) can pre-set \`globalThis.__agentOsWasiHost\`
96
+ // with browser-provided equivalents so this same preview1 runner is shared.
97
+ const __agentOsWasiHost =
98
+ (typeof globalThis.__agentOsWasiHost === "object" &&
99
+ globalThis.__agentOsWasiHost) ||
100
+ {};
101
+ const __agentOsWasiRequireBuiltin =
102
+ __agentOsWasiHost.requireBuiltin ||
103
+ (typeof __agentOsRequireBuiltin !== "undefined"
104
+ ? __agentOsRequireBuiltin
105
+ : (name) => globalThis.require(name));
106
+ const __agentOsFs = () => __agentOsWasiRequireBuiltin("node:fs");
107
+ const __agentOsPath = () => __agentOsWasiRequireBuiltin("node:path");
108
+ const __agentOsCrypto = () => __agentOsWasiRequireBuiltin("node:crypto");
109
+ // Stdio sync-RPC bridge + fd-handle lookup come from the host seam (a
110
+ // non-native backend supplies browser equivalents); native falls back to its
111
+ // own host globals so behavior is unchanged.
112
+ // Lazy resolvers: the native host globals are populated AFTER this module is
113
+ // defined (per-execution), so resolve at call time, not at module-load.
114
+ const __agentOsWasiSyncRpc = () =>
115
+ __agentOsWasiHost.syncRpc ||
116
+ (typeof globalThis.__agentOsSyncRpc !== "undefined"
117
+ ? globalThis.__agentOsSyncRpc
118
+ : undefined);
119
+ const __agentOsWasiLookupFdHandle = () =>
120
+ __agentOsWasiHost.lookupFdHandle ||
121
+ (typeof globalThis.lookupFdHandle === "function"
122
+ ? globalThis.lookupFdHandle
123
+ : undefined);
124
+ const __agentOsWasiErrnoSuccess = 0;
125
+ const __agentOsWasiErrnoAcces = 2;
126
+ const __agentOsWasiErrnoBadf = 8;
127
+ const __agentOsWasiErrnoExist = 20;
128
+ const __agentOsWasiErrnoFault = 21;
129
+ const __agentOsWasiErrnoInval = 28;
130
+ const __agentOsWasiErrnoIo = 29;
131
+ const __agentOsWasiErrnoNoent = 44;
132
+ const __agentOsWasiErrnoNosys = 52;
133
+ const __agentOsWasiErrnoNotdir = 54;
134
+ const __agentOsWasiErrnoPipe = 64;
135
+ const __agentOsWasiErrnoRofs = 69;
136
+ const __agentOsWasiErrnoXdev = 18;
137
+ const __agentOsWasiFiletypeUnknown = 0;
138
+ const __agentOsWasiFiletypeCharacterDevice = 2;
139
+ const __agentOsWasiFiletypeDirectory = 3;
140
+ const __agentOsWasiFiletypeRegularFile = 4;
141
+ const __agentOsWasiFiletypeSymbolicLink = 7;
142
+ const __agentOsWasiLookupSymlinkFollow = 1;
143
+ const __agentOsWasiOpenCreate = 1;
144
+ const __agentOsWasiOpenDirectory = 2;
145
+ const __agentOsWasiOpenExclusive = 4;
146
+ const __agentOsWasiOpenTruncate = 8;
147
+ const __agentOsWasiRightFdWrite = 1n << 6n;
148
+ const __agentOsWasiDefaultRightsBase = 0xffffffffffffffffn;
149
+ const __agentOsWasiDefaultRightsInheriting = 0xffffffffffffffffn;
150
+ const __agentOsWasiWhenceSet = 0;
151
+ const __agentOsWasiWhenceCur = 1;
152
+ const __agentOsWasiWhenceEnd = 2;
153
+ // Read cap: a non-native backend provides it via the seam; native uses its
154
+ // build-substituted constant. The ternary short-circuits so the native-only
155
+ // placeholder token is never evaluated when the seam supplies a number.
156
+ const __agentOsWasmSyncReadLimitBytes =
157
+ typeof __agentOsWasiHost.syncReadLimitBytes === "number"
158
+ ? __agentOsWasiHost.syncReadLimitBytes
159
+ : 16777216;
160
+ const __agentOsKernelStdioSyncRpcEnabled = () =>
161
+ process?.env?.AGENT_OS_WASI_STDIO_SYNC_RPC === "1";
162
+ const __agentOsWasiDebugEnabled = () => process?.env?.AGENT_OS_WASM_WASI_DEBUG === "1";
163
+ const __agentOsWasiDebug = (message) => {
164
+ if (!__agentOsWasiDebugEnabled() || typeof process?.stderr?.write !== "function") {
165
+ return;
166
+ }
167
+ try {
168
+ process.stderr.write(\`[secure-exec-wasi] \${message}\\n\`);
169
+ } catch {
170
+ // Ignore debug logging failures.
171
+ }
172
+ };
173
+
174
+ class WASI {
175
+ constructor(options = {}) {
176
+ this.args = Array.isArray(options.args) ? options.args.map((value) => String(value)) : [];
177
+ this.env =
178
+ options.env && typeof options.env === "object"
179
+ ? Object.fromEntries(
180
+ Object.entries(options.env).map(([key, value]) => [String(key), String(value)]),
181
+ )
182
+ : {};
183
+ this.preopens = options.preopens && typeof options.preopens === "object" ? options.preopens : {};
184
+ this.returnOnExit = options.returnOnExit === true;
185
+ this.instance = null;
186
+ this.nextFd = 3;
187
+ this.fdTable = new Map([
188
+ [0, { kind: "stdin", fdFlags: 0 }],
189
+ [1, { kind: "stdout", fdFlags: 0 }],
190
+ [2, { kind: "stderr", fdFlags: 0 }],
191
+ ]);
192
+ for (const [guestPath, spec] of Object.entries(this.preopens)) {
193
+ const normalized = this._normalizePreopenSpec(spec);
194
+ if (!normalized) {
195
+ continue;
196
+ }
197
+ this.fdTable.set(this.nextFd++, {
198
+ kind: "preopen",
199
+ guestPath: String(guestPath),
200
+ hostPath: normalized.hostPath,
201
+ readOnly: normalized.readOnly,
202
+ rightsBase: normalized.rightsBase,
203
+ rightsInheriting: normalized.rightsInheriting,
204
+ fdFlags: 0,
205
+ });
206
+ }
207
+ this.wasiImport = {
208
+ args_get: (...args) => this._argsGet(...args),
209
+ args_sizes_get: (...args) => this._argsSizesGet(...args),
210
+ clock_time_get: (...args) => this._clockTimeGet(...args),
211
+ clock_res_get: (...args) => this._clockResGet(...args),
212
+ environ_get: (...args) => this._environGet(...args),
213
+ environ_sizes_get: (...args) => this._environSizesGet(...args),
214
+ fd_close: (...args) => this._fdClose(...args),
215
+ fd_fdstat_get: (...args) => this._fdFdstatGet(...args),
216
+ fd_fdstat_set_flags: (...args) => this._fdFdstatSetFlags(...args),
217
+ fd_filestat_get: (...args) => this._fdFilestatGet(...args),
218
+ fd_filestat_set_size: (...args) => this._fdFilestatSetSize(...args),
219
+ fd_prestat_dir_name: (...args) => this._fdPrestatDirName(...args),
220
+ fd_prestat_get: (...args) => this._fdPrestatGet(...args),
221
+ fd_pread: (...args) => this._fdPread(...args),
222
+ fd_pwrite: (...args) => this._fdPwrite(...args),
223
+ fd_readdir: (...args) => this._fdReaddir(...args),
224
+ fd_read: (...args) => this._fdRead(...args),
225
+ fd_seek: (...args) => this._fdSeek(...args),
226
+ fd_sync: (...args) => this._fdSync(...args),
227
+ fd_tell: (...args) => this._fdTell(...args),
228
+ fd_write: (...args) => this._fdWrite(...args),
229
+ path_create_directory: (...args) => this._pathCreateDirectory(...args),
230
+ path_filestat_get: (...args) => this._pathFilestatGet(...args),
231
+ path_link: (...args) => this._pathLink(...args),
232
+ path_open: (...args) => this._pathOpen(...args),
233
+ path_readlink: (...args) => this._pathReadlink(...args),
234
+ path_remove_directory: (...args) => this._pathRemoveDirectory(...args),
235
+ path_rename: (...args) => this._pathRename(...args),
236
+ path_symlink: (...args) => this._pathSymlink(...args),
237
+ path_unlink_file: (...args) => this._pathUnlinkFile(...args),
238
+ poll_oneoff: (...args) => this._pollOneoff(...args),
239
+ proc_exit: (...args) => this._procExit(...args),
240
+ random_get: (...args) => this._randomGet(...args),
241
+ sched_yield: (...args) => this._schedYield(...args),
242
+ };
243
+ }
244
+
245
+ start(instance) {
246
+ this.instance = instance;
247
+ try {
248
+ if (typeof instance?.exports?._start === "function") {
249
+ instance.exports._start();
250
+ }
251
+ return 0;
252
+ } catch (error) {
253
+ if (error && error.__agentOsWasiExit === true) {
254
+ return Number(error.code) >>> 0;
255
+ }
256
+ throw error;
257
+ }
258
+ }
259
+
260
+ _memoryView() {
261
+ const memory = this.instance?.exports?.memory;
262
+ if (!(memory instanceof WebAssembly.Memory)) {
263
+ throw new Error("WASI memory export is unavailable");
264
+ }
265
+ return new DataView(memory.buffer);
266
+ }
267
+
268
+ _memoryBytes() {
269
+ const memory = this.instance?.exports?.memory;
270
+ if (!(memory instanceof WebAssembly.Memory)) {
271
+ throw new Error("WASI memory export is unavailable");
272
+ }
273
+ return new Uint8Array(memory.buffer);
274
+ }
275
+
276
+ _boundedIovLength(iovs, iovsLen) {
277
+ const view = this._memoryView();
278
+ let length = 0;
279
+ for (let index = 0; index < (Number(iovsLen) >>> 0); index += 1) {
280
+ const entryOffset = (Number(iovs) >>> 0) + index * 8;
281
+ length += view.getUint32(entryOffset + 4, true);
282
+ if (length > __agentOsWasmSyncReadLimitBytes) {
283
+ throw new RangeError(
284
+ \`WASI read iov length \${length} exceeds \${__agentOsWasmSyncReadLimitBytes}\`,
285
+ );
286
+ }
287
+ }
288
+ return length >>> 0;
289
+ }
290
+
291
+ _normalizeRights(value, fallback) {
292
+ try {
293
+ return BigInt(value);
294
+ } catch {
295
+ return fallback;
296
+ }
297
+ }
298
+
299
+ _normalizePreopenSpec(value) {
300
+ // Path-model seam (convergence item C): native maps guest paths to HOST
301
+ // paths (its preopen specs carry \`hostPath\`); a non-native backend with no
302
+ // host paths (the browser, whose \`require("fs")\` IS the kernel VFS) can
303
+ // supply \`__agentOsWasiHost.normalizePreopen\` to treat the guest/VFS path
304
+ // as the "hostPath" identity, so the same runner serves both.
305
+ if (typeof __agentOsWasiHost.normalizePreopen === "function") {
306
+ const seamNormalized = __agentOsWasiHost.normalizePreopen(value, {
307
+ defaultRightsBase: __agentOsWasiDefaultRightsBase,
308
+ defaultRightsInheriting: __agentOsWasiDefaultRightsInheriting,
309
+ normalizeRights: (rights, fallback) =>
310
+ this._normalizeRights(rights, fallback),
311
+ });
312
+ return seamNormalized ?? null;
313
+ }
314
+ if (typeof value === "string") {
315
+ return {
316
+ hostPath: String(value),
317
+ readOnly: false,
318
+ rightsBase: __agentOsWasiDefaultRightsBase,
319
+ rightsInheriting: __agentOsWasiDefaultRightsInheriting,
320
+ };
321
+ }
322
+ if (!value || typeof value !== "object" || typeof value.hostPath !== "string") {
323
+ return null;
324
+ }
325
+ return {
326
+ hostPath: String(value.hostPath),
327
+ readOnly: value.readOnly === true,
328
+ rightsBase: this._normalizeRights(
329
+ value.rightsBase,
330
+ __agentOsWasiDefaultRightsBase,
331
+ ),
332
+ rightsInheriting: this._normalizeRights(
333
+ value.rightsInheriting,
334
+ __agentOsWasiDefaultRightsInheriting,
335
+ ),
336
+ };
337
+ }
338
+
339
+ _descriptorRightsBase(entry) {
340
+ return this._normalizeRights(
341
+ entry?.rightsBase,
342
+ __agentOsWasiDefaultRightsBase,
343
+ );
344
+ }
345
+
346
+ _descriptorRightsInheriting(entry) {
347
+ return this._normalizeRights(
348
+ entry?.rightsInheriting,
349
+ __agentOsWasiDefaultRightsInheriting,
350
+ );
351
+ }
352
+
353
+ _hasWriteRights(rights) {
354
+ try {
355
+ return (BigInt(rights) & __agentOsWasiRightFdWrite) !== 0n;
356
+ } catch {
357
+ return true;
358
+ }
359
+ }
360
+
361
+ _writeUint32(ptr, value) {
362
+ try {
363
+ this._memoryView().setUint32(Number(ptr) >>> 0, Number(value) >>> 0, true);
364
+ return __agentOsWasiErrnoSuccess;
365
+ } catch {
366
+ __agentOsWasiDebug(\`writeUint32 failed ptr=\${Number(ptr)} value=\${Number(value)}\`);
367
+ return __agentOsWasiErrnoFault;
368
+ }
369
+ }
370
+
371
+ _writeUint64(ptr, value) {
372
+ try {
373
+ this._memoryView().setBigUint64(Number(ptr) >>> 0, BigInt(value), true);
374
+ return __agentOsWasiErrnoSuccess;
375
+ } catch {
376
+ __agentOsWasiDebug(\`writeUint64 failed ptr=\${Number(ptr)} value=\${String(value)}\`);
377
+ return __agentOsWasiErrnoFault;
378
+ }
379
+ }
380
+
381
+ _writeBytes(ptr, bytes) {
382
+ try {
383
+ this._memoryBytes().set(bytes, Number(ptr) >>> 0);
384
+ return __agentOsWasiErrnoSuccess;
385
+ } catch {
386
+ __agentOsWasiDebug(\`writeBytes failed ptr=\${Number(ptr)} len=\${bytes?.length ?? 0}\`);
387
+ return __agentOsWasiErrnoFault;
388
+ }
389
+ }
390
+
391
+ _readBytes(ptr, len) {
392
+ const start = Number(ptr) >>> 0;
393
+ const end = start + (Number(len) >>> 0);
394
+ return Buffer.from(this._memoryBytes().slice(start, end));
395
+ }
396
+
397
+ _readString(ptr, len) {
398
+ return this._readBytes(ptr, len).toString("utf8");
399
+ }
400
+
401
+ _decodeSyncRpcBytes(value) {
402
+ if (value == null) {
403
+ return null;
404
+ }
405
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
406
+ return value;
407
+ }
408
+ if (value instanceof Uint8Array) {
409
+ return Buffer.from(value);
410
+ }
411
+ if (ArrayBuffer.isView(value)) {
412
+ return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
413
+ }
414
+ if (value instanceof ArrayBuffer) {
415
+ return Buffer.from(value);
416
+ }
417
+ if (
418
+ value &&
419
+ typeof value === "object" &&
420
+ value.__agentOsType === "bytes" &&
421
+ typeof value.base64 === "string"
422
+ ) {
423
+ return Buffer.from(value.base64, "base64");
424
+ }
425
+ return null;
426
+ }
427
+
428
+ _dequeuePipeBytes(pipe, maxBytes) {
429
+ if (!pipe || !Array.isArray(pipe.chunks) || pipe.chunks.length === 0) {
430
+ return Buffer.alloc(0);
431
+ }
432
+
433
+ let remaining = Math.max(0, Number(maxBytes) >>> 0);
434
+ if (remaining === 0) {
435
+ return Buffer.alloc(0);
436
+ }
437
+
438
+ const parts = [];
439
+ while (remaining > 0 && pipe.chunks.length > 0) {
440
+ const chunk = pipe.chunks[0];
441
+ if (!chunk || chunk.length === 0) {
442
+ pipe.chunks.shift();
443
+ continue;
444
+ }
445
+
446
+ if (chunk.length <= remaining) {
447
+ parts.push(chunk);
448
+ pipe.chunks.shift();
449
+ remaining -= chunk.length;
450
+ continue;
451
+ }
452
+
453
+ parts.push(chunk.subarray(0, remaining));
454
+ pipe.chunks[0] = chunk.subarray(remaining);
455
+ remaining = 0;
456
+ }
457
+
458
+ return Buffer.concat(parts);
459
+ }
460
+
461
+ _enqueuePipeBytes(pipe, bytes) {
462
+ if (!pipe || !Array.isArray(pipe.chunks)) {
463
+ return;
464
+ }
465
+ const chunk = Buffer.from(bytes ?? []);
466
+ if (chunk.length === 0) {
467
+ return;
468
+ }
469
+ pipe.chunks.push(chunk);
470
+ }
471
+
472
+ _pipeHasReaders(pipe) {
473
+ return (
474
+ (pipe?.readHandleCount ?? 0) > 0 ||
475
+ (pipe?.consumers?.size ?? 0) > 0
476
+ );
477
+ }
478
+
479
+ _flushPipeConsumers(pipe) {
480
+ if (
481
+ !pipe ||
482
+ typeof pipe.consumers?.entries !== "function" ||
483
+ !Array.isArray(pipe.chunks) ||
484
+ pipe.chunks.length === 0 ||
485
+ typeof globalThis?.__agentOsSyncRpc?.callSync !== "function"
486
+ ) {
487
+ return false;
488
+ }
489
+
490
+ let flushed = false;
491
+ while (pipe.chunks.length > 0) {
492
+ const chunk = pipe.chunks.shift();
493
+ if (!chunk || chunk.length === 0) {
494
+ continue;
495
+ }
496
+
497
+ for (const [consumerKey, consumer] of Array.from(pipe.consumers.entries())) {
498
+ if (!consumer || typeof consumer.childId !== "string") {
499
+ pipe.consumers.delete(consumerKey);
500
+ continue;
501
+ }
502
+ try {
503
+ __agentOsWasiSyncRpc().callSync("child_process.write_stdin", [
504
+ consumer.childId,
505
+ chunk,
506
+ ]);
507
+ flushed = true;
508
+ } catch {
509
+ pipe.consumers.delete(consumerKey);
510
+ }
511
+ }
512
+ }
513
+
514
+ return flushed;
515
+ }
516
+
517
+ _closePipeConsumers(pipe) {
518
+ if (
519
+ !pipe ||
520
+ typeof pipe.consumers?.entries !== "function" ||
521
+ typeof globalThis?.__agentOsSyncRpc?.callSync !== "function"
522
+ ) {
523
+ return false;
524
+ }
525
+
526
+ let closed = false;
527
+ for (const [consumerKey, consumer] of Array.from(pipe.consumers.entries())) {
528
+ if (!consumer || typeof consumer.childId !== "string") {
529
+ pipe.consumers.delete(consumerKey);
530
+ continue;
531
+ }
532
+ try {
533
+ __agentOsWasiSyncRpc().callSync("child_process.close_stdin", [
534
+ consumer.childId,
535
+ ]);
536
+ closed = true;
537
+ } catch {
538
+ // Ignore close errors during teardown.
539
+ }
540
+ pipe.consumers.delete(consumerKey);
541
+ }
542
+
543
+ return closed;
544
+ }
545
+
546
+ _pumpPipeProducers(pipe, waitMs) {
547
+ if (
548
+ !pipe ||
549
+ typeof pipe.producers?.entries !== "function" ||
550
+ typeof globalThis?.__agentOsSyncRpc?.callSync !== "function"
551
+ ) {
552
+ return false;
553
+ }
554
+
555
+ let processed = false;
556
+ for (const [producerKey, producer] of Array.from(pipe.producers.entries())) {
557
+ if (!producer || typeof producer.childId !== "string") {
558
+ pipe.producers.delete(producerKey);
559
+ continue;
560
+ }
561
+
562
+ let event = null;
563
+ try {
564
+ event = __agentOsWasiSyncRpc().callSync("child_process.poll", [
565
+ producer.childId,
566
+ Math.max(0, Number(waitMs) >>> 0),
567
+ ]);
568
+ } catch {
569
+ pipe.producers.delete(producerKey);
570
+ continue;
571
+ }
572
+
573
+ if (!event) {
574
+ continue;
575
+ }
576
+
577
+ processed = true;
578
+ const streamType =
579
+ producer.stream === "stderr" ? "stderr" : producer.stream === "stdout" ? "stdout" : null;
580
+ if ((event.type === "stdout" || event.type === "stderr") && event.type === streamType) {
581
+ const chunk = this._decodeSyncRpcBytes(event.data);
582
+ if (chunk && chunk.length > 0) {
583
+ pipe.chunks.push(Buffer.from(chunk));
584
+ }
585
+ continue;
586
+ }
587
+
588
+ if (event.type === "exit") {
589
+ pipe.producers.delete(producerKey);
590
+ if (pipe.producers.size === 0 && (pipe.writeHandleCount ?? 0) === 0) {
591
+ this._closePipeConsumers(pipe);
592
+ }
593
+ continue;
594
+ }
595
+ }
596
+
597
+ return processed;
598
+ }
599
+
600
+ _collectIovs(iovs, iovsLen) {
601
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
602
+ const view = this._memoryView();
603
+ const chunks = [];
604
+ for (let index = 0; index < (Number(iovsLen) >>> 0); index += 1) {
605
+ const entryOffset = (Number(iovs) >>> 0) + index * 8;
606
+ const ptr = view.getUint32(entryOffset, true);
607
+ const len = view.getUint32(entryOffset + 4, true);
608
+ chunks.push(this._readBytes(ptr, len));
609
+ }
610
+ return Buffer.concat(chunks, totalLength);
611
+ }
612
+
613
+ _writeToIovs(iovs, iovsLen, bytes) {
614
+ const view = this._memoryView();
615
+ const memory = this._memoryBytes();
616
+ let sourceOffset = 0;
617
+ for (let index = 0; index < (Number(iovsLen) >>> 0) && sourceOffset < bytes.length; index += 1) {
618
+ const entryOffset = (Number(iovs) >>> 0) + index * 8;
619
+ const ptr = view.getUint32(entryOffset, true);
620
+ const len = view.getUint32(entryOffset + 4, true);
621
+ const chunk = bytes.subarray(sourceOffset, sourceOffset + len);
622
+ memory.set(chunk, Number(ptr) >>> 0);
623
+ sourceOffset += chunk.length;
624
+ }
625
+ return sourceOffset;
626
+ }
627
+
628
+ _stringTable(values) {
629
+ return values.map((value) => Buffer.from(\`\${String(value)}\\0\`, "utf8"));
630
+ }
631
+
632
+ _writeStringTable(values, offsetsPtr, bufferPtr) {
633
+ try {
634
+ const view = this._memoryView();
635
+ const memory = this._memoryBytes();
636
+ let cursor = Number(bufferPtr) >>> 0;
637
+ for (let index = 0; index < values.length; index += 1) {
638
+ const bytes = values[index];
639
+ view.setUint32((Number(offsetsPtr) >>> 0) + index * 4, cursor, true);
640
+ memory.set(bytes, cursor);
641
+ cursor += bytes.length;
642
+ }
643
+ return __agentOsWasiErrnoSuccess;
644
+ } catch {
645
+ __agentOsWasiDebug(
646
+ \`writeStringTable failed offsetsPtr=\${Number(offsetsPtr)} bufferPtr=\${Number(bufferPtr)} count=\${values.length}\`,
647
+ );
648
+ return __agentOsWasiErrnoFault;
649
+ }
650
+ }
651
+
652
+ _filetypeForStats(stats) {
653
+ if (!stats) {
654
+ return __agentOsWasiFiletypeUnknown;
655
+ }
656
+ if (typeof stats.isDirectory === "function" && stats.isDirectory()) {
657
+ return __agentOsWasiFiletypeDirectory;
658
+ }
659
+ if (typeof stats.isFile === "function" && stats.isFile()) {
660
+ return __agentOsWasiFiletypeRegularFile;
661
+ }
662
+ if (typeof stats.isSymbolicLink === "function" && stats.isSymbolicLink()) {
663
+ return __agentOsWasiFiletypeSymbolicLink;
664
+ }
665
+ if (typeof stats.isCharacterDevice === "function" && stats.isCharacterDevice()) {
666
+ return __agentOsWasiFiletypeCharacterDevice;
667
+ }
668
+ return __agentOsWasiFiletypeUnknown;
669
+ }
670
+
671
+ _fdFiletype(entry) {
672
+ if (!entry) {
673
+ return __agentOsWasiFiletypeUnknown;
674
+ }
675
+ if (
676
+ entry.kind === "stdin" ||
677
+ entry.kind === "stdout" ||
678
+ entry.kind === "stderr"
679
+ ) {
680
+ return __agentOsWasiFiletypeCharacterDevice;
681
+ }
682
+ if (entry.kind === "preopen" || entry.kind === "directory") {
683
+ return __agentOsWasiFiletypeDirectory;
684
+ }
685
+ if (entry.kind === "symlink") {
686
+ return __agentOsWasiFiletypeSymbolicLink;
687
+ }
688
+ return __agentOsWasiFiletypeRegularFile;
689
+ }
690
+
691
+ _mapFsError(error) {
692
+ switch (error?.code) {
693
+ case "EACCES":
694
+ case "EPERM":
695
+ return __agentOsWasiErrnoAcces;
696
+ case "ENOENT":
697
+ return __agentOsWasiErrnoNoent;
698
+ case "ENOTDIR":
699
+ return __agentOsWasiErrnoNotdir;
700
+ case "EEXIST":
701
+ return __agentOsWasiErrnoExist;
702
+ case "EINVAL":
703
+ return __agentOsWasiErrnoInval;
704
+ case "EROFS":
705
+ return __agentOsWasiErrnoRofs;
706
+ case "EXDEV":
707
+ return __agentOsWasiErrnoXdev;
708
+ default:
709
+ return __agentOsWasiErrnoIo;
710
+ }
711
+ }
712
+
713
+ _descriptorEntry(fd) {
714
+ return this.fdTable.get(Number(fd) >>> 0) ?? null;
715
+ }
716
+
717
+ _localFdHandle(fd) {
718
+ const entry = this._descriptorEntry(fd);
719
+ if (!entry || typeof entry.realFd !== "number") {
720
+ return null;
721
+ }
722
+ return {
723
+ kind: "host-passthrough",
724
+ targetFd: entry.realFd,
725
+ displayFd: Number(fd) >>> 0,
726
+ refCount: 1,
727
+ open: true,
728
+ readOnly: entry.readOnly === true,
729
+ };
730
+ }
731
+
732
+ _externalFdHandle(fd) {
733
+ const descriptor = Number(fd) >>> 0;
734
+ const localHandle = this._localFdHandle(descriptor);
735
+ if (localHandle) {
736
+ return localHandle;
737
+ }
738
+ try {
739
+ if (typeof lookupFdHandle === "function") {
740
+ return lookupFdHandle(descriptor) ?? null;
741
+ }
742
+ } catch {
743
+ // Fall through to other lookup paths.
744
+ }
745
+ try {
746
+ const __agentOsWasiFdHandleFn = __agentOsWasiLookupFdHandle();
747
+ if (typeof __agentOsWasiFdHandleFn === "function") {
748
+ return __agentOsWasiFdHandleFn(descriptor) ?? null;
749
+ }
750
+ } catch {
751
+ // Ignore missing global bridge helpers.
752
+ }
753
+ return null;
754
+ }
755
+
756
+ _descriptorHostPath(entry) {
757
+ if (!entry) {
758
+ return null;
759
+ }
760
+ if (typeof entry.hostPath === "string") {
761
+ return entry.hostPath;
762
+ }
763
+ if (typeof entry.realFd === "number") {
764
+ return __agentOsFs().readlinkSync(\`/proc/self/fd/\${entry.realFd}\`);
765
+ }
766
+ return null;
767
+ }
768
+
769
+ _descriptorFsPath(entry) {
770
+ if (!entry) {
771
+ return null;
772
+ }
773
+ if (typeof entry.hostPath === "string" && entry.hostPath.length > 0) {
774
+ return entry.hostPath;
775
+ }
776
+ if (typeof entry.guestPath === "string" && entry.guestPath.length > 0) {
777
+ return entry.guestPath;
778
+ }
779
+ return null;
780
+ }
781
+
782
+ _sidecarManagedProcess() {
783
+ if (
784
+ typeof globalThis.__agentOsWasmInternalEnv?.AGENT_OS_SANDBOX_ROOT ===
785
+ "string" &&
786
+ globalThis.__agentOsWasmInternalEnv.AGENT_OS_SANDBOX_ROOT.length > 0
787
+ ) {
788
+ return true;
789
+ }
790
+ return (
791
+ typeof process?.env?.AGENT_OS_SANDBOX_ROOT === "string" &&
792
+ process.env.AGENT_OS_SANDBOX_ROOT.length > 0
793
+ );
794
+ }
795
+
796
+ _descriptorDirectoryFsPath(entry) {
797
+ if (
798
+ (entry?.kind === "preopen" || entry?.kind === "directory") &&
799
+ this._sidecarManagedProcess()
800
+ ) {
801
+ return this._descriptorGuestPath(entry);
802
+ }
803
+ return this._descriptorFsPath(entry);
804
+ }
805
+
806
+ _descriptorGuestPath(entry) {
807
+ if (!entry) {
808
+ return null;
809
+ }
810
+ const guestPath = typeof entry.guestPath === "string" ? entry.guestPath : null;
811
+ if (guestPath === ".") {
812
+ return this._currentGuestCwd();
813
+ }
814
+ if (typeof guestPath === "string" && guestPath.length > 0) {
815
+ return __agentOsPath().posix.normalize(guestPath);
816
+ }
817
+ return null;
818
+ }
819
+
820
+ _descriptorPreopenName(entry) {
821
+ if (!entry) {
822
+ return null;
823
+ }
824
+ const guestPath = typeof entry.guestPath === "string" ? entry.guestPath : null;
825
+ if (guestPath === ".") {
826
+ return this._descriptorGuestPath(entry);
827
+ }
828
+ if (typeof guestPath === "string" && guestPath.length > 0) {
829
+ return __agentOsPath().posix.normalize(guestPath);
830
+ }
831
+ return null;
832
+ }
833
+
834
+ _currentDirectoryPreopen() {
835
+ for (const entry of this.fdTable.values()) {
836
+ if (entry?.kind === "preopen" && entry.guestPath === ".") {
837
+ return entry;
838
+ }
839
+ }
840
+ return null;
841
+ }
842
+
843
+ _descriptorPathBase(entry, target) {
844
+ const baseGuestPath = this._descriptorGuestPath(entry);
845
+ if (typeof baseGuestPath !== "string") {
846
+ return null;
847
+ }
848
+ return {
849
+ entry,
850
+ guestPath: baseGuestPath,
851
+ hostPath: typeof entry?.hostPath === "string" ? entry.hostPath : null,
852
+ };
853
+ }
854
+
855
+ _hostPathExists(hostPath) {
856
+ try {
857
+ __agentOsFs().statSync(hostPath);
858
+ return true;
859
+ } catch {
860
+ return false;
861
+ }
862
+ }
863
+
864
+ _currentGuestCwd() {
865
+ const pwd =
866
+ typeof this.env?.PWD === "string" && this.env.PWD.startsWith("/")
867
+ ? this.env.PWD
868
+ : typeof this.env?.HOME === "string" && this.env.HOME.startsWith("/")
869
+ ? this.env.HOME
870
+ : "/";
871
+ return __agentOsPath().posix.normalize(pwd);
872
+ }
873
+
874
+ _resolveHostMappingForGuestPath(guestPath) {
875
+ const normalized = __agentOsPath().posix.normalize(guestPath);
876
+ const mappings = [];
877
+ for (const entry of this.fdTable.values()) {
878
+ if (entry?.kind !== "preopen" || typeof entry.hostPath !== "string") {
879
+ continue;
880
+ }
881
+ const guestRoot = this._descriptorGuestPath(entry);
882
+ if (typeof guestRoot !== "string") {
883
+ continue;
884
+ }
885
+ mappings.push({
886
+ guestRoot,
887
+ hostPath: entry.hostPath,
888
+ readOnly: entry.readOnly === true,
889
+ });
890
+ }
891
+ mappings.sort((left, right) => right.guestRoot.length - left.guestRoot.length);
892
+
893
+ for (const mapping of mappings) {
894
+ const matchesRoot = mapping.guestRoot === "/" && normalized.startsWith("/");
895
+ const matchesNested =
896
+ normalized === mapping.guestRoot ||
897
+ normalized.startsWith(\`\${mapping.guestRoot}/\`);
898
+ if (!matchesRoot && !matchesNested) {
899
+ continue;
900
+ }
901
+ const suffix =
902
+ normalized === mapping.guestRoot
903
+ ? ""
904
+ : mapping.guestRoot === "/"
905
+ ? normalized.slice(1)
906
+ : normalized.slice(mapping.guestRoot.length + 1);
907
+ return {
908
+ hostPath: suffix
909
+ ? __agentOsPath().join(mapping.hostPath, ...suffix.split("/"))
910
+ : mapping.hostPath,
911
+ readOnly: mapping.readOnly,
912
+ };
913
+ }
914
+
915
+ return null;
916
+ }
917
+
918
+ _resolveHostPathForGuestPath(guestPath) {
919
+ return this._resolveHostMappingForGuestPath(guestPath)?.hostPath ?? null;
920
+ }
921
+
922
+ _rootRelativeTargetPrefersCwd(target) {
923
+ const normalizedTarget = __agentOsPath().posix.normalize(target || ".");
924
+ if (normalizedTarget !== ".") {
925
+ return false;
926
+ }
927
+ return !this._rootRelativeTargetMatchesAbsoluteArg(target);
928
+ }
929
+
930
+ _rootRelativeTargetMatchesAbsoluteArg(target) {
931
+ const rootGuestPath = __agentOsPath().posix.resolve("/", target);
932
+ return this.args
933
+ .slice(1)
934
+ .some(
935
+ (arg) =>
936
+ typeof arg === "string" &&
937
+ arg.startsWith("/") &&
938
+ __agentOsPath().posix.normalize(arg) === rootGuestPath,
939
+ );
940
+ }
941
+
942
+ _resolveRootRelativePath(target, preferCreateParent = false) {
943
+ const rootGuestPath = __agentOsPath().posix.resolve("/", target);
944
+ const rootMapping = this._resolveHostMappingForGuestPath(rootGuestPath);
945
+ const rootHostPath = rootMapping?.hostPath ?? null;
946
+ const cwdGuestPath = this._currentGuestCwd();
947
+ if (cwdGuestPath !== "/") {
948
+ const cwdGuestTarget = __agentOsPath().posix.resolve(cwdGuestPath, target);
949
+ const cwdMapping = this._resolveHostMappingForGuestPath(cwdGuestTarget);
950
+ const cwdHostTarget = cwdMapping?.hostPath ?? null;
951
+ if (
952
+ typeof cwdHostTarget === "string" &&
953
+ (
954
+ (preferCreateParent && !this._rootRelativeTargetMatchesAbsoluteArg(target)) ||
955
+ this._rootRelativeTargetPrefersCwd(target) ||
956
+ (
957
+ this._hostPathExists(cwdHostTarget) &&
958
+ !(typeof rootHostPath === "string" && this._hostPathExists(rootHostPath))
959
+ )
960
+ )
961
+ ) {
962
+ return {
963
+ guestPath: cwdGuestTarget,
964
+ hostPath: cwdHostTarget,
965
+ readOnly: cwdMapping?.readOnly === true,
966
+ };
967
+ }
968
+ }
969
+ return {
970
+ guestPath: rootGuestPath,
971
+ hostPath: rootHostPath,
972
+ readOnly: rootMapping?.readOnly === true,
973
+ };
974
+ }
975
+
976
+ _resolveDescriptorPath(fd, pathPtr, pathLen, options = {}) {
977
+ const entry = this._descriptorEntry(fd);
978
+ if (!entry) {
979
+ return { error: __agentOsWasiErrnoBadf };
980
+ }
981
+ const target = this._readString(pathPtr, pathLen);
982
+ const base = this._descriptorPathBase(entry, target);
983
+ if (!base || typeof base.guestPath !== "string") {
984
+ return { error: __agentOsWasiErrnoBadf };
985
+ }
986
+ const guestPath = target.startsWith("/")
987
+ ? __agentOsPath().posix.normalize(target)
988
+ : __agentOsPath().posix.resolve(base.guestPath, target);
989
+ const mapped =
990
+ base.guestPath === "/" && !target.startsWith("/")
991
+ ? this._resolveRootRelativePath(
992
+ target,
993
+ options.preferCreateParent === true,
994
+ )
995
+ : {
996
+ guestPath,
997
+ ...(
998
+ this._resolveHostMappingForGuestPath(guestPath) ??
999
+ { hostPath: null, readOnly: false }
1000
+ ),
1001
+ };
1002
+ const hostPath = mapped.hostPath;
1003
+ if (typeof hostPath !== "string") {
1004
+ return { error: __agentOsWasiErrnoNoent };
1005
+ }
1006
+ return {
1007
+ error: __agentOsWasiErrnoSuccess,
1008
+ guestPath: mapped.guestPath,
1009
+ hostPath,
1010
+ readOnly: mapped.readOnly === true,
1011
+ };
1012
+ }
1013
+
1014
+ _resolvedFsPath(resolved) {
1015
+ if (this._sidecarManagedProcess() && typeof resolved?.guestPath === "string") {
1016
+ return resolved.guestPath;
1017
+ }
1018
+ return resolved?.hostPath ?? null;
1019
+ }
1020
+
1021
+ _writeFilestat(statPtr, stats, fallbackType) {
1022
+ try {
1023
+ const view = this._memoryView();
1024
+ const offset = Number(statPtr) >>> 0;
1025
+ const filetype = stats ? this._filetypeForStats(stats) : fallbackType;
1026
+ view.setBigUint64(offset, 0n, true);
1027
+ view.setBigUint64(offset + 8, BigInt(stats?.ino ?? 0), true);
1028
+ view.setUint8(offset + 16, filetype);
1029
+ view.setBigUint64(offset + 24, BigInt(stats?.nlink ?? 1), true);
1030
+ view.setBigUint64(offset + 32, BigInt(stats?.size ?? 0), true);
1031
+ view.setBigUint64(offset + 40, BigInt(Math.trunc((stats?.atimeMs ?? 0) * 1000000)), true);
1032
+ view.setBigUint64(offset + 48, BigInt(Math.trunc((stats?.mtimeMs ?? 0) * 1000000)), true);
1033
+ view.setBigUint64(offset + 56, BigInt(Math.trunc((stats?.ctimeMs ?? 0) * 1000000)), true);
1034
+ return __agentOsWasiErrnoSuccess;
1035
+ } catch (error) {
1036
+ return this._mapFsError(error);
1037
+ }
1038
+ }
1039
+
1040
+ _argsSizesGet(argcPtr, argvBufSizePtr) {
1041
+ const values = this._stringTable(this.args);
1042
+ const total = values.reduce((sum, value) => sum + value.length, 0);
1043
+ const argcStatus = this._writeUint32(argcPtr, values.length);
1044
+ if (argcStatus !== __agentOsWasiErrnoSuccess) {
1045
+ return argcStatus;
1046
+ }
1047
+ return this._writeUint32(argvBufSizePtr, total);
1048
+ }
1049
+
1050
+ _argsGet(argvPtr, argvBufPtr) {
1051
+ return this._writeStringTable(this._stringTable(this.args), argvPtr, argvBufPtr);
1052
+ }
1053
+
1054
+ _environEntries() {
1055
+ return Object.entries(this.env).map(([key, value]) => \`\${key}=\${value}\`);
1056
+ }
1057
+
1058
+ _environSizesGet(countPtr, bufSizePtr) {
1059
+ const values = this._stringTable(this._environEntries());
1060
+ const total = values.reduce((sum, value) => sum + value.length, 0);
1061
+ const countStatus = this._writeUint32(countPtr, values.length);
1062
+ if (countStatus !== __agentOsWasiErrnoSuccess) {
1063
+ return countStatus;
1064
+ }
1065
+ return this._writeUint32(bufSizePtr, total);
1066
+ }
1067
+
1068
+ _environGet(environPtr, environBufPtr) {
1069
+ return this._writeStringTable(
1070
+ this._stringTable(this._environEntries()),
1071
+ environPtr,
1072
+ environBufPtr,
1073
+ );
1074
+ }
1075
+
1076
+ _clockTimeGet(_clockId, _precision, resultPtr) {
1077
+ return this._writeUint64(resultPtr, BigInt(Date.now()) * 1000000n);
1078
+ }
1079
+
1080
+ _clockResGet(_clockId, resultPtr) {
1081
+ return this._writeUint64(resultPtr, 1000000n);
1082
+ }
1083
+
1084
+ _fdWrite(fd, iovs, iovsLen, nwrittenPtr) {
1085
+ try {
1086
+ const bytes = this._collectIovs(iovs, iovsLen);
1087
+ const descriptor = Number(fd) >>> 0;
1088
+ const handle = this._externalFdHandle(descriptor);
1089
+ if (handle?.kind === "pipe-write" && handle.pipe) {
1090
+ if (bytes.length > 0 && !this._pipeHasReaders(handle.pipe)) {
1091
+ return __agentOsWasiErrnoPipe;
1092
+ }
1093
+ this._enqueuePipeBytes(handle.pipe, bytes);
1094
+ this._flushPipeConsumers(handle.pipe);
1095
+ return this._writeUint32(nwrittenPtr, bytes.length);
1096
+ }
1097
+ if (
1098
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1099
+ typeof handle.targetFd === "number"
1100
+ ) {
1101
+ if (handle.readOnly === true) {
1102
+ return __agentOsWasiErrnoRofs;
1103
+ }
1104
+ if (descriptor === 1 || descriptor === 2) {
1105
+ const sidecarManagedProcess =
1106
+ typeof process?.env?.AGENT_OS_SANDBOX_ROOT === "string" &&
1107
+ process.env.AGENT_OS_SANDBOX_ROOT.length > 0;
1108
+ const useKernelStdioSyncRpc =
1109
+ sidecarManagedProcess || __agentOsKernelStdioSyncRpcEnabled();
1110
+ if (useKernelStdioSyncRpc) {
1111
+ const written = Number(
1112
+ __agentOsWasiSyncRpc().callSync("__kernel_stdio_write", [descriptor, bytes]),
1113
+ ) >>> 0;
1114
+ return this._writeUint32(nwrittenPtr, written);
1115
+ }
1116
+ }
1117
+ const written = __agentOsFs().writeSync(
1118
+ handle.targetFd,
1119
+ bytes,
1120
+ 0,
1121
+ bytes.length,
1122
+ null,
1123
+ );
1124
+ return this._writeUint32(nwrittenPtr, written);
1125
+ }
1126
+ if (handle?.kind === "guest-file" && typeof handle.targetFd === "number") {
1127
+ const position = handle.append ? null : (handle.position ?? 0);
1128
+ const written = __agentOsFs().writeSync(
1129
+ handle.targetFd,
1130
+ bytes,
1131
+ 0,
1132
+ bytes.length,
1133
+ position,
1134
+ );
1135
+ if (handle.append) {
1136
+ handle.position = Number(__agentOsFs().fstatSync(handle.targetFd).size ?? 0);
1137
+ } else {
1138
+ handle.position = (handle.position ?? 0) + written;
1139
+ }
1140
+ return this._writeUint32(nwrittenPtr, written);
1141
+ }
1142
+ const entry = this.fdTable.get(descriptor);
1143
+ if (!entry) {
1144
+ return __agentOsWasiErrnoBadf;
1145
+ }
1146
+ if (entry.kind === "stdout") {
1147
+ const sidecarManagedProcess =
1148
+ typeof process?.env?.AGENT_OS_SANDBOX_ROOT === "string" &&
1149
+ process.env.AGENT_OS_SANDBOX_ROOT.length > 0;
1150
+ const useKernelStdioSyncRpc =
1151
+ sidecarManagedProcess || __agentOsKernelStdioSyncRpcEnabled();
1152
+ const written = useKernelStdioSyncRpc
1153
+ ? Number(__agentOsWasiSyncRpc().callSync("__kernel_stdio_write", [1, bytes])) >>> 0
1154
+ : (process.stdout.write(bytes), bytes.length);
1155
+ return this._writeUint32(nwrittenPtr, written);
1156
+ }
1157
+ if (entry.kind === "stderr") {
1158
+ const sidecarManagedProcess =
1159
+ typeof process?.env?.AGENT_OS_SANDBOX_ROOT === "string" &&
1160
+ process.env.AGENT_OS_SANDBOX_ROOT.length > 0;
1161
+ const useKernelStdioSyncRpc =
1162
+ sidecarManagedProcess || __agentOsKernelStdioSyncRpcEnabled();
1163
+ const written = useKernelStdioSyncRpc
1164
+ ? Number(__agentOsWasiSyncRpc().callSync("__kernel_stdio_write", [2, bytes])) >>> 0
1165
+ : (process.stderr.write(bytes), bytes.length);
1166
+ return this._writeUint32(nwrittenPtr, written);
1167
+ }
1168
+ if (entry.readOnly === true) {
1169
+ return __agentOsWasiErrnoRofs;
1170
+ }
1171
+ if (entry.kind === "file") {
1172
+ const position = typeof entry.offset === "number" ? entry.offset : null;
1173
+ const written = __agentOsFs().writeSync(
1174
+ entry.realFd,
1175
+ bytes,
1176
+ 0,
1177
+ bytes.length,
1178
+ position,
1179
+ );
1180
+ if (typeof entry.offset === "number") {
1181
+ entry.offset += written;
1182
+ }
1183
+ return this._writeUint32(nwrittenPtr, written);
1184
+ }
1185
+ return __agentOsWasiErrnoBadf;
1186
+ } catch (error) {
1187
+ return this._mapFsError(error);
1188
+ }
1189
+ }
1190
+
1191
+ _fdPwrite(fd, iovs, iovsLen, offset, nwrittenPtr) {
1192
+ try {
1193
+ const bytes = this._collectIovs(iovs, iovsLen);
1194
+ const descriptor = Number(fd) >>> 0;
1195
+ const handle = this._externalFdHandle(descriptor);
1196
+ if (
1197
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1198
+ typeof handle.targetFd === "number"
1199
+ ) {
1200
+ if (handle.readOnly === true) {
1201
+ return __agentOsWasiErrnoRofs;
1202
+ }
1203
+ const written = __agentOsFs().writeSync(
1204
+ handle.targetFd,
1205
+ bytes,
1206
+ 0,
1207
+ bytes.length,
1208
+ Number(offset) >>> 0,
1209
+ );
1210
+ return this._writeUint32(nwrittenPtr, written);
1211
+ }
1212
+ const entry = this.fdTable.get(descriptor);
1213
+ if (!entry || entry.kind !== "file") {
1214
+ return __agentOsWasiErrnoBadf;
1215
+ }
1216
+ if (entry.readOnly === true) {
1217
+ return __agentOsWasiErrnoRofs;
1218
+ }
1219
+ const written = __agentOsFs().writeSync(
1220
+ entry.realFd,
1221
+ bytes,
1222
+ 0,
1223
+ bytes.length,
1224
+ Number(offset) >>> 0,
1225
+ );
1226
+ return this._writeUint32(nwrittenPtr, written);
1227
+ } catch {
1228
+ return __agentOsWasiErrnoFault;
1229
+ }
1230
+ }
1231
+
1232
+ _fdPread(fd, iovs, iovsLen, offset, nreadPtr) {
1233
+ try {
1234
+ const descriptor = Number(fd) >>> 0;
1235
+ const explicitOffset = Number(offset) >>> 0;
1236
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
1237
+ const buffer = Buffer.alloc(totalLength);
1238
+ const handle = this._externalFdHandle(descriptor);
1239
+ if (
1240
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1241
+ typeof handle.targetFd === "number"
1242
+ ) {
1243
+ const bytesRead = __agentOsFs().readSync(
1244
+ handle.targetFd,
1245
+ buffer,
1246
+ 0,
1247
+ totalLength,
1248
+ explicitOffset,
1249
+ );
1250
+ const written = this._writeToIovs(iovs, iovsLen, buffer.subarray(0, bytesRead));
1251
+ return this._writeUint32(nreadPtr, written);
1252
+ }
1253
+ const entry = this.fdTable.get(descriptor);
1254
+ if (!entry || entry.kind !== "file") {
1255
+ return __agentOsWasiErrnoBadf;
1256
+ }
1257
+ const bytesRead = __agentOsFs().readSync(
1258
+ entry.realFd,
1259
+ buffer,
1260
+ 0,
1261
+ totalLength,
1262
+ explicitOffset,
1263
+ );
1264
+ const written = this._writeToIovs(iovs, iovsLen, buffer.subarray(0, bytesRead));
1265
+ return this._writeUint32(nreadPtr, written);
1266
+ } catch {
1267
+ return __agentOsWasiErrnoFault;
1268
+ }
1269
+ }
1270
+
1271
+ _fdRead(fd, iovs, iovsLen, nreadPtr) {
1272
+ try {
1273
+ const descriptor = Number(fd) >>> 0;
1274
+ const handle = this._externalFdHandle(descriptor);
1275
+ if (handle?.kind === "pipe-read" && handle.pipe) {
1276
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
1277
+ while (handle.pipe.chunks.length === 0) {
1278
+ if (handle.pipe.writeHandleCount === 0 && handle.pipe.producers.size === 0) {
1279
+ return this._writeUint32(nreadPtr, 0);
1280
+ }
1281
+ this._pumpPipeProducers(handle.pipe, 10);
1282
+ }
1283
+ const chunk = this._dequeuePipeBytes(handle.pipe, totalLength);
1284
+ const written = this._writeToIovs(iovs, iovsLen, chunk);
1285
+ return this._writeUint32(nreadPtr, written);
1286
+ }
1287
+ const entry = this.fdTable.get(descriptor);
1288
+ if (!entry) {
1289
+ return __agentOsWasiErrnoBadf;
1290
+ }
1291
+ if (entry.kind === "stdin") {
1292
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
1293
+ const syncRpc =
1294
+ typeof globalThis?.__agentOsSyncRpc?.callSync === "function"
1295
+ ? __agentOsWasiSyncRpc()
1296
+ : null;
1297
+ const sidecarManagedProcess =
1298
+ typeof process?.env?.AGENT_OS_SANDBOX_ROOT === "string" &&
1299
+ process.env.AGENT_OS_SANDBOX_ROOT.length > 0;
1300
+ if (syncRpc && (sidecarManagedProcess || __agentOsKernelStdioSyncRpcEnabled())) {
1301
+ try {
1302
+ let chunk = null;
1303
+ while (true) {
1304
+ const response = syncRpc.callSync("__kernel_stdin_read", [totalLength, 10]);
1305
+ if (
1306
+ response &&
1307
+ typeof response === "object" &&
1308
+ typeof response.dataBase64 === "string"
1309
+ ) {
1310
+ chunk = Buffer.from(response.dataBase64, "base64");
1311
+ break;
1312
+ }
1313
+ if (response && typeof response === "object" && response.done === true) {
1314
+ chunk = Buffer.alloc(0);
1315
+ break;
1316
+ }
1317
+ if (
1318
+ typeof Atomics?.wait === "function" &&
1319
+ typeof syntheticWaitArray !== "undefined"
1320
+ ) {
1321
+ Atomics.wait(syntheticWaitArray, 0, 0, 10);
1322
+ }
1323
+ }
1324
+ if (!chunk || chunk.length === 0) {
1325
+ return this._writeUint32(nreadPtr, 0);
1326
+ }
1327
+ const written = this._writeToIovs(iovs, iovsLen, chunk);
1328
+ return this._writeUint32(nreadPtr, written);
1329
+ } catch {
1330
+ // Fall back to direct stdin reads when the sync bridge is unavailable
1331
+ // in the standalone runner bootstrap.
1332
+ }
1333
+ }
1334
+ const buffer = Buffer.alloc(totalLength);
1335
+ const directStdinFd =
1336
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1337
+ typeof handle.targetFd === "number"
1338
+ ? handle.targetFd
1339
+ : typeof process?.stdin?.fd === "number"
1340
+ ? process.stdin.fd
1341
+ : 0;
1342
+ const bytesRead = __agentOsFs().readSync(
1343
+ directStdinFd,
1344
+ buffer,
1345
+ 0,
1346
+ totalLength,
1347
+ null,
1348
+ );
1349
+ const written = this._writeToIovs(iovs, iovsLen, buffer.subarray(0, bytesRead));
1350
+ return this._writeUint32(nreadPtr, written);
1351
+ }
1352
+ if (
1353
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1354
+ typeof handle.targetFd === "number"
1355
+ ) {
1356
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
1357
+ const buffer = Buffer.alloc(totalLength);
1358
+ const bytesRead = __agentOsFs().readSync(
1359
+ handle.targetFd,
1360
+ buffer,
1361
+ 0,
1362
+ totalLength,
1363
+ null,
1364
+ );
1365
+ const written = this._writeToIovs(iovs, iovsLen, buffer.subarray(0, bytesRead));
1366
+ return this._writeUint32(nreadPtr, written);
1367
+ }
1368
+ if (entry.kind !== "file") {
1369
+ return __agentOsWasiErrnoBadf;
1370
+ }
1371
+ const totalLength = this._boundedIovLength(iovs, iovsLen);
1372
+ const buffer = Buffer.alloc(totalLength);
1373
+ const position = typeof entry.offset === "number" ? entry.offset : null;
1374
+ const bytesRead = __agentOsFs().readSync(
1375
+ entry.realFd,
1376
+ buffer,
1377
+ 0,
1378
+ totalLength,
1379
+ position,
1380
+ );
1381
+ if (typeof entry.offset === "number") {
1382
+ entry.offset += bytesRead;
1383
+ }
1384
+ const written = this._writeToIovs(iovs, iovsLen, buffer.subarray(0, bytesRead));
1385
+ return this._writeUint32(nreadPtr, written);
1386
+ } catch (error) {
1387
+ return this._mapFsError(error);
1388
+ }
1389
+ }
1390
+
1391
+ _fdClose(fd) {
1392
+ try {
1393
+ const descriptor = Number(fd) >>> 0;
1394
+ const entry = this.fdTable.get(descriptor);
1395
+ if (!entry) {
1396
+ return __agentOsWasiErrnoBadf;
1397
+ }
1398
+ const retainedDelegateRefs = (() => {
1399
+ try {
1400
+ if (typeof globalThis.__agentOsWasiDelegateFdRefCount === "function") {
1401
+ return Number(globalThis.__agentOsWasiDelegateFdRefCount(descriptor)) || 0;
1402
+ }
1403
+ } catch {
1404
+ // Fall through to the default close path.
1405
+ }
1406
+ return 0;
1407
+ })();
1408
+ if (entry.kind === "file" && retainedDelegateRefs <= 0) {
1409
+ __agentOsFs().closeSync(entry.realFd);
1410
+ }
1411
+ if (descriptor > 2 && retainedDelegateRefs <= 0) {
1412
+ this.fdTable.delete(descriptor);
1413
+ }
1414
+ return __agentOsWasiErrnoSuccess;
1415
+ } catch {
1416
+ return __agentOsWasiErrnoFault;
1417
+ }
1418
+ }
1419
+
1420
+ _fdSync(fd) {
1421
+ try {
1422
+ const descriptor = Number(fd) >>> 0;
1423
+ const handle = this._externalFdHandle(descriptor);
1424
+ if (
1425
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1426
+ typeof handle.targetFd === "number"
1427
+ ) {
1428
+ __agentOsFs().fsyncSync(handle.targetFd);
1429
+ return __agentOsWasiErrnoSuccess;
1430
+ }
1431
+ const entry = this.fdTable.get(descriptor);
1432
+ if (!entry || entry.kind !== "file" || typeof entry.realFd !== "number") {
1433
+ return __agentOsWasiErrnoBadf;
1434
+ }
1435
+ __agentOsFs().fsyncSync(entry.realFd);
1436
+ return __agentOsWasiErrnoSuccess;
1437
+ } catch {
1438
+ return __agentOsWasiErrnoFault;
1439
+ }
1440
+ }
1441
+
1442
+ _fdFdstatGet(fd, statPtr) {
1443
+ try {
1444
+ const entry = this._descriptorEntry(fd);
1445
+ if (!entry) {
1446
+ return __agentOsWasiErrnoBadf;
1447
+ }
1448
+ const view = this._memoryView();
1449
+ const offset = Number(statPtr) >>> 0;
1450
+ view.setUint8(offset, this._fdFiletype(entry));
1451
+ view.setUint16(offset + 2, (Number(entry.fdFlags) >>> 0) & 0xffff, true);
1452
+ view.setBigUint64(offset + 8, this._descriptorRightsBase(entry), true);
1453
+ view.setBigUint64(offset + 16, this._descriptorRightsInheriting(entry), true);
1454
+ return __agentOsWasiErrnoSuccess;
1455
+ } catch {
1456
+ return __agentOsWasiErrnoFault;
1457
+ }
1458
+ }
1459
+
1460
+ _fdFdstatSetFlags(fd, flags) {
1461
+ try {
1462
+ const entry = this._descriptorEntry(fd);
1463
+ if (!entry) {
1464
+ return __agentOsWasiErrnoBadf;
1465
+ }
1466
+ entry.fdFlags = (Number(flags) >>> 0) & 0xffff;
1467
+ return __agentOsWasiErrnoSuccess;
1468
+ } catch {
1469
+ return __agentOsWasiErrnoFault;
1470
+ }
1471
+ }
1472
+
1473
+ _fdFilestatGet(fd, statPtr) {
1474
+ try {
1475
+ const entry = this._descriptorEntry(fd);
1476
+ if (!entry) {
1477
+ return __agentOsWasiErrnoBadf;
1478
+ }
1479
+ if (
1480
+ entry.kind === "stdin" ||
1481
+ entry.kind === "stdout" ||
1482
+ entry.kind === "stderr"
1483
+ ) {
1484
+ return this._writeFilestat(statPtr, null, __agentOsWasiFiletypeCharacterDevice);
1485
+ }
1486
+ if (entry.kind === "preopen") {
1487
+ const stats = __agentOsFs().statSync(entry.guestPath);
1488
+ return this._writeFilestat(statPtr, stats, __agentOsWasiFiletypeDirectory);
1489
+ }
1490
+ const stats =
1491
+ typeof entry.realFd === "number"
1492
+ ? __agentOsFs().fstatSync(entry.realFd)
1493
+ : __agentOsFs().statSync(this._descriptorFsPath(entry));
1494
+ return this._writeFilestat(statPtr, stats, this._fdFiletype(entry));
1495
+ } catch (error) {
1496
+ return this._mapFsError(error);
1497
+ }
1498
+ }
1499
+
1500
+ _fdFilestatSetSize(fd, size) {
1501
+ try {
1502
+ const entry = this._descriptorEntry(fd);
1503
+ if (!entry || entry.kind !== "file" || typeof entry.realFd !== "number") {
1504
+ return __agentOsWasiErrnoBadf;
1505
+ }
1506
+ if (entry.readOnly === true) {
1507
+ return __agentOsWasiErrnoRofs;
1508
+ }
1509
+ __agentOsFs().ftruncateSync(entry.realFd, Number(size));
1510
+ return __agentOsWasiErrnoSuccess;
1511
+ } catch (error) {
1512
+ return this._mapFsError(error);
1513
+ }
1514
+ }
1515
+
1516
+ _fdSeek(fd, offset, whence, newOffsetPtr) {
1517
+ try {
1518
+ const entry = this._descriptorEntry(fd);
1519
+ if (!entry || entry.kind !== "file" || typeof entry.realFd !== "number") {
1520
+ return __agentOsWasiErrnoBadf;
1521
+ }
1522
+ const delta = Number(offset);
1523
+ if (!Number.isFinite(delta)) {
1524
+ return __agentOsWasiErrnoInval;
1525
+ }
1526
+ const currentOffset = typeof entry.offset === "number" ? entry.offset : 0;
1527
+ let nextOffset = 0;
1528
+ switch (Number(whence) >>> 0) {
1529
+ case __agentOsWasiWhenceSet:
1530
+ nextOffset = delta;
1531
+ break;
1532
+ case __agentOsWasiWhenceCur:
1533
+ nextOffset = currentOffset + delta;
1534
+ break;
1535
+ case __agentOsWasiWhenceEnd: {
1536
+ const stats = __agentOsFs().fstatSync(entry.realFd);
1537
+ nextOffset = Number(stats?.size ?? 0) + delta;
1538
+ break;
1539
+ }
1540
+ default:
1541
+ return __agentOsWasiErrnoInval;
1542
+ }
1543
+ if (!Number.isFinite(nextOffset) || nextOffset < 0) {
1544
+ return __agentOsWasiErrnoInval;
1545
+ }
1546
+ entry.offset = nextOffset;
1547
+ return this._writeUint64(newOffsetPtr, BigInt(nextOffset));
1548
+ } catch (error) {
1549
+ return this._mapFsError(error);
1550
+ }
1551
+ }
1552
+
1553
+ _fdTell(fd, offsetPtr) {
1554
+ try {
1555
+ const entry = this._descriptorEntry(fd);
1556
+ if (!entry || entry.kind !== "file") {
1557
+ return __agentOsWasiErrnoBadf;
1558
+ }
1559
+ const offset = typeof entry.offset === "number" ? entry.offset : 0;
1560
+ return this._writeUint64(offsetPtr, BigInt(offset));
1561
+ } catch (error) {
1562
+ return this._mapFsError(error);
1563
+ }
1564
+ }
1565
+
1566
+ _fdPrestatGet(fd, prestatPtr) {
1567
+ try {
1568
+ const entry = this._descriptorEntry(fd);
1569
+ if (!entry || entry.kind !== "preopen") {
1570
+ return __agentOsWasiErrnoBadf;
1571
+ }
1572
+ const guestPath = this._descriptorPreopenName(entry);
1573
+ if (typeof guestPath !== "string") {
1574
+ return __agentOsWasiErrnoBadf;
1575
+ }
1576
+ const view = this._memoryView();
1577
+ const offset = Number(prestatPtr) >>> 0;
1578
+ view.setUint8(offset, 0);
1579
+ view.setUint32(offset + 4, Buffer.byteLength(guestPath), true);
1580
+ return __agentOsWasiErrnoSuccess;
1581
+ } catch {
1582
+ return __agentOsWasiErrnoFault;
1583
+ }
1584
+ }
1585
+
1586
+ _fdPrestatDirName(fd, pathPtr, pathLen) {
1587
+ try {
1588
+ const entry = this._descriptorEntry(fd);
1589
+ if (!entry || entry.kind !== "preopen") {
1590
+ return __agentOsWasiErrnoBadf;
1591
+ }
1592
+ const guestPath = this._descriptorPreopenName(entry);
1593
+ if (typeof guestPath !== "string") {
1594
+ return __agentOsWasiErrnoBadf;
1595
+ }
1596
+ const bytes = Buffer.from(guestPath, "utf8");
1597
+ if ((Number(pathLen) >>> 0) < bytes.length) {
1598
+ return __agentOsWasiErrnoFault;
1599
+ }
1600
+ return this._writeBytes(pathPtr, bytes);
1601
+ } catch {
1602
+ return __agentOsWasiErrnoFault;
1603
+ }
1604
+ }
1605
+
1606
+ _fdReaddir(fd, bufPtr, bufLen, cookie, bufUsedPtr) {
1607
+ try {
1608
+ const entry = this._descriptorEntry(fd);
1609
+ const fsPath = this._descriptorDirectoryFsPath(entry);
1610
+ if (
1611
+ !entry ||
1612
+ (entry.kind !== "preopen" && entry.kind !== "directory") ||
1613
+ typeof fsPath !== "string"
1614
+ ) {
1615
+ return __agentOsWasiErrnoBadf;
1616
+ }
1617
+ const dirents = __agentOsFs()
1618
+ .readdirSync(fsPath, { withFileTypes: true })
1619
+ .sort((left, right) => left.name.localeCompare(right.name));
1620
+ const view = this._memoryView();
1621
+ const memory = this._memoryBytes();
1622
+ let offset = Number(bufPtr) >>> 0;
1623
+ const limit = offset + (Number(bufLen) >>> 0);
1624
+ let used = 0;
1625
+ for (let index = Number(cookie) >>> 0; index < dirents.length; index += 1) {
1626
+ const dirent = dirents[index];
1627
+ const nameBytes = Buffer.from(dirent.name, "utf8");
1628
+ const recordLen = 24 + nameBytes.length;
1629
+ if (offset + recordLen > limit) {
1630
+ break;
1631
+ }
1632
+ view.setBigUint64(offset, BigInt(index + 1), true);
1633
+ view.setBigUint64(offset + 8, BigInt(index + 1), true);
1634
+ view.setUint32(offset + 16, nameBytes.length, true);
1635
+ view.setUint8(
1636
+ offset + 20,
1637
+ dirent.isDirectory()
1638
+ ? __agentOsWasiFiletypeDirectory
1639
+ : dirent.isSymbolicLink()
1640
+ ? __agentOsWasiFiletypeSymbolicLink
1641
+ : __agentOsWasiFiletypeRegularFile,
1642
+ );
1643
+ memory.set(nameBytes, offset + 24);
1644
+ offset += recordLen;
1645
+ used += recordLen;
1646
+ }
1647
+ return this._writeUint32(bufUsedPtr, used);
1648
+ } catch (error) {
1649
+ return this._mapFsError(error);
1650
+ }
1651
+ }
1652
+
1653
+ _pathCreateDirectory(fd, pathPtr, pathLen) {
1654
+ try {
1655
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1656
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1657
+ return resolved.error;
1658
+ }
1659
+ if (resolved.readOnly) {
1660
+ return __agentOsWasiErrnoRofs;
1661
+ }
1662
+ __agentOsFs().mkdirSync(this._resolvedFsPath(resolved));
1663
+ return __agentOsWasiErrnoSuccess;
1664
+ } catch (error) {
1665
+ return this._mapFsError(error);
1666
+ }
1667
+ }
1668
+
1669
+ _pathLink(oldFd, _oldFlags, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen) {
1670
+ try {
1671
+ const source = this._resolveDescriptorPath(oldFd, oldPathPtr, oldPathLen);
1672
+ if (source.error !== __agentOsWasiErrnoSuccess) {
1673
+ return source.error;
1674
+ }
1675
+ const destination = this._resolveDescriptorPath(newFd, newPathPtr, newPathLen);
1676
+ if (destination.error !== __agentOsWasiErrnoSuccess) {
1677
+ return destination.error;
1678
+ }
1679
+ if (source.readOnly || destination.readOnly) {
1680
+ return __agentOsWasiErrnoRofs;
1681
+ }
1682
+ __agentOsFs().linkSync(this._resolvedFsPath(source), this._resolvedFsPath(destination));
1683
+ return __agentOsWasiErrnoSuccess;
1684
+ } catch (error) {
1685
+ return this._mapFsError(error);
1686
+ }
1687
+ }
1688
+
1689
+ _pathOpen(fd, _dirflags, pathPtr, pathLen, oflags, rightsBase, rightsInheriting, _fdflags, openedFdPtr) {
1690
+ try {
1691
+ const entry = this._descriptorEntry(fd);
1692
+ if (
1693
+ !entry ||
1694
+ (entry.kind !== "preopen" && entry.kind !== "directory") ||
1695
+ typeof entry.hostPath !== "string"
1696
+ ) {
1697
+ return __agentOsWasiErrnoBadf;
1698
+ }
1699
+ const requestedFlags = Number(oflags) >>> 0;
1700
+ const createOrTruncate =
1701
+ (requestedFlags & __agentOsWasiOpenCreate) !== 0 ||
1702
+ (requestedFlags & __agentOsWasiOpenTruncate) !== 0;
1703
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen, {
1704
+ preferCreateParent: createOrTruncate,
1705
+ });
1706
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1707
+ return resolved.error;
1708
+ }
1709
+ const guestPath = resolved.guestPath;
1710
+ const fsPath = this._resolvedFsPath(resolved);
1711
+ const openDirectory = (requestedFlags & __agentOsWasiOpenDirectory) !== 0;
1712
+ const allowedRightsBase = this._descriptorRightsBase(entry);
1713
+ const allowedRightsInheriting = this._descriptorRightsInheriting(entry);
1714
+ const requestedRightsBase = this._normalizeRights(rightsBase, allowedRightsInheriting);
1715
+ const requestedRightsInheriting = this._normalizeRights(
1716
+ rightsInheriting,
1717
+ allowedRightsInheriting,
1718
+ );
1719
+ if (
1720
+ (requestedRightsBase & ~allowedRightsInheriting) !== 0n ||
1721
+ (requestedRightsInheriting & ~allowedRightsInheriting) !== 0n
1722
+ ) {
1723
+ return __agentOsWasiErrnoAcces;
1724
+ }
1725
+ const requestedWriteAccess =
1726
+ !openDirectory &&
1727
+ (createOrTruncate || this._hasWriteRights(requestedRightsBase));
1728
+ if (
1729
+ requestedWriteAccess &&
1730
+ !this._hasWriteRights(allowedRightsBase)
1731
+ ) {
1732
+ return __agentOsWasiErrnoAcces;
1733
+ }
1734
+ if (requestedWriteAccess && resolved.readOnly) {
1735
+ return __agentOsWasiErrnoRofs;
1736
+ }
1737
+ const fsConstants = __agentOsFs().constants ?? {};
1738
+ let openFlags = requestedWriteAccess
1739
+ ? fsConstants.O_RDWR ?? 2
1740
+ : fsConstants.O_RDONLY ?? 0;
1741
+ if ((requestedFlags & __agentOsWasiOpenCreate) !== 0) {
1742
+ openFlags |= fsConstants.O_CREAT ?? 64;
1743
+ }
1744
+ if ((requestedFlags & __agentOsWasiOpenExclusive) !== 0) {
1745
+ openFlags |= fsConstants.O_EXCL ?? 128;
1746
+ }
1747
+ if ((requestedFlags & __agentOsWasiOpenTruncate) !== 0) {
1748
+ openFlags |= fsConstants.O_TRUNC ?? 512;
1749
+ }
1750
+ if (openDirectory) {
1751
+ openFlags |= fsConstants.O_DIRECTORY ?? 0;
1752
+ }
1753
+ if (createOrTruncate && !openDirectory) {
1754
+ __agentOsFs().statSync(__agentOsPath().dirname(fsPath));
1755
+ } else {
1756
+ __agentOsFs().statSync(fsPath);
1757
+ }
1758
+ const realFd = __agentOsFs().openSync(fsPath, openFlags);
1759
+ const stats =
1760
+ createOrTruncate && !openDirectory
1761
+ ? __agentOsFs().fstatSync(realFd)
1762
+ : __agentOsFs().statSync(fsPath);
1763
+ const openedFd = this.nextFd++;
1764
+ this.fdTable.set(openedFd, {
1765
+ kind: stats.isDirectory() ? "directory" : "file",
1766
+ guestPath,
1767
+ hostPath: fsPath,
1768
+ readOnly: resolved.readOnly === true,
1769
+ realFd,
1770
+ offset: 0,
1771
+ rightsBase: requestedRightsBase & allowedRightsInheriting,
1772
+ rightsInheriting: requestedRightsInheriting & allowedRightsInheriting,
1773
+ fdFlags: (Number(_fdflags) >>> 0) & 0xffff,
1774
+ });
1775
+ return this._writeUint32(openedFdPtr, openedFd);
1776
+ } catch (error) {
1777
+ return this._mapFsError(error);
1778
+ }
1779
+ }
1780
+
1781
+ _pathSymlink(targetPtr, targetLen, fd, pathPtr, pathLen) {
1782
+ try {
1783
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1784
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1785
+ return resolved.error;
1786
+ }
1787
+ if (resolved.readOnly) {
1788
+ return __agentOsWasiErrnoRofs;
1789
+ }
1790
+ const target = this._readString(targetPtr, targetLen);
1791
+ __agentOsFs().symlinkSync(target, this._resolvedFsPath(resolved));
1792
+ return __agentOsWasiErrnoSuccess;
1793
+ } catch (error) {
1794
+ return this._mapFsError(error);
1795
+ }
1796
+ }
1797
+
1798
+ _pathRemoveDirectory(fd, pathPtr, pathLen) {
1799
+ try {
1800
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1801
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1802
+ return resolved.error;
1803
+ }
1804
+ if (resolved.readOnly) {
1805
+ return __agentOsWasiErrnoRofs;
1806
+ }
1807
+ __agentOsFs().rmdirSync(this._resolvedFsPath(resolved));
1808
+ return __agentOsWasiErrnoSuccess;
1809
+ } catch (error) {
1810
+ return this._mapFsError(error);
1811
+ }
1812
+ }
1813
+
1814
+ _pathRename(oldFd, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen) {
1815
+ try {
1816
+ const source = this._resolveDescriptorPath(oldFd, oldPathPtr, oldPathLen);
1817
+ if (source.error !== __agentOsWasiErrnoSuccess) {
1818
+ return source.error;
1819
+ }
1820
+ const destination = this._resolveDescriptorPath(newFd, newPathPtr, newPathLen);
1821
+ if (destination.error !== __agentOsWasiErrnoSuccess) {
1822
+ return destination.error;
1823
+ }
1824
+ if (source.readOnly || destination.readOnly) {
1825
+ return __agentOsWasiErrnoRofs;
1826
+ }
1827
+ __agentOsFs().renameSync(this._resolvedFsPath(source), this._resolvedFsPath(destination));
1828
+ return __agentOsWasiErrnoSuccess;
1829
+ } catch (error) {
1830
+ return this._mapFsError(error);
1831
+ }
1832
+ }
1833
+
1834
+ _pathUnlinkFile(fd, pathPtr, pathLen) {
1835
+ try {
1836
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1837
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1838
+ return resolved.error;
1839
+ }
1840
+ if (resolved.readOnly) {
1841
+ return __agentOsWasiErrnoRofs;
1842
+ }
1843
+ __agentOsFs().unlinkSync(this._resolvedFsPath(resolved));
1844
+ return __agentOsWasiErrnoSuccess;
1845
+ } catch (error) {
1846
+ return this._mapFsError(error);
1847
+ }
1848
+ }
1849
+
1850
+ _pathFilestatGet(fd, flags, pathPtr, pathLen, statPtr) {
1851
+ try {
1852
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1853
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1854
+ return resolved.error;
1855
+ }
1856
+ const follow = (Number(flags) & __agentOsWasiLookupSymlinkFollow) !== 0;
1857
+ const stats = follow
1858
+ ? __agentOsFs().statSync(this._resolvedFsPath(resolved))
1859
+ : __agentOsFs().lstatSync(this._resolvedFsPath(resolved));
1860
+ return this._writeFilestat(statPtr, stats, this._filetypeForStats(stats));
1861
+ } catch (error) {
1862
+ return this._mapFsError(error);
1863
+ }
1864
+ }
1865
+
1866
+ _pathReadlink(fd, pathPtr, pathLen, bufPtr, bufLen, bufUsedPtr) {
1867
+ try {
1868
+ const resolved = this._resolveDescriptorPath(fd, pathPtr, pathLen);
1869
+ if (resolved.error !== __agentOsWasiErrnoSuccess) {
1870
+ return resolved.error;
1871
+ }
1872
+ const bytes = Buffer.from(__agentOsFs().readlinkSync(resolved.guestPath), "utf8");
1873
+ const length = Math.min(bytes.length, Number(bufLen) >>> 0);
1874
+ const writeStatus = this._writeBytes(bufPtr, bytes.subarray(0, length));
1875
+ if (writeStatus !== __agentOsWasiErrnoSuccess) {
1876
+ return writeStatus;
1877
+ }
1878
+ return this._writeUint32(bufUsedPtr, length);
1879
+ } catch (error) {
1880
+ return this._mapFsError(error);
1881
+ }
1882
+ }
1883
+
1884
+ _pollOneoff(inPtr, outPtr, nsubscriptions, neventsPtr) {
1885
+ try {
1886
+ const subscriptionCount = Number(nsubscriptions) >>> 0;
1887
+ if (subscriptionCount === 0) {
1888
+ return this._writeUint32(neventsPtr, 0);
1889
+ }
1890
+
1891
+ const subscriptionSize = 48;
1892
+ const eventSize = 32;
1893
+ const kernelPollIn = 0x0001;
1894
+ const kernelPollOut = 0x0004;
1895
+ const kernelPollErr = 0x0008;
1896
+ const kernelPollHup = 0x0010;
1897
+ const view = this._memoryView();
1898
+ const memory = this._memoryBytes();
1899
+ const syncRpc =
1900
+ typeof globalThis?.__agentOsSyncRpc?.callSync === "function"
1901
+ ? __agentOsWasiSyncRpc()
1902
+ : null;
1903
+ const subscriptions = [];
1904
+ let timeoutMs = null;
1905
+
1906
+ for (let index = 0; index < subscriptionCount; index += 1) {
1907
+ const base = (Number(inPtr) >>> 0) + index * subscriptionSize;
1908
+ const tag = view.getUint8(base + 8);
1909
+ const userdata = memory.slice(base, base + 8);
1910
+ if (tag === 0) {
1911
+ const timeoutNs = view.getBigUint64(base + 24, true);
1912
+ const relativeTimeoutMs = Number(timeoutNs / 1000000n);
1913
+ timeoutMs =
1914
+ timeoutMs == null ? relativeTimeoutMs : Math.min(timeoutMs, relativeTimeoutMs);
1915
+ subscriptions.push({ kind: "clock", userdata });
1916
+ continue;
1917
+ }
1918
+
1919
+ if (tag !== 1 && tag !== 2) {
1920
+ subscriptions.push({ kind: "unsupported", userdata });
1921
+ continue;
1922
+ }
1923
+
1924
+ const fd = view.getUint32(base + 16, true);
1925
+ const descriptor = Number(fd) >>> 0;
1926
+ const handle = this._externalFdHandle(descriptor);
1927
+ const entry = this._descriptorEntry(descriptor);
1928
+ let targetFd = null;
1929
+ if (
1930
+ (handle?.kind === "passthrough" || handle?.kind === "host-passthrough") &&
1931
+ typeof handle.targetFd === "number"
1932
+ ) {
1933
+ targetFd = Number(handle.targetFd) >>> 0;
1934
+ } else if (
1935
+ entry?.kind === "stdin" ||
1936
+ entry?.kind === "stdout" ||
1937
+ entry?.kind === "stderr"
1938
+ ) {
1939
+ targetFd = descriptor;
1940
+ }
1941
+
1942
+ subscriptions.push({
1943
+ kind: tag === 1 ? "fd_read" : "fd_write",
1944
+ fd: descriptor,
1945
+ handle,
1946
+ targetFd,
1947
+ userdata,
1948
+ });
1949
+ }
1950
+
1951
+ const deadline = timeoutMs == null ? null : Date.now() + Math.max(0, timeoutMs);
1952
+ const readyEvents = [];
1953
+
1954
+ while (readyEvents.length === 0) {
1955
+ for (const subscription of subscriptions) {
1956
+ if (subscription.kind === "fd_read" && subscription.handle?.kind === "pipe-read") {
1957
+ const pipe = subscription.handle.pipe;
1958
+ if (
1959
+ pipe &&
1960
+ (pipe.chunks.length > 0 ||
1961
+ (pipe.writeHandleCount === 0 && pipe.producers.size === 0))
1962
+ ) {
1963
+ readyEvents.push({
1964
+ userdata: subscription.userdata,
1965
+ error: __agentOsWasiErrnoSuccess,
1966
+ type: 1,
1967
+ nbytes: pipe.chunks[0]?.length ?? 0,
1968
+ flags: 0,
1969
+ });
1970
+ }
1971
+ continue;
1972
+ }
1973
+
1974
+ if (subscription.kind === "fd_write" && subscription.handle?.kind === "pipe-write") {
1975
+ readyEvents.push({
1976
+ userdata: subscription.userdata,
1977
+ error: __agentOsWasiErrnoSuccess,
1978
+ type: 2,
1979
+ nbytes: 65536,
1980
+ flags: 0,
1981
+ });
1982
+ }
1983
+ }
1984
+
1985
+ if (readyEvents.length > 0) {
1986
+ break;
1987
+ }
1988
+
1989
+ const pollTargets = subscriptions
1990
+ .filter(
1991
+ (subscription) =>
1992
+ (subscription.kind === "fd_read" || subscription.kind === "fd_write") &&
1993
+ typeof subscription.targetFd === "number",
1994
+ )
1995
+ .map((subscription) => ({
1996
+ fd: subscription.targetFd,
1997
+ events: subscription.kind === "fd_read" ? kernelPollIn : kernelPollOut,
1998
+ }));
1999
+ const waitMs =
2000
+ deadline == null ? 10 : Math.max(0, Math.min(10, deadline - Date.now()));
2001
+
2002
+ if (syncRpc && pollTargets.length > 0) {
2003
+ let response = null;
2004
+ try {
2005
+ response = syncRpc.callSync("__kernel_poll", [pollTargets, waitMs]);
2006
+ } catch (error) {
2007
+ __agentOsWasiDebug(
2008
+ \`poll_oneoff __kernel_poll failed: \${
2009
+ error instanceof Error ? error.message : String(error)
2010
+ }\`,
2011
+ );
2012
+ }
2013
+
2014
+ const responseEntries = Array.isArray(response?.fds) ? response.fds : [];
2015
+ for (const subscription of subscriptions) {
2016
+ if (
2017
+ (subscription.kind !== "fd_read" && subscription.kind !== "fd_write") ||
2018
+ typeof subscription.targetFd !== "number"
2019
+ ) {
2020
+ continue;
2021
+ }
2022
+
2023
+ const responseEntry = responseEntries.find(
2024
+ (entry) => (Number(entry?.fd) >>> 0) === subscription.targetFd,
2025
+ );
2026
+ const revents = Number(responseEntry?.revents) >>> 0;
2027
+ const interested =
2028
+ subscription.kind === "fd_read"
2029
+ ? kernelPollIn | kernelPollErr | kernelPollHup
2030
+ : kernelPollOut | kernelPollErr | kernelPollHup;
2031
+ if ((revents & interested) === 0) {
2032
+ continue;
2033
+ }
2034
+
2035
+ readyEvents.push({
2036
+ userdata: subscription.userdata,
2037
+ error: __agentOsWasiErrnoSuccess,
2038
+ type: subscription.kind === "fd_read" ? 1 : 2,
2039
+ nbytes: subscription.kind === "fd_read" ? 1 : 65536,
2040
+ flags: 0,
2041
+ });
2042
+ }
2043
+ }
2044
+
2045
+ if (readyEvents.length > 0) {
2046
+ break;
2047
+ }
2048
+
2049
+ let pumped = false;
2050
+ for (const subscription of subscriptions) {
2051
+ if (subscription.kind === "fd_read" && subscription.handle?.kind === "pipe-read") {
2052
+ pumped = this._pumpPipeProducers(subscription.handle.pipe, 10) || pumped;
2053
+ }
2054
+ }
2055
+
2056
+ if (pumped) {
2057
+ continue;
2058
+ }
2059
+
2060
+ if (deadline != null && Date.now() >= deadline) {
2061
+ break;
2062
+ }
2063
+
2064
+ if (
2065
+ pollTargets.length === 0 &&
2066
+ typeof Atomics?.wait !== "function" &&
2067
+ deadline == null
2068
+ ) {
2069
+ break;
2070
+ }
2071
+
2072
+ if (
2073
+ typeof Atomics?.wait === "function" &&
2074
+ typeof syntheticWaitArray !== "undefined"
2075
+ ) {
2076
+ Atomics.wait(syntheticWaitArray, 0, 0, waitMs);
2077
+ } else if (!syncRpc && pollTargets.length === 0) {
2078
+ break;
2079
+ }
2080
+ }
2081
+
2082
+ if (
2083
+ readyEvents.length === 0 &&
2084
+ subscriptions.some((subscription) => subscription.kind === "clock")
2085
+ ) {
2086
+ const clockSubscription = subscriptions.find(
2087
+ (subscription) => subscription.kind === "clock",
2088
+ );
2089
+ readyEvents.push({
2090
+ userdata: clockSubscription.userdata,
2091
+ error: __agentOsWasiErrnoSuccess,
2092
+ type: 0,
2093
+ nbytes: 0,
2094
+ flags: 0,
2095
+ });
2096
+ }
2097
+
2098
+ for (let index = 0; index < readyEvents.length; index += 1) {
2099
+ const base = (Number(outPtr) >>> 0) + index * eventSize;
2100
+ const event = readyEvents[index];
2101
+ memory.set(event.userdata, base);
2102
+ view.setUint16(base + 8, event.error, true);
2103
+ view.setUint8(base + 10, event.type);
2104
+ view.setBigUint64(base + 16, BigInt(event.nbytes), true);
2105
+ view.setUint16(base + 24, event.flags, true);
2106
+ }
2107
+
2108
+ return this._writeUint32(neventsPtr, readyEvents.length);
2109
+ } catch (error) {
2110
+ __agentOsWasiDebug(
2111
+ \`poll_oneoff failed: \${error instanceof Error ? error.message : String(error)}\`,
2112
+ );
2113
+ return __agentOsWasiErrnoFault;
2114
+ }
2115
+ }
2116
+
2117
+ _randomGet(bufPtr, bufLen) {
2118
+ try {
2119
+ const length = Number(bufLen) >>> 0;
2120
+ const bytes = Buffer.allocUnsafe(length);
2121
+ __agentOsCrypto().randomFillSync(bytes);
2122
+ return this._writeBytes(bufPtr, bytes);
2123
+ } catch {
2124
+ return __agentOsWasiErrnoFault;
2125
+ }
2126
+ }
2127
+
2128
+ _schedYield() {
2129
+ return __agentOsWasiErrnoSuccess;
2130
+ }
2131
+
2132
+ _procExit(code) {
2133
+ if (this.returnOnExit) {
2134
+ const error = new Error(\`wasi exit(\${Number(code) >>> 0})\`);
2135
+ error.__agentOsWasiExit = true;
2136
+ error.code = Number(code) >>> 0;
2137
+ throw error;
2138
+ }
2139
+ process.exit(Number(code) >>> 0);
2140
+ }
2141
+ }
2142
+
2143
+ Object.defineProperty(globalThis, "__agentOsWasiModule", {
2144
+ configurable: true,
2145
+ enumerable: false,
2146
+ value: { WASI },
2147
+ writable: true,
2148
+ });
2149
+ }
2150
+
2151
+ // Re-export the shared runner WASI class as the browser wasi module.
2152
+ module.exports = { WASI: globalThis.__agentOsWasiModule.WASI };
2153
+ module.exports.default = { WASI: globalThis.__agentOsWasiModule.WASI };
2154
+ `;