@finalai/final-agent-provider 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +1 -14
  2. package/dist/modules/integrations.d.mts +0 -1
  3. package/dist/modules/integrations.mjs +0 -2
  4. package/dist/modules/integrations.mjs.map +2 -2
  5. package/dist/modules/sandboxes/computer.d.mts +2 -4
  6. package/dist/modules/sandboxes/computer.mjs +110 -480
  7. package/dist/modules/sandboxes/computer.mjs.map +2 -2
  8. package/dist/modules/sandboxes/computers-api.d.mts +6 -1
  9. package/dist/modules/sandboxes/computers-api.mjs.map +2 -2
  10. package/dist/modules/sandboxes/device-api.d.mts +8 -48
  11. package/dist/modules/sandboxes/device-api.mjs +2 -92
  12. package/dist/modules/sandboxes/device-api.mjs.map +2 -2
  13. package/dist/modules/sandboxes/device.d.mts +1 -1
  14. package/dist/modules/sandboxes/device.mjs.map +2 -2
  15. package/dist/modules/sandboxes/environment.d.mts +4 -0
  16. package/dist/modules/sandboxes/environment.mjs.map +2 -2
  17. package/dist/modules/sandboxes/local.d.mts +2 -1
  18. package/dist/modules/sandboxes/local.mjs +64 -8
  19. package/dist/modules/sandboxes/local.mjs.map +2 -2
  20. package/dist/modules/sandboxes/session.mjs +0 -1
  21. package/dist/modules/sandboxes/session.mjs.map +2 -2
  22. package/package.json +5 -57
  23. package/WORKSPACE-EGRESS.md +0 -184
  24. package/dist/modules/authoring-final-channel.d.mts +0 -3
  25. package/dist/modules/authoring-final-channel.mjs +0 -10
  26. package/dist/modules/authoring-final-channel.mjs.map +0 -7
  27. package/dist/modules/channel-factories.d.mts +0 -40
  28. package/dist/modules/channel-factories.mjs +0 -212
  29. package/dist/modules/channel-factories.mjs.map +0 -7
  30. package/dist/modules/channels/content.d.mts +0 -6
  31. package/dist/modules/channels/content.mjs +0 -31
  32. package/dist/modules/channels/content.mjs.map +0 -7
  33. package/dist/modules/channels/delivery.d.mts +0 -54
  34. package/dist/modules/channels/delivery.mjs +0 -243
  35. package/dist/modules/channels/delivery.mjs.map +0 -7
  36. package/dist/modules/channels/direct-messaging.d.mts +0 -5
  37. package/dist/modules/channels/direct-messaging.mjs +0 -8
  38. package/dist/modules/channels/direct-messaging.mjs.map +0 -7
  39. package/dist/modules/channels/fake-platform.d.mts +0 -36
  40. package/dist/modules/channels/fake-platform.mjs +0 -168
  41. package/dist/modules/channels/fake-platform.mjs.map +0 -7
  42. package/dist/modules/channels/group-messaging.d.mts +0 -5
  43. package/dist/modules/channels/group-messaging.mjs +0 -8
  44. package/dist/modules/channels/group-messaging.mjs.map +0 -7
  45. package/dist/modules/channels/inbound.d.mts +0 -52
  46. package/dist/modules/channels/inbound.mjs +0 -42
  47. package/dist/modules/channels/inbound.mjs.map +0 -7
  48. package/dist/modules/channels/index.d.mts +0 -9
  49. package/dist/modules/channels/index.mjs +0 -10
  50. package/dist/modules/channels/index.mjs.map +0 -7
  51. package/dist/modules/channels/messaging-channel.d.mts +0 -7
  52. package/dist/modules/channels/messaging-channel.mjs +0 -99
  53. package/dist/modules/channels/messaging-channel.mjs.map +0 -7
  54. package/dist/modules/channels/projection.d.mts +0 -36
  55. package/dist/modules/channels/projection.mjs +0 -233
  56. package/dist/modules/channels/projection.mjs.map +0 -7
  57. package/dist/modules/channels/prompt.d.mts +0 -72
  58. package/dist/modules/channels/prompt.mjs +0 -208
  59. package/dist/modules/channels/prompt.mjs.map +0 -7
  60. package/dist/modules/channels/routing.d.mts +0 -5
  61. package/dist/modules/channels/routing.mjs +0 -53
  62. package/dist/modules/channels/routing.mjs.map +0 -7
  63. package/dist/modules/sandboxes/access.d.mts +0 -34
  64. package/dist/modules/sandboxes/access.mjs +0 -15
  65. package/dist/modules/sandboxes/access.mjs.map +0 -7
  66. package/dist/modules/sandboxes/egress-bootstrap.d.mts +0 -3
  67. package/dist/modules/sandboxes/egress-bootstrap.mjs +0 -929
  68. package/dist/modules/sandboxes/egress-bootstrap.mjs.map +0 -7
  69. package/dist/modules/sandboxes/egress.d.mts +0 -94
  70. package/dist/modules/sandboxes/egress.mjs +0 -1561
  71. package/dist/modules/sandboxes/egress.mjs.map +0 -7
@@ -1,10 +1,13 @@
1
1
  import { Capability, FilesAccess, ShellAccess } from "@finalai/agent-protocol";
2
+ import { NetworkPolicy } from "@finalai/agent-provider";
2
3
  import {
3
4
  defineSandboxProvider,
4
5
  encodeSandboxText,
6
+ PLATFORM_ENVIRONMENT_NAMES,
5
7
  platformProcessEnvironment,
6
8
  PortProtocol,
7
9
  readTextFileStream,
10
+ reportPlatformNetworkPolicy,
8
11
  runCollect,
9
12
  SandboxEntryType
10
13
  } from "@finalai/agent-provider/sandbox";
@@ -431,18 +434,48 @@ const createLocalSandbox = async (options) => {
431
434
  };
432
435
  const localEnvironmentSchema = z.strictObject({
433
436
  root: z.string().min(1),
434
- env: z.record(z.string(), z.string()).optional(),
437
+ // The platform's variables (its proxy, its CA) are its own to set.
438
+ env: z.record(z.string(), z.string()).refine(
439
+ (env) => Object.keys(env).every((name) => !PLATFORM_ENVIRONMENT_NAMES.has(name)),
440
+ "env sets a variable the platform owns"
441
+ ).optional(),
435
442
  inheritEnv: z.array(z.string().min(1)).optional()
436
443
  });
437
444
  const localStateSchema = z.object({ version: z.literal(1), root: z.string() });
438
- const handleOf = (sandbox) => ({
445
+ const LOCAL_PLATFORM_DIRECTORY = ".final";
446
+ const platformFileTarget = (root, path) => {
447
+ const paths = node().path;
448
+ const components = path.slice(paths.parse(path).root.length).split(/[\\/]/).filter((component) => component !== "" && component !== ".");
449
+ if (components.length === 0 || components.includes(".."))
450
+ throw new Error(
451
+ `refusing the platform file ${JSON.stringify(path)}: it must name a file without ..`
452
+ );
453
+ return paths.join(root, LOCAL_PLATFORM_DIRECTORY, ...components);
454
+ };
455
+ const relocatedEnvironment = (env, moved) => {
456
+ if (moved == null || moved.size === 0) return env;
457
+ const result = {};
458
+ for (const [name, value] of Object.entries(env)) result[name] = moved.get(value) ?? value;
459
+ return result;
460
+ };
461
+ const handleOf = (sandbox, forget) => ({
439
462
  sandbox,
440
- onSandboxStop: () => sandbox.stop(),
441
- onSandboxDelete: () => sandbox.destroy(),
442
- onRuntimeShutdown: () => sandbox.stop()
463
+ onSandboxStop: () => {
464
+ forget();
465
+ return sandbox.stop();
466
+ },
467
+ onSandboxDelete: () => {
468
+ forget();
469
+ return sandbox.destroy();
470
+ },
471
+ onRuntimeShutdown: () => {
472
+ forget();
473
+ return sandbox.stop();
474
+ }
443
475
  });
444
476
  const createLocalSandboxProvider = () => {
445
477
  const live = /* @__PURE__ */ new Map();
478
+ const relocated = /* @__PURE__ */ new Map();
446
479
  return defineSandboxProvider({
447
480
  name: LOCAL_PROVIDER,
448
481
  environment: (rawOptions) => {
@@ -454,7 +487,10 @@ const createLocalSandboxProvider = () => {
454
487
  id: sandboxId,
455
488
  env: options.env,
456
489
  inheritEnv: options.inheritEnv,
457
- baseEnv: platformProcessEnvironment(ctx, {})
490
+ baseEnv: async () => relocatedEnvironment(
491
+ await platformProcessEnvironment(ctx, {})(),
492
+ relocated.get(sandboxId)
493
+ )
458
494
  });
459
495
  live.set(sandboxId, sandbox);
460
496
  return sandbox;
@@ -466,14 +502,32 @@ const createLocalSandboxProvider = () => {
466
502
  }),
467
503
  artifactKey: async () => `local:${root}`,
468
504
  prepare: async () => ({ version: 1, root }),
469
- create: async () => ({ state: { version: 1, root } }),
505
+ // Commands run on this machine's own network: a policy could not be enforced.
506
+ create: async (_ctx, { setup }) => {
507
+ if (setup?.network != null)
508
+ throw new Error(
509
+ "a local sandbox runs on this machine's network and cannot enforce a network policy; remove the setup's network"
510
+ );
511
+ return { state: { version: 1, root } };
512
+ },
470
513
  // This process is the machine: it runs as long as the sandbox can be reached.
471
514
  awaitRunning: async () => void 0,
472
515
  attach: async (ctx, { state }) => {
473
516
  const existing = live.get(ctx.sandboxId);
474
517
  const fresh = existing == null && await node().fsPromises.stat(root).catch(() => null) == null;
475
518
  const sandbox = existing ?? await open(ctx, ctx.sandboxId);
476
- return { handle: handleOf(sandbox), state, fresh, booted: existing == null };
519
+ await reportPlatformNetworkPolicy(ctx, { mode: NetworkPolicy.AllowAll });
520
+ const moved = /* @__PURE__ */ new Map();
521
+ for (const [path, content] of Object.entries(await ctx.platformFiles?.() ?? {})) {
522
+ const target = platformFileTarget(root, path);
523
+ await sandbox.writeTextFile({ path: target, content });
524
+ moved.set(path, target);
525
+ }
526
+ relocated.set(ctx.sandboxId, moved);
527
+ const forget = () => {
528
+ if (live.get(ctx.sandboxId) === sandbox) live.delete(ctx.sandboxId);
529
+ };
530
+ return { handle: handleOf(sandbox, forget), state, fresh, booted: existing == null };
477
531
  },
478
532
  detach: async (_ctx, { state }) => state,
479
533
  park: async (ctx, { state }) => {
@@ -484,6 +538,7 @@ const createLocalSandboxProvider = () => {
484
538
  delete: async (ctx) => {
485
539
  await live.get(ctx.sandboxId)?.destroy();
486
540
  live.delete(ctx.sandboxId);
541
+ relocated.delete(ctx.sandboxId);
487
542
  }
488
543
  };
489
544
  }
@@ -491,6 +546,7 @@ const createLocalSandboxProvider = () => {
491
546
  };
492
547
  export {
493
548
  LOCAL_INHERITED_ENV,
549
+ LOCAL_PLATFORM_DIRECTORY,
494
550
  LOCAL_PROVIDER,
495
551
  LOCAL_STOP_GRACE_MS,
496
552
  createLocalSandbox,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/local.ts"],
4
- "sourcesContent": ["import { Capability, FilesAccess, ShellAccess } from '@finalai/agent-protocol';\nimport type { JsonValue } from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n encodeSandboxText,\n platformProcessEnvironment,\n PortProtocol,\n readTextFileStream,\n runCollect,\n SandboxEntryType,\n type DirEntryIface,\n type NetworkSandboxSessionIface,\n type SandboxProcessIface,\n type SandboxProcessOptionsIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxResourceContextIface,\n type StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport type { ChildProcess } from 'node:child_process';\nimport type { Readable, Writable } from 'node:stream';\nimport * as z from 'zod';\n\n// A sandbox served from the calling process: files under one directory of\n// this machine and commands run in it, with Node's own fs and child_process.\n// The agents client provides it for any `files` or `shell` capability the\n// caller left out; nothing it does leaves this machine except what the model\n// asks for through the handle. Node only.\n\nexport const LOCAL_PROVIDER = 'local';\n\n// Variables a local command inherits from this process; anything else (API\n// keys, tokens) stays out of the model's shell unless passed in `env`.\nexport const LOCAL_INHERITED_ENV = [\n 'PATH',\n 'HOME',\n 'USER',\n 'LANG',\n 'LC_ALL',\n 'TMPDIR',\n 'TERM',\n 'SHELL',\n];\n\nexport interface LocalSandboxOptionsIface {\n // The directory the sandbox is confined to; created when missing.\n root: string;\n // Plain variables for every command, over the inherited ones.\n env?: Record<string, string>;\n // Names inherited from this process's environment (default LOCAL_INHERITED_ENV).\n inheritEnv?: string[];\n id?: string;\n // Every process's environment from the host, read again for each process.\n baseEnv?: () => Promise<Record<string, string>>;\n}\n\nexport interface LocalSandboxIface extends NetworkSandboxSessionIface {\n readonly root: string;\n}\n\nconst fsError = (code: string, message: string) =>\n Object.assign(new Error(`${code}: ${message}`), { code });\n\nconst errorCode = (error: unknown): string | null => {\n const parsed = z.object({ code: z.string() }).safeParse(error);\n return parsed.success ? parsed.data.code : null;\n};\n\nconst missing = (error: unknown) => {\n const code = errorCode(error);\n return code === 'ENOENT' || code === 'ENOTDIR';\n};\n\nconst signalExitCode = (signal: NodeJS.Signals | null): number => {\n if (signal === 'SIGKILL') return 137;\n if (signal === 'SIGINT') return 130;\n return 143;\n};\n\n// Node's built-ins, read on first use so that importing this module does not\n// tie a browser bundle of the client to Node.\nconst loadNode = () => {\n if (globalThis.process?.getBuiltinModule == null)\n throw new Error('A local sandbox runs only in Node');\n return {\n childProcess: process.getBuiltinModule('node:child_process'),\n fs: process.getBuiltinModule('node:fs'),\n fsPromises: process.getBuiltinModule('node:fs/promises'),\n os: process.getBuiltinModule('node:os'),\n path: process.getBuiltinModule('node:path'),\n streamPromises: process.getBuiltinModule('node:stream/promises'),\n };\n};\nlet loaded: ReturnType<typeof loadNode> | null = null;\nconst node = () => (loaded ??= loadNode());\n\nconst isSignal = (value: string): value is NodeJS.Signals => value in node().os.constants.signals;\n\n// Settles when a writable can take more, or will take nothing more.\nconst drained = (stream: Writable): Promise<void> =>\n new Promise((resolve) => {\n const done = () => {\n stream.off('drain', done);\n stream.off('close', done);\n stream.off('error', done);\n resolve();\n };\n stream.once('drain', done);\n stream.once('close', done);\n stream.once('error', done);\n });\n\n// How much a bridged stream buffers before it stops reading its Node stream.\nconst BRIDGE_HIGH_WATER_BYTES = 64 * 1024;\n\n// A Node stream as a web stream, with backpressure: the Node stream pauses\n// whenever the web stream's queue is full and reads on when its reader pulls.\n// `extra` may push bytes and close the stream from elsewhere.\nconst nodeToWeb = (\n readable: Readable | null,\n extra?: (bridge: { push: (bytes: Uint8Array) => void; close: () => void }) => void,\n): ReadableStream<Uint8Array> => {\n let open = true;\n return new ReadableStream<Uint8Array>(\n {\n start: (controller) => {\n const close = () => {\n if (!open) return;\n open = false;\n controller.close();\n };\n const push = (bytes: Uint8Array) => {\n if (!open) return;\n controller.enqueue(bytes);\n if ((controller.desiredSize ?? 0) <= 0) readable?.pause();\n };\n extra?.({ push, close });\n if (readable == null) {\n close();\n return;\n }\n readable.on('data', (chunk: Buffer) => push(new Uint8Array(chunk)));\n // Reads start when the reader pulls.\n readable.pause();\n readable.once('end', close);\n readable.once('error', (error) => {\n if (!open) return;\n open = false;\n controller.error(error);\n });\n },\n pull: () => {\n readable?.resume();\n },\n cancel: () => {\n open = false;\n readable?.destroy();\n },\n },\n { highWaterMark: BRIDGE_HIGH_WATER_BYTES, size: (chunk) => chunk.byteLength },\n );\n};\n\n// How long stopping waits for commands to end on SIGTERM before SIGKILL.\nexport const LOCAL_STOP_GRACE_MS = 2_000;\n\n// Referenced on purpose: a script that ends with `await sandbox.stop()` stays\n// alive until a stubborn command has been killed.\nconst pause = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));\n\n// Whether `promise` settles within `ms`; the timer is cleared either way.\nconst within = async (promise: Promise<unknown>, ms: number): Promise<boolean> => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise.then(() => true),\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), Math.max(0, ms));\n }),\n ]);\n } finally {\n clearTimeout(timer);\n }\n};\n\n// Symlinks one path may pass through before it is refused as a loop.\nconst MAX_SYMLINKS = 40;\n\n// A command runs in its own process group (POSIX), so that a timeout, a cancel\n// or a stop ends everything it started; a shell's children would otherwise\n// outlive it and hold its output open.\nconst ownGroup = (): boolean => process.platform !== 'win32';\n\nconst signalProcessTree = (child: ChildProcess, signal: NodeJS.Signals): void => {\n if (ownGroup() && child.pid != null) {\n try {\n process.kill(-child.pid, signal);\n return;\n } catch {\n // The group has already exited; signal the child itself.\n }\n }\n child.kill(signal);\n};\n\n// A leading `..` component leaves the root; a name that merely starts with\n// two dots (`..config`) does not.\nconst inside = (root: string, path: string): boolean => {\n const { isAbsolute, relative, sep } = node().path;\n const rel = relative(root, path);\n return rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);\n};\n\nexport const createLocalSandbox = async (\n options: LocalSandboxOptionsIface,\n): Promise<LocalSandboxIface> => {\n const { childProcess, fs, fsPromises, path: paths, streamPromises } = node();\n const root = paths.resolve(options.root);\n await fsPromises.mkdir(root, { recursive: true });\n const realRoot = await fsPromises.realpath(root);\n const id = options.id ?? `local-${crypto.randomUUID()}`;\n const processes = new Set<ChildProcess>();\n // Every process group a command started: a shell's backgrounded children\n // outlive it in its group, and stopping the sandbox ends them too.\n const groups = new Set<number>();\n const groupAlive = (pgid: number): boolean => {\n try {\n process.kill(-pgid, 0);\n return true;\n } catch {\n return false;\n }\n };\n const inherited: Record<string, string> = {};\n for (const name of options.inheritEnv ?? LOCAL_INHERITED_ENV) {\n const value = process.env[name];\n if (value != null) inherited[name] = value;\n }\n\n const resolvePath = (path: string): string =>\n paths.isAbsolute(path) ? paths.resolve(path) : paths.join(root, path);\n\n // The real location of `path` (or of its nearest existing ancestor, for a\n // path about to be created), refused unless it stays under `within`: no `..`\n // and no symlink leads out of the sandbox. A dangling symlink is followed to\n // where it points, since writing through it creates its target.\n const confined = async (path: string, within?: string): Promise<string> => {\n const bounds = within == null ? [realRoot] : [realRoot, await confined(within)];\n let existing = resolvePath(path);\n const rest: string[] = [];\n let links = 0;\n for (;;) {\n const real = await fsPromises.realpath(existing).catch((error: unknown) => {\n if (missing(error)) return null;\n throw error;\n });\n if (real != null) {\n const target = paths.join(real, ...rest.toReversed());\n for (const bound of bounds)\n if (!inside(bound, target)) throw fsError('EACCES', `${path} is outside the sandbox`);\n return target;\n }\n const entry = await fsPromises.lstat(existing).catch((error: unknown) => {\n if (missing(error)) return null;\n throw error;\n });\n if (entry?.isSymbolicLink() === true) {\n links += 1;\n if (links > MAX_SYMLINKS) throw fsError('ELOOP', `${path} has too many symlinks`);\n // Relative to the link's real directory, as the kernel resolves it.\n const directory = await fsPromises.realpath(paths.dirname(existing));\n existing = paths.resolve(directory, await fsPromises.readlink(existing));\n continue;\n }\n const parent = paths.dirname(existing);\n if (parent === existing) throw fsError('ENOENT', `${path} does not exist`);\n rest.push(paths.basename(existing));\n existing = parent;\n }\n };\n\n // The real location of the entry `path` names, its last component not\n // followed: removing a symlink removes the link, not what it points to.\n const confinedEntry = async (path: string): Promise<string> => {\n const logical = resolvePath(path);\n if (logical === root) throw fsError('EPERM', 'refusing to remove the sandbox root');\n return paths.join(await confined(paths.dirname(logical)), paths.basename(logical));\n };\n\n const statOf = async (path: string, within?: string): Promise<StatIface | null> => {\n let target: string;\n try {\n target = await confined(path, within);\n const entry = await fsPromises.stat(target);\n return {\n path: resolvePath(path),\n type: entry.isDirectory()\n ? SandboxEntryType.Directory\n : entry.isFile()\n ? SandboxEntryType.File\n : SandboxEntryType.Other,\n size: entry.isDirectory() ? 0 : entry.size,\n modifiedAt: entry.mtime.toISOString(),\n mode: entry.mode & 0o7777,\n };\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n };\n\n const writeBytes = async (path: string, data: Uint8Array): Promise<void> => {\n const target = await confined(path);\n await fsPromises.mkdir(paths.dirname(target), { recursive: true });\n await fsPromises.writeFile(target, data);\n };\n\n const spawn = async (spawnOptions: SandboxProcessOptionsIface): Promise<SandboxProcessIface> => {\n // A command cancelled before it starts never runs.\n const signal = spawnOptions.abortSignal;\n signal?.throwIfAborted();\n const cwd = await confined(spawnOptions.cwd ?? '.');\n signal?.throwIfAborted();\n const base = await options.baseEnv?.();\n signal?.throwIfAborted();\n const env = { ...inherited, ...options.env, ...base, ...spawnOptions.env };\n const shell = spawnOptions.shell === true;\n const child = childProcess.spawn(\n shell ? [spawnOptions.command, ...(spawnOptions.args ?? [])].join(' ') : spawnOptions.command,\n shell ? [] : (spawnOptions.args ?? []),\n { cwd, env, shell, stdio: ['pipe', 'pipe', 'pipe'], detached: ownGroup() },\n );\n processes.add(child);\n if (ownGroup() && child.pid != null) {\n for (const pgid of groups) if (!groupAlive(pgid)) groups.delete(pgid);\n groups.add(child.pid);\n }\n let timedOut = false;\n // A command that never started reports why on stderr.\n const stderr = nodeToWeb(child.stderr, ({ push, close }) =>\n child.once('error', (error) => {\n push(new TextEncoder().encode(`${error.message}\\n`));\n close();\n }),\n );\n const exited = new Promise<{ exitCode: number }>((settle) => {\n child.once('error', (error) => {\n processes.delete(child);\n settle({ exitCode: errorCode(error) === 'ENOENT' ? 127 : 126 });\n });\n // Exit, not close: output nobody reads holds the pipes (and `close`) open, and the\n // command has ended all the same.\n child.once('exit', (code, signal) => {\n processes.delete(child);\n settle({ exitCode: timedOut ? 124 : (code ?? signalExitCode(signal)) });\n });\n });\n const timer =\n spawnOptions.timeoutMs == null\n ? null\n : setTimeout(() => {\n timedOut = true;\n signalProcessTree(child, 'SIGKILL');\n }, spawnOptions.timeoutMs);\n // A command that ignores SIGTERM is killed once the stop grace period ends.\n let escalation: ReturnType<typeof setTimeout> | null = null;\n const terminate = (signal: NodeJS.Signals) => {\n signalProcessTree(child, signal);\n if (signal !== 'SIGTERM' || escalation != null) return;\n escalation = setTimeout(() => signalProcessTree(child, 'SIGKILL'), LOCAL_STOP_GRACE_MS);\n };\n const onAbort = () => terminate('SIGTERM');\n spawnOptions.abortSignal?.addEventListener('abort', onAbort, { once: true });\n // The deadline, a cancel and the SIGKILL escalation stand until the output closes: a\n // descendant that outlives the command holds it open and is ended with the group.\n const settled = () => {\n if (timer != null) clearTimeout(timer);\n const groupLeft = ownGroup() && child.pid != null && groupAlive(child.pid);\n if (escalation != null && !groupLeft) clearTimeout(escalation);\n spawnOptions.abortSignal?.removeEventListener('abort', onAbort);\n };\n child.once('close', settled);\n child.once('error', settled);\n const stdin = child.stdin;\n stdin?.on('error', () => undefined);\n if (typeof spawnOptions.stdin === 'string') stdin?.end(spawnOptions.stdin);\n else if (spawnOptions.stdin != null) {\n const reader = spawnOptions.stdin.getReader();\n // Reads on only as fast as the command takes its input, and stops when it exits.\n let finished = false;\n void exited.then(() => {\n finished = true;\n void reader.cancel().catch(() => undefined);\n });\n void (async () => {\n for (;;) {\n const next = await reader.read();\n if (next.done || finished || stdin == null || stdin.destroyed) break;\n if (!stdin.write(next.value)) await Promise.race([drained(stdin), exited]);\n }\n stdin?.end();\n })().catch(() => stdin?.destroy());\n }\n return {\n pid: child.pid == null ? null : String(child.pid),\n ref: null,\n stdout: nodeToWeb(child.stdout),\n stderr,\n write: async (data, writeOptions) => {\n if (spawnOptions.stdin != null) throw new Error('stdin was provided at spawn');\n if (stdin == null) throw new Error('the process has no stdin');\n await new Promise<void>((done, fail) =>\n stdin.write(data, (error) => (error == null ? done() : fail(error))),\n );\n if (writeOptions?.end === true) stdin.end();\n },\n wait: () => exited,\n // SIGTERM (killed after the grace period if ignored) and SIGKILL resolve once the\n // command has ended; any other signal (SIGSTOP, SIGCONT, ...) once it is sent.\n kill: async (signal) => {\n const name = signal ?? 'SIGTERM';\n const sent = isSignal(name) ? name : 'SIGTERM';\n terminate(sent);\n if (sent === 'SIGTERM' || sent === 'SIGKILL') await exited;\n },\n };\n };\n\n const sandbox: LocalSandboxIface = {\n id,\n root,\n defaultWorkingDirectory: root,\n ports: [],\n description: `This machine, in ${root}.`,\n readFile: async ({ path, root: within }) => {\n let target: string;\n try {\n target = await confined(path, within);\n const entry = await fsPromises.stat(target);\n if (entry.isDirectory()) throw fsError('EISDIR', `${path} is a directory`);\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n return nodeToWeb(fs.createReadStream(target));\n },\n readBinaryFile: async ({ path }) => {\n try {\n return new Uint8Array(await fsPromises.readFile(await confined(path)));\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n },\n readTextFile: async (readOptions) => {\n const stream = await sandbox.readFile({ path: readOptions.path });\n return stream == null ? null : readTextFileStream(stream, readOptions);\n },\n writeFile: async ({ path, content }) => {\n const target = await confined(path);\n await fsPromises.mkdir(paths.dirname(target), { recursive: true });\n const reader = content.getReader();\n const output = fs.createWriteStream(target);\n await streamPromises.pipeline(\n (async function* () {\n for (;;) {\n const next = await reader.read();\n if (next.done) return;\n yield next.value;\n }\n })(),\n output,\n );\n },\n writeBinaryFile: ({ path, content }) => writeBytes(path, content),\n writeTextFile: ({ path, content, encoding }) =>\n writeBytes(path, encodeSandboxText(content, encoding)),\n spawn,\n run: (runOptions) => runCollect({ spawn }, runOptions),\n stat: ({ path, root: within }) => statOf(path, within),\n readDir: async ({ path, root: within }): Promise<DirEntryIface[]> => {\n const target = await confined(path, within);\n const logical = resolvePath(path);\n const entries = await fsPromises.readdir(target, { withFileTypes: true });\n return Promise.all(\n entries.map(async (entry) => {\n const type = entry.isDirectory()\n ? SandboxEntryType.Directory\n : entry.isFile()\n ? SandboxEntryType.File\n : entry.isSymbolicLink()\n ? SandboxEntryType.Symlink\n : SandboxEntryType.Other;\n const size = entry.isFile()\n ? (await fsPromises.lstat(paths.join(target, entry.name))).size\n : null;\n return { name: entry.name, path: paths.join(logical, entry.name), type, size };\n }),\n );\n },\n resolvePath,\n removePath: async ({ path, recursive, force }) => {\n const target = await confinedEntry(path);\n await fsPromises.rm(target, { recursive: recursive === true, force: force === true });\n },\n getPortEndpoint: async ({ port, protocol }) => ({\n url: `${protocol ?? PortProtocol.Http}://127.0.0.1:${port}`,\n }),\n getPortUrl: async (portOptions) => (await sandbox.getPortEndpoint(portOptions)).url,\n // Stopping ends the commands it started; the directory is the caller's and stays.\n // A command that ignores SIGTERM is killed once the grace period ends.\n stop: async () => {\n const children = [...processes];\n const pgids = new Set(groups);\n groups.clear();\n for (const child of children) if (ownGroup() && child.pid != null) pgids.add(child.pid);\n const closed = Promise.all(\n children.map(\n (child) =>\n new Promise<void>((done) => {\n if (child.exitCode != null || child.signalCode != null) done();\n else child.once('exit', () => done());\n }),\n ),\n );\n const signalAll = (signal: NodeJS.Signals) => {\n for (const child of children) signalProcessTree(child, signal);\n for (const pgid of pgids) {\n try {\n process.kill(-pgid, signal);\n } catch {\n // The group has already exited.\n }\n }\n };\n // Whether every command closed and every group is gone by the deadline.\n const settled = async (deadline: number): Promise<boolean> => {\n if (!(await within(closed, deadline - Date.now()))) return false;\n while ([...pgids].some(groupAlive)) {\n if (Date.now() >= deadline) return false;\n await pause(25);\n }\n return true;\n };\n signalAll('SIGTERM');\n if (await settled(Date.now() + LOCAL_STOP_GRACE_MS)) return;\n signalAll('SIGKILL');\n await settled(Date.now() + LOCAL_STOP_GRACE_MS);\n },\n destroy: () => sandbox.stop(),\n };\n return sandbox;\n};\n\nconst localEnvironmentSchema = z.strictObject({\n root: z.string().min(1),\n env: z.record(z.string(), z.string()).optional(),\n inheritEnv: z.array(z.string().min(1)).optional(),\n});\n\nconst localStateSchema = z.object({ version: z.literal(1), root: z.string() });\n\ntype LocalArtifact = { version: 1; root: string };\ntype LocalState = z.infer<typeof localStateSchema>;\n\nconst handleOf = (sandbox: LocalSandboxIface): SandboxProviderHandleIface<LocalSandboxIface> => ({\n sandbox,\n onSandboxStop: () => sandbox.stop(),\n onSandboxDelete: () => sandbox.destroy(),\n onRuntimeShutdown: () => sandbox.stop(),\n});\n\n// The local sandbox as a provider, for a host that drives sandboxes through\n// the provider lifecycle. Deleting it stops its commands and leaves the\n// directory, which belongs to whoever runs this process.\nexport const createLocalSandboxProvider = (): SandboxProviderIface<\n JsonValue,\n LocalArtifact,\n LocalState,\n LocalSandboxIface\n> => {\n const live = new Map<string, LocalSandboxIface>();\n return defineSandboxProvider<JsonValue, LocalArtifact, LocalState, LocalSandboxIface>({\n name: LOCAL_PROVIDER,\n environment: (rawOptions) => {\n const options = localEnvironmentSchema.parse(rawOptions);\n const root = node().path.resolve(options.root);\n const open = async (ctx: SandboxResourceContextIface, sandboxId: string) => {\n const sandbox = await createLocalSandbox({\n root,\n id: sandboxId,\n env: options.env,\n inheritEnv: options.inheritEnv,\n baseEnv: platformProcessEnvironment(ctx, {}),\n });\n live.set(sandboxId, sandbox);\n return sandbox;\n };\n return {\n capabilities: async () => ({\n [Capability.Files]: FilesAccess.Write,\n [Capability.Shell]: ShellAccess.Execute,\n }),\n artifactKey: async () => `local:${root}`,\n prepare: async () => ({ version: 1, root }),\n create: async () => ({ state: { version: 1, root } }),\n // This process is the machine: it runs as long as the sandbox can be reached.\n awaitRunning: async () => undefined,\n attach: async (ctx, { state }) => {\n const existing = live.get(ctx.sandboxId);\n const fresh =\n existing == null &&\n (await node()\n .fsPromises.stat(root)\n .catch(() => null)) == null;\n const sandbox = existing ?? (await open(ctx, ctx.sandboxId));\n return { handle: handleOf(sandbox), state, fresh, booted: existing == null };\n },\n detach: async (_ctx, { state }) => state,\n park: async (ctx, { state }) => {\n await live.get(ctx.sandboxId)?.stop();\n live.delete(ctx.sandboxId);\n return state;\n },\n delete: async (ctx) => {\n await live.get(ctx.sandboxId)?.destroy();\n live.delete(ctx.sandboxId);\n },\n };\n },\n });\n};\n"],
5
- "mappings": "AAAA,SAAS,YAAY,aAAa,mBAAmB;AAErD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAGP,YAAY,OAAO;AAQZ,MAAM,iBAAiB;AAIvB,MAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAkBA,MAAM,UAAU,CAAC,MAAc,YAC7B,OAAO,OAAO,IAAI,MAAM,GAAG,IAAI,KAAK,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;AAE1D,MAAM,YAAY,CAAC,UAAkC;AACnD,QAAM,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,KAAK;AAC7D,SAAO,OAAO,UAAU,OAAO,KAAK,OAAO;AAC7C;AAEA,MAAM,UAAU,CAAC,UAAmB;AAClC,QAAM,OAAO,UAAU,KAAK;AAC5B,SAAO,SAAS,YAAY,SAAS;AACvC;AAEA,MAAM,iBAAiB,CAAC,WAA0C;AAChE,MAAI,WAAW,UAAW,QAAO;AACjC,MAAI,WAAW,SAAU,QAAO;AAChC,SAAO;AACT;AAIA,MAAM,WAAW,MAAM;AACrB,MAAI,WAAW,SAAS,oBAAoB;AAC1C,UAAM,IAAI,MAAM,mCAAmC;AACrD,SAAO;AAAA,IACL,cAAc,QAAQ,iBAAiB,oBAAoB;AAAA,IAC3D,IAAI,QAAQ,iBAAiB,SAAS;AAAA,IACtC,YAAY,QAAQ,iBAAiB,kBAAkB;AAAA,IACvD,IAAI,QAAQ,iBAAiB,SAAS;AAAA,IACtC,MAAM,QAAQ,iBAAiB,WAAW;AAAA,IAC1C,gBAAgB,QAAQ,iBAAiB,sBAAsB;AAAA,EACjE;AACF;AACA,IAAI,SAA6C;AACjD,MAAM,OAAO,MAAO,WAAW,SAAS;AAExC,MAAM,WAAW,CAAC,UAA2C,SAAS,KAAK,EAAE,GAAG,UAAU;AAG1F,MAAM,UAAU,CAAC,WACf,IAAI,QAAQ,CAAC,YAAY;AACvB,QAAM,OAAO,MAAM;AACjB,WAAO,IAAI,SAAS,IAAI;AACxB,WAAO,IAAI,SAAS,IAAI;AACxB,WAAO,IAAI,SAAS,IAAI;AACxB,YAAQ;AAAA,EACV;AACA,SAAO,KAAK,SAAS,IAAI;AACzB,SAAO,KAAK,SAAS,IAAI;AACzB,SAAO,KAAK,SAAS,IAAI;AAC3B,CAAC;AAGH,MAAM,0BAA0B,KAAK;AAKrC,MAAM,YAAY,CAChB,UACA,UAC+B;AAC/B,MAAI,OAAO;AACX,SAAO,IAAI;AAAA,IACT;AAAA,MACE,OAAO,CAAC,eAAe;AACrB,cAAM,QAAQ,MAAM;AAClB,cAAI,CAAC,KAAM;AACX,iBAAO;AACP,qBAAW,MAAM;AAAA,QACnB;AACA,cAAM,OAAO,CAAC,UAAsB;AAClC,cAAI,CAAC,KAAM;AACX,qBAAW,QAAQ,KAAK;AACxB,eAAK,WAAW,eAAe,MAAM,EAAG,WAAU,MAAM;AAAA,QAC1D;AACA,gBAAQ,EAAE,MAAM,MAAM,CAAC;AACvB,YAAI,YAAY,MAAM;AACpB,gBAAM;AACN;AAAA,QACF;AACA,iBAAS,GAAG,QAAQ,CAAC,UAAkB,KAAK,IAAI,WAAW,KAAK,CAAC,CAAC;AAElE,iBAAS,MAAM;AACf,iBAAS,KAAK,OAAO,KAAK;AAC1B,iBAAS,KAAK,SAAS,CAAC,UAAU;AAChC,cAAI,CAAC,KAAM;AACX,iBAAO;AACP,qBAAW,MAAM,KAAK;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,MACA,MAAM,MAAM;AACV,kBAAU,OAAO;AAAA,MACnB;AAAA,MACA,QAAQ,MAAM;AACZ,eAAO;AACP,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,IACA,EAAE,eAAe,yBAAyB,MAAM,CAAC,UAAU,MAAM,WAAW;AAAA,EAC9E;AACF;AAGO,MAAM,sBAAsB;AAInC,MAAM,QAAQ,CAAC,OACb,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC;AAG/D,MAAM,SAAS,OAAO,SAA2B,OAAiC;AAChF,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;AAAA,MACxB,QAAQ,KAAK,MAAM,IAAI;AAAA,MACvB,IAAI,QAAiB,CAAC,YAAY;AAChC,gBAAQ,WAAW,MAAM,QAAQ,KAAK,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC;AAAA,MAC1D,CAAC;AAAA,IACH,CAAC;AAAA,EACH,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAGA,MAAM,eAAe;AAKrB,MAAM,WAAW,MAAe,QAAQ,aAAa;AAErD,MAAM,oBAAoB,CAAC,OAAqB,WAAiC;AAC/E,MAAI,SAAS,KAAK,MAAM,OAAO,MAAM;AACnC,QAAI;AACF,cAAQ,KAAK,CAAC,MAAM,KAAK,MAAM;AAC/B;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,KAAK,MAAM;AACnB;AAIA,MAAM,SAAS,CAAC,MAAc,SAA0B;AACtD,QAAM,EAAE,YAAY,UAAU,IAAI,IAAI,KAAK,EAAE;AAC7C,QAAM,MAAM,SAAS,MAAM,IAAI;AAC/B,SAAO,QAAQ,QAAQ,CAAC,IAAI,WAAW,KAAK,GAAG,EAAE,KAAK,CAAC,WAAW,GAAG;AACvE;AAEO,MAAM,qBAAqB,OAChC,YAC+B;AAC/B,QAAM,EAAE,cAAc,IAAI,YAAY,MAAM,OAAO,eAAe,IAAI,KAAK;AAC3E,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;AACvC,QAAM,WAAW,MAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AAChD,QAAM,WAAW,MAAM,WAAW,SAAS,IAAI;AAC/C,QAAM,KAAK,QAAQ,MAAM,SAAS,OAAO,WAAW,CAAC;AACrD,QAAM,YAAY,oBAAI,IAAkB;AAGxC,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,aAAa,CAAC,SAA0B;AAC5C,QAAI;AACF,cAAQ,KAAK,CAAC,MAAM,CAAC;AACrB,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,YAAoC,CAAC;AAC3C,aAAW,QAAQ,QAAQ,cAAc,qBAAqB;AAC5D,UAAM,QAAQ,QAAQ,IAAI,IAAI;AAC9B,QAAI,SAAS,KAAM,WAAU,IAAI,IAAI;AAAA,EACvC;AAEA,QAAM,cAAc,CAAC,SACnB,MAAM,WAAW,IAAI,IAAI,MAAM,QAAQ,IAAI,IAAI,MAAM,KAAK,MAAM,IAAI;AAMtE,QAAM,WAAW,OAAO,MAAcA,YAAqC;AACzE,UAAM,SAASA,WAAU,OAAO,CAAC,QAAQ,IAAI,CAAC,UAAU,MAAM,SAASA,OAAM,CAAC;AAC9E,QAAI,WAAW,YAAY,IAAI;AAC/B,UAAM,OAAiB,CAAC;AACxB,QAAI,QAAQ;AACZ,eAAS;AACP,YAAM,OAAO,MAAM,WAAW,SAAS,QAAQ,EAAE,MAAM,CAAC,UAAmB;AACzE,YAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,cAAM;AAAA,MACR,CAAC;AACD,UAAI,QAAQ,MAAM;AAChB,cAAM,SAAS,MAAM,KAAK,MAAM,GAAG,KAAK,WAAW,CAAC;AACpD,mBAAW,SAAS;AAClB,cAAI,CAAC,OAAO,OAAO,MAAM,EAAG,OAAM,QAAQ,UAAU,GAAG,IAAI,yBAAyB;AACtF,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,MAAM,WAAW,MAAM,QAAQ,EAAE,MAAM,CAAC,UAAmB;AACvE,YAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,cAAM;AAAA,MACR,CAAC;AACD,UAAI,OAAO,eAAe,MAAM,MAAM;AACpC,iBAAS;AACT,YAAI,QAAQ,aAAc,OAAM,QAAQ,SAAS,GAAG,IAAI,wBAAwB;AAEhF,cAAM,YAAY,MAAM,WAAW,SAAS,MAAM,QAAQ,QAAQ,CAAC;AACnE,mBAAW,MAAM,QAAQ,WAAW,MAAM,WAAW,SAAS,QAAQ,CAAC;AACvE;AAAA,MACF;AACA,YAAM,SAAS,MAAM,QAAQ,QAAQ;AACrC,UAAI,WAAW,SAAU,OAAM,QAAQ,UAAU,GAAG,IAAI,iBAAiB;AACzE,WAAK,KAAK,MAAM,SAAS,QAAQ,CAAC;AAClC,iBAAW;AAAA,IACb;AAAA,EACF;AAIA,QAAM,gBAAgB,OAAO,SAAkC;AAC7D,UAAM,UAAU,YAAY,IAAI;AAChC,QAAI,YAAY,KAAM,OAAM,QAAQ,SAAS,qCAAqC;AAClF,WAAO,MAAM,KAAK,MAAM,SAAS,MAAM,QAAQ,OAAO,CAAC,GAAG,MAAM,SAAS,OAAO,CAAC;AAAA,EACnF;AAEA,QAAM,SAAS,OAAO,MAAcA,YAA+C;AACjF,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,SAAS,MAAMA,OAAM;AACpC,YAAM,QAAQ,MAAM,WAAW,KAAK,MAAM;AAC1C,aAAO;AAAA,QACL,MAAM,YAAY,IAAI;AAAA,QACtB,MAAM,MAAM,YAAY,IACpB,iBAAiB,YACjB,MAAM,OAAO,IACX,iBAAiB,OACjB,iBAAiB;AAAA,QACvB,MAAM,MAAM,YAAY,IAAI,IAAI,MAAM;AAAA,QACtC,YAAY,MAAM,MAAM,YAAY;AAAA,QACpC,MAAM,MAAM,OAAO;AAAA,MACrB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,aAAa,OAAO,MAAc,SAAoC;AAC1E,UAAM,SAAS,MAAM,SAAS,IAAI;AAClC,UAAM,WAAW,MAAM,MAAM,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AACjE,UAAM,WAAW,UAAU,QAAQ,IAAI;AAAA,EACzC;AAEA,QAAM,QAAQ,OAAO,iBAA2E;AAE9F,UAAM,SAAS,aAAa;AAC5B,YAAQ,eAAe;AACvB,UAAM,MAAM,MAAM,SAAS,aAAa,OAAO,GAAG;AAClD,YAAQ,eAAe;AACvB,UAAM,OAAO,MAAM,QAAQ,UAAU;AACrC,YAAQ,eAAe;AACvB,UAAM,MAAM,EAAE,GAAG,WAAW,GAAG,QAAQ,KAAK,GAAG,MAAM,GAAG,aAAa,IAAI;AACzE,UAAM,QAAQ,aAAa,UAAU;AACrC,UAAM,QAAQ,aAAa;AAAA,MACzB,QAAQ,CAAC,aAAa,SAAS,GAAI,aAAa,QAAQ,CAAC,CAAE,EAAE,KAAK,GAAG,IAAI,aAAa;AAAA,MACtF,QAAQ,CAAC,IAAK,aAAa,QAAQ,CAAC;AAAA,MACpC,EAAE,KAAK,KAAK,OAAO,OAAO,CAAC,QAAQ,QAAQ,MAAM,GAAG,UAAU,SAAS,EAAE;AAAA,IAC3E;AACA,cAAU,IAAI,KAAK;AACnB,QAAI,SAAS,KAAK,MAAM,OAAO,MAAM;AACnC,iBAAW,QAAQ,OAAQ,KAAI,CAAC,WAAW,IAAI,EAAG,QAAO,OAAO,IAAI;AACpE,aAAO,IAAI,MAAM,GAAG;AAAA,IACtB;AACA,QAAI,WAAW;AAEf,UAAM,SAAS;AAAA,MAAU,MAAM;AAAA,MAAQ,CAAC,EAAE,MAAM,MAAM,MACpD,MAAM,KAAK,SAAS,CAAC,UAAU;AAC7B,aAAK,IAAI,YAAY,EAAE,OAAO,GAAG,MAAM,OAAO;AAAA,CAAI,CAAC;AACnD,cAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM,SAAS,IAAI,QAA8B,CAAC,WAAW;AAC3D,YAAM,KAAK,SAAS,CAAC,UAAU;AAC7B,kBAAU,OAAO,KAAK;AACtB,eAAO,EAAE,UAAU,UAAU,KAAK,MAAM,WAAW,MAAM,IAAI,CAAC;AAAA,MAChE,CAAC;AAGD,YAAM,KAAK,QAAQ,CAAC,MAAMC,YAAW;AACnC,kBAAU,OAAO,KAAK;AACtB,eAAO,EAAE,UAAU,WAAW,MAAO,QAAQ,eAAeA,OAAM,EAAG,CAAC;AAAA,MACxE,CAAC;AAAA,IACH,CAAC;AACD,UAAM,QACJ,aAAa,aAAa,OACtB,OACA,WAAW,MAAM;AACf,iBAAW;AACX,wBAAkB,OAAO,SAAS;AAAA,IACpC,GAAG,aAAa,SAAS;AAE/B,QAAI,aAAmD;AACvD,UAAM,YAAY,CAACA,YAA2B;AAC5C,wBAAkB,OAAOA,OAAM;AAC/B,UAAIA,YAAW,aAAa,cAAc,KAAM;AAChD,mBAAa,WAAW,MAAM,kBAAkB,OAAO,SAAS,GAAG,mBAAmB;AAAA,IACxF;AACA,UAAM,UAAU,MAAM,UAAU,SAAS;AACzC,iBAAa,aAAa,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAG3E,UAAM,UAAU,MAAM;AACpB,UAAI,SAAS,KAAM,cAAa,KAAK;AACrC,YAAM,YAAY,SAAS,KAAK,MAAM,OAAO,QAAQ,WAAW,MAAM,GAAG;AACzE,UAAI,cAAc,QAAQ,CAAC,UAAW,cAAa,UAAU;AAC7D,mBAAa,aAAa,oBAAoB,SAAS,OAAO;AAAA,IAChE;AACA,UAAM,KAAK,SAAS,OAAO;AAC3B,UAAM,KAAK,SAAS,OAAO;AAC3B,UAAM,QAAQ,MAAM;AACpB,WAAO,GAAG,SAAS,MAAM,MAAS;AAClC,QAAI,OAAO,aAAa,UAAU,SAAU,QAAO,IAAI,aAAa,KAAK;AAAA,aAChE,aAAa,SAAS,MAAM;AACnC,YAAM,SAAS,aAAa,MAAM,UAAU;AAE5C,UAAI,WAAW;AACf,WAAK,OAAO,KAAK,MAAM;AACrB,mBAAW;AACX,aAAK,OAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,MAC5C,CAAC;AACD,YAAM,YAAY;AAChB,mBAAS;AACP,gBAAM,OAAO,MAAM,OAAO,KAAK;AAC/B,cAAI,KAAK,QAAQ,YAAY,SAAS,QAAQ,MAAM,UAAW;AAC/D,cAAI,CAAC,MAAM,MAAM,KAAK,KAAK,EAAG,OAAM,QAAQ,KAAK,CAAC,QAAQ,KAAK,GAAG,MAAM,CAAC;AAAA,QAC3E;AACA,eAAO,IAAI;AAAA,MACb,GAAG,EAAE,MAAM,MAAM,OAAO,QAAQ,CAAC;AAAA,IACnC;AACA,WAAO;AAAA,MACL,KAAK,MAAM,OAAO,OAAO,OAAO,OAAO,MAAM,GAAG;AAAA,MAChD,KAAK;AAAA,MACL,QAAQ,UAAU,MAAM,MAAM;AAAA,MAC9B;AAAA,MACA,OAAO,OAAO,MAAM,iBAAiB;AACnC,YAAI,aAAa,SAAS,KAAM,OAAM,IAAI,MAAM,6BAA6B;AAC7E,YAAI,SAAS,KAAM,OAAM,IAAI,MAAM,0BAA0B;AAC7D,cAAM,IAAI;AAAA,UAAc,CAAC,MAAM,SAC7B,MAAM,MAAM,MAAM,CAAC,UAAW,SAAS,OAAO,KAAK,IAAI,KAAK,KAAK,CAAE;AAAA,QACrE;AACA,YAAI,cAAc,QAAQ,KAAM,OAAM,IAAI;AAAA,MAC5C;AAAA,MACA,MAAM,MAAM;AAAA;AAAA;AAAA,MAGZ,MAAM,OAAOA,YAAW;AACtB,cAAM,OAAOA,WAAU;AACvB,cAAM,OAAO,SAAS,IAAI,IAAI,OAAO;AACrC,kBAAU,IAAI;AACd,YAAI,SAAS,aAAa,SAAS,UAAW,OAAM;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAA6B;AAAA,IACjC;AAAA,IACA;AAAA,IACA,yBAAyB;AAAA,IACzB,OAAO,CAAC;AAAA,IACR,aAAa,oBAAoB,IAAI;AAAA,IACrC,UAAU,OAAO,EAAE,MAAM,MAAMD,QAAO,MAAM;AAC1C,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,SAAS,MAAMA,OAAM;AACpC,cAAM,QAAQ,MAAM,WAAW,KAAK,MAAM;AAC1C,YAAI,MAAM,YAAY,EAAG,OAAM,QAAQ,UAAU,GAAG,IAAI,iBAAiB;AAAA,MAC3E,SAAS,OAAO;AACd,YAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,cAAM;AAAA,MACR;AACA,aAAO,UAAU,GAAG,iBAAiB,MAAM,CAAC;AAAA,IAC9C;AAAA,IACA,gBAAgB,OAAO,EAAE,KAAK,MAAM;AAClC,UAAI;AACF,eAAO,IAAI,WAAW,MAAM,WAAW,SAAS,MAAM,SAAS,IAAI,CAAC,CAAC;AAAA,MACvE,SAAS,OAAO;AACd,YAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,cAAc,OAAO,gBAAgB;AACnC,YAAM,SAAS,MAAM,QAAQ,SAAS,EAAE,MAAM,YAAY,KAAK,CAAC;AAChE,aAAO,UAAU,OAAO,OAAO,mBAAmB,QAAQ,WAAW;AAAA,IACvE;AAAA,IACA,WAAW,OAAO,EAAE,MAAM,QAAQ,MAAM;AACtC,YAAM,SAAS,MAAM,SAAS,IAAI;AAClC,YAAM,WAAW,MAAM,MAAM,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AACjE,YAAM,SAAS,QAAQ,UAAU;AACjC,YAAM,SAAS,GAAG,kBAAkB,MAAM;AAC1C,YAAM,eAAe;AAAA,SAClB,mBAAmB;AAClB,qBAAS;AACP,kBAAM,OAAO,MAAM,OAAO,KAAK;AAC/B,gBAAI,KAAK,KAAM;AACf,kBAAM,KAAK;AAAA,UACb;AAAA,QACF,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,IACA,iBAAiB,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,MAAM,OAAO;AAAA,IAChE,eAAe,CAAC,EAAE,MAAM,SAAS,SAAS,MACxC,WAAW,MAAM,kBAAkB,SAAS,QAAQ,CAAC;AAAA,IACvD;AAAA,IACA,KAAK,CAAC,eAAe,WAAW,EAAE,MAAM,GAAG,UAAU;AAAA,IACrD,MAAM,CAAC,EAAE,MAAM,MAAMA,QAAO,MAAM,OAAO,MAAMA,OAAM;AAAA,IACrD,SAAS,OAAO,EAAE,MAAM,MAAMA,QAAO,MAAgC;AACnE,YAAM,SAAS,MAAM,SAAS,MAAMA,OAAM;AAC1C,YAAM,UAAU,YAAY,IAAI;AAChC,YAAM,UAAU,MAAM,WAAW,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AACxE,aAAO,QAAQ;AAAA,QACb,QAAQ,IAAI,OAAO,UAAU;AAC3B,gBAAM,OAAO,MAAM,YAAY,IAC3B,iBAAiB,YACjB,MAAM,OAAO,IACX,iBAAiB,OACjB,MAAM,eAAe,IACnB,iBAAiB,UACjB,iBAAiB;AACzB,gBAAM,OAAO,MAAM,OAAO,KACrB,MAAM,WAAW,MAAM,MAAM,KAAK,QAAQ,MAAM,IAAI,CAAC,GAAG,OACzD;AACJ,iBAAO,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,KAAK;AAAA,QAC/E,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,IACA,YAAY,OAAO,EAAE,MAAM,WAAW,MAAM,MAAM;AAChD,YAAM,SAAS,MAAM,cAAc,IAAI;AACvC,YAAM,WAAW,GAAG,QAAQ,EAAE,WAAW,cAAc,MAAM,OAAO,UAAU,KAAK,CAAC;AAAA,IACtF;AAAA,IACA,iBAAiB,OAAO,EAAE,MAAM,SAAS,OAAO;AAAA,MAC9C,KAAK,GAAG,YAAY,aAAa,IAAI,gBAAgB,IAAI;AAAA,IAC3D;AAAA,IACA,YAAY,OAAO,iBAAiB,MAAM,QAAQ,gBAAgB,WAAW,GAAG;AAAA;AAAA;AAAA,IAGhF,MAAM,YAAY;AAChB,YAAM,WAAW,CAAC,GAAG,SAAS;AAC9B,YAAM,QAAQ,IAAI,IAAI,MAAM;AAC5B,aAAO,MAAM;AACb,iBAAW,SAAS,SAAU,KAAI,SAAS,KAAK,MAAM,OAAO,KAAM,OAAM,IAAI,MAAM,GAAG;AACtF,YAAM,SAAS,QAAQ;AAAA,QACrB,SAAS;AAAA,UACP,CAAC,UACC,IAAI,QAAc,CAAC,SAAS;AAC1B,gBAAI,MAAM,YAAY,QAAQ,MAAM,cAAc,KAAM,MAAK;AAAA,gBACxD,OAAM,KAAK,QAAQ,MAAM,KAAK,CAAC;AAAA,UACtC,CAAC;AAAA,QACL;AAAA,MACF;AACA,YAAM,YAAY,CAAC,WAA2B;AAC5C,mBAAW,SAAS,SAAU,mBAAkB,OAAO,MAAM;AAC7D,mBAAW,QAAQ,OAAO;AACxB,cAAI;AACF,oBAAQ,KAAK,CAAC,MAAM,MAAM;AAAA,UAC5B,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAEA,YAAM,UAAU,OAAO,aAAuC;AAC5D,YAAI,CAAE,MAAM,OAAO,QAAQ,WAAW,KAAK,IAAI,CAAC,EAAI,QAAO;AAC3D,eAAO,CAAC,GAAG,KAAK,EAAE,KAAK,UAAU,GAAG;AAClC,cAAI,KAAK,IAAI,KAAK,SAAU,QAAO;AACnC,gBAAM,MAAM,EAAE;AAAA,QAChB;AACA,eAAO;AAAA,MACT;AACA,gBAAU,SAAS;AACnB,UAAI,MAAM,QAAQ,KAAK,IAAI,IAAI,mBAAmB,EAAG;AACrD,gBAAU,SAAS;AACnB,YAAM,QAAQ,KAAK,IAAI,IAAI,mBAAmB;AAAA,IAChD;AAAA,IACA,SAAS,MAAM,QAAQ,KAAK;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,MAAM,yBAAyB,EAAE,aAAa;AAAA,EAC5C,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC/C,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAClD,CAAC;AAED,MAAM,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC;AAK7E,MAAM,WAAW,CAAC,aAA+E;AAAA,EAC/F;AAAA,EACA,eAAe,MAAM,QAAQ,KAAK;AAAA,EAClC,iBAAiB,MAAM,QAAQ,QAAQ;AAAA,EACvC,mBAAmB,MAAM,QAAQ,KAAK;AACxC;AAKO,MAAM,6BAA6B,MAKrC;AACH,QAAM,OAAO,oBAAI,IAA+B;AAChD,SAAO,sBAA+E;AAAA,IACpF,MAAM;AAAA,IACN,aAAa,CAAC,eAAe;AAC3B,YAAM,UAAU,uBAAuB,MAAM,UAAU;AACvD,YAAM,OAAO,KAAK,EAAE,KAAK,QAAQ,QAAQ,IAAI;AAC7C,YAAM,OAAO,OAAO,KAAkC,cAAsB;AAC1E,cAAM,UAAU,MAAM,mBAAmB;AAAA,UACvC;AAAA,UACA,IAAI;AAAA,UACJ,KAAK,QAAQ;AAAA,UACb,YAAY,QAAQ;AAAA,UACpB,SAAS,2BAA2B,KAAK,CAAC,CAAC;AAAA,QAC7C,CAAC;AACD,aAAK,IAAI,WAAW,OAAO;AAC3B,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,cAAc,aAAa;AAAA,UACzB,CAAC,WAAW,KAAK,GAAG,YAAY;AAAA,UAChC,CAAC,WAAW,KAAK,GAAG,YAAY;AAAA,QAClC;AAAA,QACA,aAAa,YAAY,SAAS,IAAI;AAAA,QACtC,SAAS,aAAa,EAAE,SAAS,GAAG,KAAK;AAAA,QACzC,QAAQ,aAAa,EAAE,OAAO,EAAE,SAAS,GAAG,KAAK,EAAE;AAAA;AAAA,QAEnD,cAAc,YAAY;AAAA,QAC1B,QAAQ,OAAO,KAAK,EAAE,MAAM,MAAM;AAChC,gBAAM,WAAW,KAAK,IAAI,IAAI,SAAS;AACvC,gBAAM,QACJ,YAAY,QACX,MAAM,KAAK,EACT,WAAW,KAAK,IAAI,EACpB,MAAM,MAAM,IAAI,KAAM;AAC3B,gBAAM,UAAU,YAAa,MAAM,KAAK,KAAK,IAAI,SAAS;AAC1D,iBAAO,EAAE,QAAQ,SAAS,OAAO,GAAG,OAAO,OAAO,QAAQ,YAAY,KAAK;AAAA,QAC7E;AAAA,QACA,QAAQ,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,QACnC,MAAM,OAAO,KAAK,EAAE,MAAM,MAAM;AAC9B,gBAAM,KAAK,IAAI,IAAI,SAAS,GAAG,KAAK;AACpC,eAAK,OAAO,IAAI,SAAS;AACzB,iBAAO;AAAA,QACT;AAAA,QACA,QAAQ,OAAO,QAAQ;AACrB,gBAAM,KAAK,IAAI,IAAI,SAAS,GAAG,QAAQ;AACvC,eAAK,OAAO,IAAI,SAAS;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
4
+ "sourcesContent": ["import { Capability, FilesAccess, ShellAccess } from '@finalai/agent-protocol';\nimport { NetworkPolicy, type JsonValue } from '@finalai/agent-provider';\nimport {\n defineSandboxProvider,\n encodeSandboxText,\n PLATFORM_ENVIRONMENT_NAMES,\n platformProcessEnvironment,\n PortProtocol,\n readTextFileStream,\n reportPlatformNetworkPolicy,\n runCollect,\n SandboxEntryType,\n type DirEntryIface,\n type NetworkSandboxSessionIface,\n type SandboxProcessIface,\n type SandboxProcessOptionsIface,\n type SandboxProviderHandleIface,\n type SandboxProviderIface,\n type SandboxResourceContextIface,\n type StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport type { ChildProcess } from 'node:child_process';\nimport type { Readable, Writable } from 'node:stream';\nimport * as z from 'zod';\n\n// A sandbox served from the calling process: files under one directory of\n// this machine and commands run in it, with Node's own fs and child_process.\n// The agents client provides it for any `files` or `shell` capability the\n// caller left out; nothing it does leaves this machine except what the model\n// asks for through the handle. Node only.\n\nexport const LOCAL_PROVIDER = 'local';\n\n// Variables a local command inherits from this process; anything else (API\n// keys, tokens) stays out of the model's shell unless passed in `env`.\nexport const LOCAL_INHERITED_ENV = [\n 'PATH',\n 'HOME',\n 'USER',\n 'LANG',\n 'LC_ALL',\n 'TMPDIR',\n 'TERM',\n 'SHELL',\n];\n\nexport interface LocalSandboxOptionsIface {\n // The directory the sandbox is confined to; created when missing.\n root: string;\n // Plain variables for every command, over the inherited ones.\n env?: Record<string, string>;\n // Names inherited from this process's environment (default LOCAL_INHERITED_ENV).\n inheritEnv?: string[];\n id?: string;\n // Every process's environment from the host, read again for each process.\n baseEnv?: () => Promise<Record<string, string>>;\n}\n\nexport interface LocalSandboxIface extends NetworkSandboxSessionIface {\n readonly root: string;\n}\n\nconst fsError = (code: string, message: string) =>\n Object.assign(new Error(`${code}: ${message}`), { code });\n\nconst errorCode = (error: unknown): string | null => {\n const parsed = z.object({ code: z.string() }).safeParse(error);\n return parsed.success ? parsed.data.code : null;\n};\n\nconst missing = (error: unknown) => {\n const code = errorCode(error);\n return code === 'ENOENT' || code === 'ENOTDIR';\n};\n\nconst signalExitCode = (signal: NodeJS.Signals | null): number => {\n if (signal === 'SIGKILL') return 137;\n if (signal === 'SIGINT') return 130;\n return 143;\n};\n\n// Node's built-ins, read on first use so that importing this module does not\n// tie a browser bundle of the client to Node.\nconst loadNode = () => {\n if (globalThis.process?.getBuiltinModule == null)\n throw new Error('A local sandbox runs only in Node');\n return {\n childProcess: process.getBuiltinModule('node:child_process'),\n fs: process.getBuiltinModule('node:fs'),\n fsPromises: process.getBuiltinModule('node:fs/promises'),\n os: process.getBuiltinModule('node:os'),\n path: process.getBuiltinModule('node:path'),\n streamPromises: process.getBuiltinModule('node:stream/promises'),\n };\n};\nlet loaded: ReturnType<typeof loadNode> | null = null;\nconst node = () => (loaded ??= loadNode());\n\nconst isSignal = (value: string): value is NodeJS.Signals => value in node().os.constants.signals;\n\n// Settles when a writable can take more, or will take nothing more.\nconst drained = (stream: Writable): Promise<void> =>\n new Promise((resolve) => {\n const done = () => {\n stream.off('drain', done);\n stream.off('close', done);\n stream.off('error', done);\n resolve();\n };\n stream.once('drain', done);\n stream.once('close', done);\n stream.once('error', done);\n });\n\n// How much a bridged stream buffers before it stops reading its Node stream.\nconst BRIDGE_HIGH_WATER_BYTES = 64 * 1024;\n\n// A Node stream as a web stream, with backpressure: the Node stream pauses\n// whenever the web stream's queue is full and reads on when its reader pulls.\n// `extra` may push bytes and close the stream from elsewhere.\nconst nodeToWeb = (\n readable: Readable | null,\n extra?: (bridge: { push: (bytes: Uint8Array) => void; close: () => void }) => void,\n): ReadableStream<Uint8Array> => {\n let open = true;\n return new ReadableStream<Uint8Array>(\n {\n start: (controller) => {\n const close = () => {\n if (!open) return;\n open = false;\n controller.close();\n };\n const push = (bytes: Uint8Array) => {\n if (!open) return;\n controller.enqueue(bytes);\n if ((controller.desiredSize ?? 0) <= 0) readable?.pause();\n };\n extra?.({ push, close });\n if (readable == null) {\n close();\n return;\n }\n readable.on('data', (chunk: Buffer) => push(new Uint8Array(chunk)));\n // Reads start when the reader pulls.\n readable.pause();\n readable.once('end', close);\n readable.once('error', (error) => {\n if (!open) return;\n open = false;\n controller.error(error);\n });\n },\n pull: () => {\n readable?.resume();\n },\n cancel: () => {\n open = false;\n readable?.destroy();\n },\n },\n { highWaterMark: BRIDGE_HIGH_WATER_BYTES, size: (chunk) => chunk.byteLength },\n );\n};\n\n// How long stopping waits for commands to end on SIGTERM before SIGKILL.\nexport const LOCAL_STOP_GRACE_MS = 2_000;\n\n// Referenced on purpose: a script that ends with `await sandbox.stop()` stays\n// alive until a stubborn command has been killed.\nconst pause = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));\n\n// Whether `promise` settles within `ms`; the timer is cleared either way.\nconst within = async (promise: Promise<unknown>, ms: number): Promise<boolean> => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise.then(() => true),\n new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), Math.max(0, ms));\n }),\n ]);\n } finally {\n clearTimeout(timer);\n }\n};\n\n// Symlinks one path may pass through before it is refused as a loop.\nconst MAX_SYMLINKS = 40;\n\n// A command runs in its own process group (POSIX), so that a timeout, a cancel\n// or a stop ends everything it started; a shell's children would otherwise\n// outlive it and hold its output open.\nconst ownGroup = (): boolean => process.platform !== 'win32';\n\nconst signalProcessTree = (child: ChildProcess, signal: NodeJS.Signals): void => {\n if (ownGroup() && child.pid != null) {\n try {\n process.kill(-child.pid, signal);\n return;\n } catch {\n // The group has already exited; signal the child itself.\n }\n }\n child.kill(signal);\n};\n\n// A leading `..` component leaves the root; a name that merely starts with\n// two dots (`..config`) does not.\nconst inside = (root: string, path: string): boolean => {\n const { isAbsolute, relative, sep } = node().path;\n const rel = relative(root, path);\n return rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);\n};\n\nexport const createLocalSandbox = async (\n options: LocalSandboxOptionsIface,\n): Promise<LocalSandboxIface> => {\n const { childProcess, fs, fsPromises, path: paths, streamPromises } = node();\n const root = paths.resolve(options.root);\n await fsPromises.mkdir(root, { recursive: true });\n const realRoot = await fsPromises.realpath(root);\n const id = options.id ?? `local-${crypto.randomUUID()}`;\n const processes = new Set<ChildProcess>();\n // Every process group a command started: a shell's backgrounded children\n // outlive it in its group, and stopping the sandbox ends them too.\n const groups = new Set<number>();\n const groupAlive = (pgid: number): boolean => {\n try {\n process.kill(-pgid, 0);\n return true;\n } catch {\n return false;\n }\n };\n const inherited: Record<string, string> = {};\n for (const name of options.inheritEnv ?? LOCAL_INHERITED_ENV) {\n const value = process.env[name];\n if (value != null) inherited[name] = value;\n }\n\n const resolvePath = (path: string): string =>\n paths.isAbsolute(path) ? paths.resolve(path) : paths.join(root, path);\n\n // The real location of `path` (or of its nearest existing ancestor, for a\n // path about to be created), refused unless it stays under `within`: no `..`\n // and no symlink leads out of the sandbox. A dangling symlink is followed to\n // where it points, since writing through it creates its target.\n const confined = async (path: string, within?: string): Promise<string> => {\n const bounds = within == null ? [realRoot] : [realRoot, await confined(within)];\n let existing = resolvePath(path);\n const rest: string[] = [];\n let links = 0;\n for (;;) {\n const real = await fsPromises.realpath(existing).catch((error: unknown) => {\n if (missing(error)) return null;\n throw error;\n });\n if (real != null) {\n const target = paths.join(real, ...rest.toReversed());\n for (const bound of bounds)\n if (!inside(bound, target)) throw fsError('EACCES', `${path} is outside the sandbox`);\n return target;\n }\n const entry = await fsPromises.lstat(existing).catch((error: unknown) => {\n if (missing(error)) return null;\n throw error;\n });\n if (entry?.isSymbolicLink() === true) {\n links += 1;\n if (links > MAX_SYMLINKS) throw fsError('ELOOP', `${path} has too many symlinks`);\n // Relative to the link's real directory, as the kernel resolves it.\n const directory = await fsPromises.realpath(paths.dirname(existing));\n existing = paths.resolve(directory, await fsPromises.readlink(existing));\n continue;\n }\n const parent = paths.dirname(existing);\n if (parent === existing) throw fsError('ENOENT', `${path} does not exist`);\n rest.push(paths.basename(existing));\n existing = parent;\n }\n };\n\n // The real location of the entry `path` names, its last component not\n // followed: removing a symlink removes the link, not what it points to.\n const confinedEntry = async (path: string): Promise<string> => {\n const logical = resolvePath(path);\n if (logical === root) throw fsError('EPERM', 'refusing to remove the sandbox root');\n return paths.join(await confined(paths.dirname(logical)), paths.basename(logical));\n };\n\n const statOf = async (path: string, within?: string): Promise<StatIface | null> => {\n let target: string;\n try {\n target = await confined(path, within);\n const entry = await fsPromises.stat(target);\n return {\n path: resolvePath(path),\n type: entry.isDirectory()\n ? SandboxEntryType.Directory\n : entry.isFile()\n ? SandboxEntryType.File\n : SandboxEntryType.Other,\n size: entry.isDirectory() ? 0 : entry.size,\n modifiedAt: entry.mtime.toISOString(),\n mode: entry.mode & 0o7777,\n };\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n };\n\n const writeBytes = async (path: string, data: Uint8Array): Promise<void> => {\n const target = await confined(path);\n await fsPromises.mkdir(paths.dirname(target), { recursive: true });\n await fsPromises.writeFile(target, data);\n };\n\n const spawn = async (spawnOptions: SandboxProcessOptionsIface): Promise<SandboxProcessIface> => {\n // A command cancelled before it starts never runs.\n const signal = spawnOptions.abortSignal;\n signal?.throwIfAborted();\n const cwd = await confined(spawnOptions.cwd ?? '.');\n signal?.throwIfAborted();\n const base = await options.baseEnv?.();\n signal?.throwIfAborted();\n const env = { ...inherited, ...options.env, ...base, ...spawnOptions.env };\n const shell = spawnOptions.shell === true;\n const child = childProcess.spawn(\n shell ? [spawnOptions.command, ...(spawnOptions.args ?? [])].join(' ') : spawnOptions.command,\n shell ? [] : (spawnOptions.args ?? []),\n { cwd, env, shell, stdio: ['pipe', 'pipe', 'pipe'], detached: ownGroup() },\n );\n processes.add(child);\n if (ownGroup() && child.pid != null) {\n for (const pgid of groups) if (!groupAlive(pgid)) groups.delete(pgid);\n groups.add(child.pid);\n }\n let timedOut = false;\n // A command that never started reports why on stderr.\n const stderr = nodeToWeb(child.stderr, ({ push, close }) =>\n child.once('error', (error) => {\n push(new TextEncoder().encode(`${error.message}\\n`));\n close();\n }),\n );\n const exited = new Promise<{ exitCode: number }>((settle) => {\n child.once('error', (error) => {\n processes.delete(child);\n settle({ exitCode: errorCode(error) === 'ENOENT' ? 127 : 126 });\n });\n // Exit, not close: output nobody reads holds the pipes (and `close`) open, and the\n // command has ended all the same.\n child.once('exit', (code, signal) => {\n processes.delete(child);\n settle({ exitCode: timedOut ? 124 : (code ?? signalExitCode(signal)) });\n });\n });\n const timer =\n spawnOptions.timeoutMs == null\n ? null\n : setTimeout(() => {\n timedOut = true;\n signalProcessTree(child, 'SIGKILL');\n }, spawnOptions.timeoutMs);\n // A command that ignores SIGTERM is killed once the stop grace period ends.\n let escalation: ReturnType<typeof setTimeout> | null = null;\n const terminate = (signal: NodeJS.Signals) => {\n signalProcessTree(child, signal);\n if (signal !== 'SIGTERM' || escalation != null) return;\n escalation = setTimeout(() => signalProcessTree(child, 'SIGKILL'), LOCAL_STOP_GRACE_MS);\n };\n const onAbort = () => terminate('SIGTERM');\n spawnOptions.abortSignal?.addEventListener('abort', onAbort, { once: true });\n // The deadline, a cancel and the SIGKILL escalation stand until the output closes: a\n // descendant that outlives the command holds it open and is ended with the group.\n const settled = () => {\n if (timer != null) clearTimeout(timer);\n const groupLeft = ownGroup() && child.pid != null && groupAlive(child.pid);\n if (escalation != null && !groupLeft) clearTimeout(escalation);\n spawnOptions.abortSignal?.removeEventListener('abort', onAbort);\n };\n child.once('close', settled);\n child.once('error', settled);\n const stdin = child.stdin;\n stdin?.on('error', () => undefined);\n if (typeof spawnOptions.stdin === 'string') stdin?.end(spawnOptions.stdin);\n else if (spawnOptions.stdin != null) {\n const reader = spawnOptions.stdin.getReader();\n // Reads on only as fast as the command takes its input, and stops when it exits.\n let finished = false;\n void exited.then(() => {\n finished = true;\n void reader.cancel().catch(() => undefined);\n });\n void (async () => {\n for (;;) {\n const next = await reader.read();\n if (next.done || finished || stdin == null || stdin.destroyed) break;\n if (!stdin.write(next.value)) await Promise.race([drained(stdin), exited]);\n }\n stdin?.end();\n })().catch(() => stdin?.destroy());\n }\n return {\n pid: child.pid == null ? null : String(child.pid),\n ref: null,\n stdout: nodeToWeb(child.stdout),\n stderr,\n write: async (data, writeOptions) => {\n if (spawnOptions.stdin != null) throw new Error('stdin was provided at spawn');\n if (stdin == null) throw new Error('the process has no stdin');\n await new Promise<void>((done, fail) =>\n stdin.write(data, (error) => (error == null ? done() : fail(error))),\n );\n if (writeOptions?.end === true) stdin.end();\n },\n wait: () => exited,\n // SIGTERM (killed after the grace period if ignored) and SIGKILL resolve once the\n // command has ended; any other signal (SIGSTOP, SIGCONT, ...) once it is sent.\n kill: async (signal) => {\n const name = signal ?? 'SIGTERM';\n const sent = isSignal(name) ? name : 'SIGTERM';\n terminate(sent);\n if (sent === 'SIGTERM' || sent === 'SIGKILL') await exited;\n },\n };\n };\n\n const sandbox: LocalSandboxIface = {\n id,\n root,\n defaultWorkingDirectory: root,\n ports: [],\n description: `This machine, in ${root}.`,\n readFile: async ({ path, root: within }) => {\n let target: string;\n try {\n target = await confined(path, within);\n const entry = await fsPromises.stat(target);\n if (entry.isDirectory()) throw fsError('EISDIR', `${path} is a directory`);\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n return nodeToWeb(fs.createReadStream(target));\n },\n readBinaryFile: async ({ path }) => {\n try {\n return new Uint8Array(await fsPromises.readFile(await confined(path)));\n } catch (error) {\n if (missing(error)) return null;\n throw error;\n }\n },\n readTextFile: async (readOptions) => {\n const stream = await sandbox.readFile({ path: readOptions.path });\n return stream == null ? null : readTextFileStream(stream, readOptions);\n },\n writeFile: async ({ path, content }) => {\n const target = await confined(path);\n await fsPromises.mkdir(paths.dirname(target), { recursive: true });\n const reader = content.getReader();\n const output = fs.createWriteStream(target);\n await streamPromises.pipeline(\n (async function* () {\n for (;;) {\n const next = await reader.read();\n if (next.done) return;\n yield next.value;\n }\n })(),\n output,\n );\n },\n writeBinaryFile: ({ path, content }) => writeBytes(path, content),\n writeTextFile: ({ path, content, encoding }) =>\n writeBytes(path, encodeSandboxText(content, encoding)),\n spawn,\n run: (runOptions) => runCollect({ spawn }, runOptions),\n stat: ({ path, root: within }) => statOf(path, within),\n readDir: async ({ path, root: within }): Promise<DirEntryIface[]> => {\n const target = await confined(path, within);\n const logical = resolvePath(path);\n const entries = await fsPromises.readdir(target, { withFileTypes: true });\n return Promise.all(\n entries.map(async (entry) => {\n const type = entry.isDirectory()\n ? SandboxEntryType.Directory\n : entry.isFile()\n ? SandboxEntryType.File\n : entry.isSymbolicLink()\n ? SandboxEntryType.Symlink\n : SandboxEntryType.Other;\n const size = entry.isFile()\n ? (await fsPromises.lstat(paths.join(target, entry.name))).size\n : null;\n return { name: entry.name, path: paths.join(logical, entry.name), type, size };\n }),\n );\n },\n resolvePath,\n removePath: async ({ path, recursive, force }) => {\n const target = await confinedEntry(path);\n await fsPromises.rm(target, { recursive: recursive === true, force: force === true });\n },\n getPortEndpoint: async ({ port, protocol }) => ({\n url: `${protocol ?? PortProtocol.Http}://127.0.0.1:${port}`,\n }),\n getPortUrl: async (portOptions) => (await sandbox.getPortEndpoint(portOptions)).url,\n // Stopping ends the commands it started; the directory is the caller's and stays.\n // A command that ignores SIGTERM is killed once the grace period ends.\n stop: async () => {\n const children = [...processes];\n const pgids = new Set(groups);\n groups.clear();\n for (const child of children) if (ownGroup() && child.pid != null) pgids.add(child.pid);\n const closed = Promise.all(\n children.map(\n (child) =>\n new Promise<void>((done) => {\n if (child.exitCode != null || child.signalCode != null) done();\n else child.once('exit', () => done());\n }),\n ),\n );\n const signalAll = (signal: NodeJS.Signals) => {\n for (const child of children) signalProcessTree(child, signal);\n for (const pgid of pgids) {\n try {\n process.kill(-pgid, signal);\n } catch {\n // The group has already exited.\n }\n }\n };\n // Whether every command closed and every group is gone by the deadline.\n const settled = async (deadline: number): Promise<boolean> => {\n if (!(await within(closed, deadline - Date.now()))) return false;\n while ([...pgids].some(groupAlive)) {\n if (Date.now() >= deadline) return false;\n await pause(25);\n }\n return true;\n };\n signalAll('SIGTERM');\n if (await settled(Date.now() + LOCAL_STOP_GRACE_MS)) return;\n signalAll('SIGKILL');\n await settled(Date.now() + LOCAL_STOP_GRACE_MS);\n },\n destroy: () => sandbox.stop(),\n };\n return sandbox;\n};\n\nconst localEnvironmentSchema = z.strictObject({\n root: z.string().min(1),\n // The platform's variables (its proxy, its CA) are its own to set.\n env: z\n .record(z.string(), z.string())\n .refine(\n (env) => Object.keys(env).every((name) => !PLATFORM_ENVIRONMENT_NAMES.has(name)),\n 'env sets a variable the platform owns',\n )\n .optional(),\n inheritEnv: z.array(z.string().min(1)).optional(),\n});\n\nconst localStateSchema = z.object({ version: z.literal(1), root: z.string() });\n\n// The directory under the sandbox root that holds the platform's files (its CA certificate\n// and the like). They are written on this machine, so the paths the platform names are\n// re-rooted here rather than taken as locations outside the sandbox.\nexport const LOCAL_PLATFORM_DIRECTORY = '.final';\n\n// Where a platform file goes: its path re-rooted under the reserved directory. A path\n// with a `..` component is refused.\nconst platformFileTarget = (root: string, path: string): string => {\n const paths = node().path;\n const components = path\n .slice(paths.parse(path).root.length)\n .split(/[\\\\/]/)\n .filter((component) => component !== '' && component !== '.');\n if (components.length === 0 || components.includes('..'))\n throw new Error(\n `refusing the platform file ${JSON.stringify(path)}: it must name a file without ..`,\n );\n return paths.join(root, LOCAL_PLATFORM_DIRECTORY, ...components);\n};\n\n// The platform's variables with every value that names a platform file pointed at the\n// file's confined location.\nconst relocatedEnvironment = (\n env: Record<string, string>,\n moved: ReadonlyMap<string, string> | undefined,\n): Record<string, string> => {\n if (moved == null || moved.size === 0) return env;\n const result: Record<string, string> = {};\n for (const [name, value] of Object.entries(env)) result[name] = moved.get(value) ?? value;\n return result;\n};\n\ntype LocalArtifact = { version: 1; root: string };\ntype LocalState = z.infer<typeof localStateSchema>;\n\n// Stopping ends the sandbox's commands, its services among them: the next attach opens it\n// again and reports a boot, so they are started again.\nconst handleOf = (\n sandbox: LocalSandboxIface,\n forget: () => void,\n): SandboxProviderHandleIface<LocalSandboxIface> => ({\n sandbox,\n onSandboxStop: () => {\n forget();\n return sandbox.stop();\n },\n onSandboxDelete: () => {\n forget();\n return sandbox.destroy();\n },\n onRuntimeShutdown: () => {\n forget();\n return sandbox.stop();\n },\n});\n\n// The local sandbox as a provider, for a host that drives sandboxes through\n// the provider lifecycle. Deleting it stops its commands and leaves the\n// directory, which belongs to whoever runs this process.\nexport const createLocalSandboxProvider = (): SandboxProviderIface<\n JsonValue,\n LocalArtifact,\n LocalState,\n LocalSandboxIface\n> => {\n const live = new Map<string, LocalSandboxIface>();\n // Per sandbox, each platform file's path as the platform named it \u2192 where it was written.\n const relocated = new Map<string, Map<string, string>>();\n return defineSandboxProvider<JsonValue, LocalArtifact, LocalState, LocalSandboxIface>({\n name: LOCAL_PROVIDER,\n environment: (rawOptions) => {\n const options = localEnvironmentSchema.parse(rawOptions);\n const root = node().path.resolve(options.root);\n const open = async (ctx: SandboxResourceContextIface, sandboxId: string) => {\n const sandbox = await createLocalSandbox({\n root,\n id: sandboxId,\n env: options.env,\n inheritEnv: options.inheritEnv,\n baseEnv: async () =>\n relocatedEnvironment(\n await platformProcessEnvironment(ctx, {})(),\n relocated.get(sandboxId),\n ),\n });\n live.set(sandboxId, sandbox);\n return sandbox;\n };\n return {\n capabilities: async () => ({\n [Capability.Files]: FilesAccess.Write,\n [Capability.Shell]: ShellAccess.Execute,\n }),\n artifactKey: async () => `local:${root}`,\n prepare: async () => ({ version: 1, root }),\n // Commands run on this machine's own network: a policy could not be enforced.\n create: async (_ctx, { setup }) => {\n if (setup?.network != null)\n throw new Error(\n \"a local sandbox runs on this machine's network and cannot enforce a network policy; remove the setup's network\",\n );\n return { state: { version: 1, root } };\n },\n // This process is the machine: it runs as long as the sandbox can be reached.\n awaitRunning: async () => undefined,\n attach: async (ctx, { state }) => {\n const existing = live.get(ctx.sandboxId);\n const fresh =\n existing == null &&\n (await node()\n .fsPromises.stat(root)\n .catch(() => null)) == null;\n const sandbox = existing ?? (await open(ctx, ctx.sandboxId));\n // Every destination is reachable from here. The platform's files are written under\n // the reserved directory (through the sandbox's own confinement, so no symlink\n // leads them out of the root) before the handle runs anything, and the variables\n // that name them are pointed there.\n await reportPlatformNetworkPolicy(ctx, { mode: NetworkPolicy.AllowAll });\n const moved = new Map<string, string>();\n for (const [path, content] of Object.entries((await ctx.platformFiles?.()) ?? {})) {\n const target = platformFileTarget(root, path);\n await sandbox.writeTextFile({ path: target, content });\n moved.set(path, target);\n }\n relocated.set(ctx.sandboxId, moved);\n const forget = () => {\n if (live.get(ctx.sandboxId) === sandbox) live.delete(ctx.sandboxId);\n };\n return { handle: handleOf(sandbox, forget), state, fresh, booted: existing == null };\n },\n detach: async (_ctx, { state }) => state,\n park: async (ctx, { state }) => {\n await live.get(ctx.sandboxId)?.stop();\n live.delete(ctx.sandboxId);\n return state;\n },\n delete: async (ctx) => {\n await live.get(ctx.sandboxId)?.destroy();\n live.delete(ctx.sandboxId);\n relocated.delete(ctx.sandboxId);\n },\n };\n },\n });\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["within", "signal"]
7
7
  }
@@ -313,7 +313,6 @@ const readOnlySession = (session) => {
313
313
  destroy: readOnlyRefusal
314
314
  };
315
315
  if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;
316
- delete restricted.egress;
317
316
  delete restricted.attachProcess;
318
317
  const screen = session.screen;
319
318
  if (screen != null)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/sandboxes/session.ts"],
4
- "sourcesContent": ["import type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxAttachedProcessIface,\n SandboxAttachProcessOptionsIface,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk, splitChunks } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport {\n exitStatus,\n type SandboxTransportIface,\n type TransportOutputIface,\n type TransportOutputStreamIface,\n type TransportProcessIface,\n} from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n // What else a process ref must match beyond this session and the process's\n // boot, read when spawning and attaching (a Device's lease generation).\n processScope?: () => string;\n}\n\n// A durable process's ref: this session, the process and its boot, and the scope.\nconst PROCESS_REF_PREFIX = 'final-process.v1';\n\nconst encodeProcessRef = (parts: {\n session: string;\n process: TransportProcessIface;\n scope: string;\n}): string =>\n [PROCESS_REF_PREFIX, parts.session, parts.process.id, parts.process.bootId, parts.scope]\n .map(encodeURIComponent)\n .join(':');\n\nconst decodeProcessRef = (\n ref: string,\n): { session: string; process: TransportProcessIface; scope: string } | null => {\n const parts = ref.split(':');\n if (parts.length !== 5 || parts[0] !== PROCESS_REF_PREFIX) return null;\n try {\n const [session = '', id = '', bootId = '', scope = ''] = parts.slice(1).map(decodeURIComponent);\n return { session, process: { id, bootId }, scope };\n } catch {\n return null;\n }\n};\n\n// Where output read from `requested` starts: there, or later when the\n// backend no longer retains the bytes from there.\nconst outputStart = (chunk: TransportOutputStreamIface, requested: number): number =>\n Math.max(requested, chunk.nextOffset - chunk.data.byteLength);\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const kill =\n (process: TransportProcessIface) =>\n async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n\n // Polls a process's output from the given offsets (after `first`, output\n // already read from there) until it exits. Aborting `detach` stops polling\n // and fails the streams and the exit; the process is untouched.\n const followProcess = (args: {\n process: TransportProcessIface;\n stdoutOffset: number;\n stderrOffset: number;\n first?: TransportOutputIface;\n detach?: AbortSignal;\n }) => {\n const { process } = args;\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n void (async () => {\n let stdoutOffset = args.stdoutOffset;\n let stderrOffset = args.stderrOffset;\n let waitMs = transport.outputWaitMs;\n let pending = args.first;\n try {\n for (;;) {\n args.detach?.throwIfAborted();\n const output =\n pending ??\n (await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n signal: args.detach,\n }));\n pending = undefined;\n args.detach?.throwIfAborted();\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n }\n })();\n return { stdout: stdoutPush.stream, stderr: stderrPush.stream, exit, kill: kill(process) };\n };\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n // Durable only where processes outlive this client (`processGone`).\n const durable = options.durable === true && transport.processGone != null;\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const followed = followProcess({\n process,\n stdoutOffset: 0,\n stderrOffset: 0,\n detach: durable ? options.abortSignal : undefined,\n });\n if (!durable) {\n const onAbort = (): void => {\n void followed.kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n void followed.exit\n .catch(() => undefined)\n .finally(() => options.abortSignal?.removeEventListener('abort', onAbort));\n }\n\n // A detached durable handle neither writes to nor closes the process's stdin.\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n if (durable) options.abortSignal?.throwIfAborted();\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n // Forward input as it arrives: a stdin stream is often interactive.\n for await (const chunk of splitChunks(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n ref: durable\n ? encodeProcessRef({ session: args.id, process, scope: args.processScope?.() ?? '' })\n : null,\n stdout: followed.stdout,\n stderr: followed.stderr,\n write,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n // Finds a durable process again: null for a ref of another session or scope,\n // or a process the backend no longer knows.\n const attachProcess = async (\n options: SandboxAttachProcessOptionsIface,\n ): Promise<SandboxAttachedProcessIface | null> => {\n options.abortSignal?.throwIfAborted();\n const decoded = decodeProcessRef(options.ref);\n if (\n transport.processGone == null ||\n decoded == null ||\n decoded.session !== args.id ||\n decoded.scope !== (args.processScope?.() ?? '')\n )\n return null;\n const { process } = decoded;\n let first: TransportOutputIface;\n try {\n first = await transport.output({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n waitMs: 0,\n signal: options.abortSignal,\n });\n } catch (cause) {\n if (transport.processGone(cause)) return null;\n throw cause;\n }\n const followed = followProcess({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n first,\n detach: options.abortSignal,\n });\n return {\n ref: options.ref,\n stdoutOffset: outputStart(first.stdout, options.stdoutOffset),\n stderrOffset: outputStart(first.stderr, options.stderrOffset),\n stdout: followed.stdout,\n stderr: followed.stderr,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess({ ...options, durable: false }, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n if (transport.processGone != null) session.attachProcess = attachProcess;\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox handle is read-only');\n};\n\n// A passive viewer's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the backend the provider asked.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n delete restricted.egress;\n delete restricted.attachProcess;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n DirEntryIface,\n NetworkSandboxSessionIface,\n PortProtocol,\n SandboxAttachedProcessIface,\n SandboxAttachProcessOptionsIface,\n SandboxProcessIface,\n SandboxProcessOptionsIface,\n SandboxRunResultIface,\n StatIface,\n} from '@finalai/agent-provider/sandbox';\nimport { createConfinedFileReader, SandboxEntryType } from '@finalai/agent-provider/sandbox';\nimport { encodeSandboxText } from '@finalai/agent-provider/sandbox/bytes';\nimport { readTextFileStream } from '@finalai/agent-provider/sandbox/convenience';\nimport { collectStream, errorMessage, isNotFoundMessage, rechunk, splitChunks } from \"./bytes.mjs\";\nimport { posixCommandLine, type SandboxCommandEncoderIface } from \"./commands.mjs\";\nimport { POSIX_PATHS, type SandboxPathsIface } from \"./paths.mjs\";\nimport {\n exitStatus,\n type SandboxTransportIface,\n type TransportOutputIface,\n type TransportOutputStreamIface,\n type TransportProcessIface,\n} from \"./transport.mjs\";\n\n// NetworkSandboxSessionIface over any SandboxTransportIface. Provider specifics\n// (lifecycle, ports, extra capabilities) come in through `network`.\n\nexport interface TransportSessionNetworkIface {\n ports: readonly number[];\n getPortEndpoint(options: {\n port: number;\n protocol?: PortProtocol;\n }): Promise<{ url: string; headers?: Record<string, string> }>;\n stop(): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface CreateTransportSessionArgsIface {\n id: string;\n description: string;\n workspaceRoot: string;\n transport: SandboxTransportIface;\n // Environment every process gets (injected variables), under per-call env;\n // read again for every process.\n baseEnv: () => Promise<Record<string, string>>;\n randomUuid: () => string;\n network: TransportSessionNetworkIface;\n // The sandbox's path flavour and command encoding; POSIX unless a Device says otherwise.\n paths?: SandboxPathsIface;\n commands?: SandboxCommandEncoderIface;\n // What else a process ref must match beyond this session and the process's\n // boot, read when spawning and attaching (a Device's lease generation).\n processScope?: () => string;\n}\n\n// A durable process's ref: this session, the process and its boot, and the scope.\nconst PROCESS_REF_PREFIX = 'final-process.v1';\n\nconst encodeProcessRef = (parts: {\n session: string;\n process: TransportProcessIface;\n scope: string;\n}): string =>\n [PROCESS_REF_PREFIX, parts.session, parts.process.id, parts.process.bootId, parts.scope]\n .map(encodeURIComponent)\n .join(':');\n\nconst decodeProcessRef = (\n ref: string,\n): { session: string; process: TransportProcessIface; scope: string } | null => {\n const parts = ref.split(':');\n if (parts.length !== 5 || parts[0] !== PROCESS_REF_PREFIX) return null;\n try {\n const [session = '', id = '', bootId = '', scope = ''] = parts.slice(1).map(decodeURIComponent);\n return { session, process: { id, bootId }, scope };\n } catch {\n return null;\n }\n};\n\n// Where output read from `requested` starts: there, or later when the\n// backend no longer retains the bytes from there.\nconst outputStart = (chunk: TransportOutputStreamIface, requested: number): number =>\n Math.max(requested, chunk.nextOffset - chunk.data.byteLength);\n\nconst textDecoder = (): TextDecoder => new TextDecoder('utf-8');\n\ninterface PushStreamIface {\n stream: ReadableStream<Uint8Array>;\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\ninterface ControllerHolderIface {\n controller?: ReadableStreamDefaultController<Uint8Array>;\n}\n\n// A stream the output pump pushes into; unread output stays queued in memory.\nconst pushStream = (): PushStreamIface => {\n const holder: ControllerHolderIface = {};\n const stream = new ReadableStream<Uint8Array>({\n start: (controller) => {\n holder.controller = controller;\n },\n });\n return { stream, controller: holder.controller };\n};\n\nconst toStatEntry = (\n path: string,\n stat: { type: SandboxEntryType; size: number; modifiedAtMs: number | null; mode: number | null },\n): StatIface => ({\n path,\n type: stat.type,\n size: stat.size,\n modifiedAt: stat.modifiedAtMs == null ? null : new Date(stat.modifiedAtMs).toISOString(),\n mode: stat.mode,\n});\n\nexport const createTransportSession = (\n args: CreateTransportSessionArgsIface,\n): NetworkSandboxSessionIface => {\n const { transport } = args;\n const paths = args.paths ?? POSIX_PATHS;\n const commandLine = args.commands ?? posixCommandLine;\n const resolvePath = (path: string): string => paths.resolve(args.workspaceRoot, path);\n\n const kill =\n (process: TransportProcessIface) =>\n async (signal?: string): Promise<void> => {\n await transport.input(\n signal == null || signal === 'SIGKILL' ? { process, terminate: true } : { process, signal },\n );\n };\n\n // Polls a process's output from the given offsets (after `first`, output\n // already read from there) until it exits. Aborting `detach` stops polling\n // and fails the streams and the exit; the process is untouched.\n const followProcess = (args: {\n process: TransportProcessIface;\n stdoutOffset: number;\n stderrOffset: number;\n first?: TransportOutputIface;\n detach?: AbortSignal;\n }) => {\n const { process } = args;\n const stdoutPush = pushStream();\n const stderrPush = pushStream();\n let settleExit: (value: { exitCode: number }) => void = () => undefined;\n let failExit: (error: Error) => void = () => undefined;\n const exit = new Promise<{ exitCode: number }>((resolve, reject) => {\n settleExit = resolve;\n failExit = reject;\n });\n // Avoid an unhandled rejection when the caller only reads the streams.\n exit.catch(() => undefined);\n void (async () => {\n let stdoutOffset = args.stdoutOffset;\n let stderrOffset = args.stderrOffset;\n let waitMs = transport.outputWaitMs;\n let pending = args.first;\n try {\n for (;;) {\n args.detach?.throwIfAborted();\n const output =\n pending ??\n (await transport.output({\n process,\n stdoutOffset,\n stderrOffset,\n waitMs,\n signal: args.detach,\n }));\n pending = undefined;\n args.detach?.throwIfAborted();\n if (output.stdout.data.byteLength > 0) stdoutPush.controller?.enqueue(output.stdout.data);\n if (output.stderr.data.byteLength > 0) stderrPush.controller?.enqueue(output.stderr.data);\n const advanced =\n output.stdout.nextOffset !== stdoutOffset || output.stderr.nextOffset !== stderrOffset;\n stdoutOffset = output.stdout.nextOffset;\n stderrOffset = output.stderr.nextOffset;\n if (output.exited && output.stdout.eof && output.stderr.eof) {\n stdoutPush.controller?.close();\n stderrPush.controller?.close();\n settleExit({ exitCode: exitStatus(output.exitCode, output.exitSignal) });\n return;\n }\n // Exited with unread output: drain it without waiting.\n waitMs = output.exited && advanced ? 0 : transport.outputWaitMs;\n }\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n stdoutPush.controller?.error(error);\n stderrPush.controller?.error(error);\n failExit(error);\n }\n })();\n return { stdout: stdoutPush.stream, stderr: stderrPush.stream, exit, kill: kill(process) };\n };\n\n const spawnProcess = async (\n options: SandboxProcessOptionsIface,\n closeStdin: boolean,\n ): Promise<SandboxProcessIface> => {\n options.abortSignal?.throwIfAborted();\n // Durable only where processes outlive this client (`processGone`).\n const durable = options.durable === true && transport.processGone != null;\n const process: TransportProcessIface = await transport.exec({\n id: args.randomUuid(),\n command: commandLine(options),\n cwd: resolvePath(options.cwd ?? args.workspaceRoot),\n env: { ...(await args.baseEnv()), ...options.env },\n timeoutMs: options.timeoutMs ?? null,\n signal: options.abortSignal,\n });\n const followed = followProcess({\n process,\n stdoutOffset: 0,\n stderrOffset: 0,\n detach: durable ? options.abortSignal : undefined,\n });\n if (!durable) {\n const onAbort = (): void => {\n void followed.kill().catch(() => undefined);\n };\n options.abortSignal?.addEventListener('abort', onAbort, { once: true });\n if (options.abortSignal?.aborted === true) onAbort();\n void followed.exit\n .catch(() => undefined)\n .finally(() => options.abortSignal?.removeEventListener('abort', onAbort));\n }\n\n // A detached durable handle neither writes to nor closes the process's stdin.\n const write = async (data: Uint8Array | string, writeOptions?: { end?: boolean }) => {\n if (durable) options.abortSignal?.throwIfAborted();\n const bytes = data instanceof Uint8Array ? data : new TextEncoder().encode(data);\n if (bytes.byteLength > 0) await transport.input({ process, data: bytes });\n if (writeOptions?.end === true) await transport.input({ process, eof: true });\n };\n\n const input = options.stdin;\n if (input instanceof ReadableStream) {\n void (async () => {\n // Forward input as it arrives: a stdin stream is often interactive.\n for await (const chunk of splitChunks(input, 64 * 1024)) await write(chunk);\n await write(new Uint8Array(), { end: true });\n })().catch(() => undefined);\n } else if (input != null) {\n await write(input, { end: true });\n } else if (closeStdin) {\n await transport.input({ process, eof: true });\n }\n\n return {\n pid: process.id,\n ref: durable\n ? encodeProcessRef({ session: args.id, process, scope: args.processScope?.() ?? '' })\n : null,\n stdout: followed.stdout,\n stderr: followed.stderr,\n write,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n // Finds a durable process again: null for a ref of another session or scope,\n // or a process the backend no longer knows.\n const attachProcess = async (\n options: SandboxAttachProcessOptionsIface,\n ): Promise<SandboxAttachedProcessIface | null> => {\n options.abortSignal?.throwIfAborted();\n const decoded = decodeProcessRef(options.ref);\n if (\n transport.processGone == null ||\n decoded == null ||\n decoded.session !== args.id ||\n decoded.scope !== (args.processScope?.() ?? '')\n )\n return null;\n const { process } = decoded;\n let first: TransportOutputIface;\n try {\n first = await transport.output({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n waitMs: 0,\n signal: options.abortSignal,\n });\n } catch (cause) {\n if (transport.processGone(cause)) return null;\n throw cause;\n }\n const followed = followProcess({\n process,\n stdoutOffset: options.stdoutOffset,\n stderrOffset: options.stderrOffset,\n first,\n detach: options.abortSignal,\n });\n return {\n ref: options.ref,\n stdoutOffset: outputStart(first.stdout, options.stdoutOffset),\n stderrOffset: outputStart(first.stderr, options.stderrOffset),\n stdout: followed.stdout,\n stderr: followed.stderr,\n wait: () => followed.exit,\n kill: followed.kill,\n };\n };\n\n const readStream = async (\n path: string,\n signal: AbortSignal | undefined,\n ): Promise<ReadableStream<Uint8Array> | null> => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal });\n if (stat == null) return null;\n if (stat.type === SandboxEntryType.Directory) throw new Error(`${resolved} is a directory`);\n // Read to end of file rather than to the stat size: a symlink's stat is the\n // link's own length, not its target's.\n let offset = 0;\n let done = false;\n return new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (done) {\n controller.close();\n return;\n }\n const chunk = await transport.readChunk({\n path: resolved,\n offset,\n length: transport.fileChunkBytes,\n signal,\n });\n done = chunk.eof || chunk.bytes.byteLength === 0;\n offset += chunk.bytes.byteLength;\n if (chunk.bytes.byteLength > 0) controller.enqueue(chunk.bytes);\n if (done) controller.close();\n },\n });\n };\n\n const writeStream = async (\n path: string,\n content: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n ): Promise<void> => {\n const resolved = resolvePath(path);\n await transport.createDirectory({ path: paths.dirname(resolved), signal });\n let offset = 0;\n for await (const chunk of rechunk(content, transport.fileChunkBytes)) {\n await transport.writeChunk({ path: resolved, offset, bytes: chunk, signal });\n offset += chunk.byteLength;\n }\n if (offset === 0)\n await transport.writeChunk({ path: resolved, offset: 0, bytes: new Uint8Array(), signal });\n };\n\n const bytesStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start: (controller) => {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\n const session: NetworkSandboxSessionIface = {\n id: args.id,\n description: args.description,\n defaultWorkingDirectory: args.workspaceRoot,\n ports: args.network.ports,\n resolvePath,\n readFile: async ({ path, abortSignal }) => readStream(path, abortSignal),\n readBinaryFile: async ({ path, abortSignal }) => {\n const stream = await readStream(path, abortSignal);\n return stream == null ? null : collectStream(stream);\n },\n readTextFile: async (options) => {\n const stream = await readStream(options.path, options.abortSignal);\n return stream == null ? null : readTextFileStream(stream, options);\n },\n writeFile: async ({ path, content, abortSignal }) => writeStream(path, content, abortSignal),\n writeBinaryFile: async ({ path, content, abortSignal }) =>\n writeStream(path, bytesStream(content), abortSignal),\n writeTextFile: async ({ path, content, encoding, abortSignal }) =>\n writeStream(path, bytesStream(encodeSandboxText(content, encoding)), abortSignal),\n spawn: (options) => spawnProcess(options, false),\n run: async (options): Promise<SandboxRunResultIface> => {\n const process = await spawnProcess({ ...options, durable: false }, true);\n const [stdout, stderr, exit] = await Promise.all([\n collectStream(process.stdout),\n collectStream(process.stderr),\n process.wait(),\n ]);\n return {\n exitCode: exit.exitCode,\n stdout: textDecoder().decode(stdout),\n stderr: textDecoder().decode(stderr),\n };\n },\n stat: async ({ path, abortSignal }) => {\n const resolved = resolvePath(path);\n const stat = await transport.stat({ path: resolved, signal: abortSignal });\n return stat == null ? null : toStatEntry(resolved, stat);\n },\n readDir: async ({ path, abortSignal }): Promise<DirEntryIface[]> => {\n const resolved = resolvePath(path);\n const entries = await transport.readDir({ path: resolved, signal: abortSignal });\n return entries.map((entry) => ({\n name: entry.name,\n path: paths.join(resolved, entry.name),\n type: entry.type,\n size: entry.size,\n }));\n },\n removePath: async ({ path, recursive, force, abortSignal }) => {\n const resolved = resolvePath(path);\n try {\n await transport.remove({\n path: resolved,\n recursive: recursive === true,\n force: force === true,\n signal: abortSignal,\n });\n } catch (error) {\n if (force === true && isNotFoundMessage(errorMessage(error))) return;\n throw error;\n }\n },\n getPortEndpoint: (options) => args.network.getPortEndpoint(options),\n getPortUrl: async (options) => (await args.network.getPortEndpoint(options)).url,\n stop: () => args.network.stop(),\n destroy: () => args.network.destroy(),\n };\n if (transport.processGone != null) session.attachProcess = attachProcess;\n return { ...session, confinedFileReader: createConfinedFileReader(session) };\n};\n\nconst readOnlyRefusal = async (): Promise<never> => {\n throw new Error('this sandbox handle is read-only');\n};\n\n// A passive viewer's view of a handle: reads pass through; writes, processes and\n// lifecycle are refused here as well as by the backend the provider asked.\nexport const readOnlySession = <S extends NetworkSandboxSessionIface>(session: S): S => {\n const restricted: S = {\n ...session,\n writeFile: readOnlyRefusal,\n writeBinaryFile: readOnlyRefusal,\n writeTextFile: readOnlyRefusal,\n spawn: readOnlyRefusal,\n run: readOnlyRefusal,\n removePath: readOnlyRefusal,\n stop: readOnlyRefusal,\n destroy: readOnlyRefusal,\n };\n if (session.setNetworkPolicy != null) restricted.setNetworkPolicy = readOnlyRefusal;\n delete restricted.attachProcess;\n const screen = session.screen;\n if (screen != null)\n restricted.screen = async (options) => {\n if (options?.viewOnly === false) return readOnlyRefusal();\n return screen.call(session, options);\n };\n return restricted;\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["args"]
7
7
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@finalai/final-agent-provider",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "private": false,
5
- "description": "Final's harness and ACP adapter definitions and the general harness provider, computer, device and local sandbox providers, Final's MCP gateway integration, the Final room surface, and external provider channels.",
5
+ "description": "Final's harness and ACP adapter definitions and the general harness provider, computer, device and local sandbox providers, and Final's MCP gateway integration.",
6
6
  "license": "Apache-2.0",
7
7
  "files": [
8
8
  "dist",
9
9
  "README.md",
10
- "WORKSPACE-EGRESS.md",
11
10
  "LICENSE",
12
11
  "NOTICE",
13
12
  "HOSTING.md"
@@ -100,42 +99,7 @@
100
99
  "import": "./dist/modules/sandboxes/local.mjs",
101
100
  "default": "./dist/modules/sandboxes/local.mjs"
102
101
  },
103
- "./sandboxes/access": {
104
- "types": "./dist/modules/sandboxes/access.d.mts",
105
- "import": "./dist/modules/sandboxes/access.mjs",
106
- "default": "./dist/modules/sandboxes/access.mjs"
107
- },
108
- "./channels": {
109
- "types": "./dist/modules/channels/index.d.mts",
110
- "import": "./dist/modules/channels/index.mjs",
111
- "default": "./dist/modules/channels/index.mjs"
112
- },
113
- "./channels/direct-messaging": {
114
- "types": "./dist/modules/channels/direct-messaging.d.mts",
115
- "import": "./dist/modules/channels/direct-messaging.mjs",
116
- "default": "./dist/modules/channels/direct-messaging.mjs"
117
- },
118
- "./channels/group-messaging": {
119
- "types": "./dist/modules/channels/group-messaging.d.mts",
120
- "import": "./dist/modules/channels/group-messaging.mjs",
121
- "default": "./dist/modules/channels/group-messaging.mjs"
122
- },
123
102
  "./package.json": "./package.json",
124
- "./channel-factories": {
125
- "types": "./dist/modules/channel-factories.d.mts",
126
- "import": "./dist/modules/channel-factories.mjs",
127
- "default": "./dist/modules/channel-factories.mjs"
128
- },
129
- "./channels/final": {
130
- "types": "./dist/modules/authoring-final-channel.d.mts",
131
- "import": "./dist/modules/authoring-final-channel.mjs",
132
- "default": "./dist/modules/authoring-final-channel.mjs"
133
- },
134
- "./channels/inbound": {
135
- "types": "./dist/modules/channels/inbound.d.mts",
136
- "import": "./dist/modules/channels/inbound.mjs",
137
- "default": "./dist/modules/channels/inbound.mjs"
138
- },
139
103
  "./harnesses/config-fields": {
140
104
  "types": "./dist/modules/harnesses/config-fields.d.mts",
141
105
  "import": "./dist/modules/harnesses/config-fields.mjs",
@@ -156,21 +120,6 @@
156
120
  "import": "./dist/modules/sandboxes/testing/quoted-shell-arguments.mjs",
157
121
  "default": "./dist/modules/sandboxes/testing/quoted-shell-arguments.mjs"
158
122
  },
159
- "./testing/fake-platform": {
160
- "types": "./dist/modules/channels/fake-platform.d.mts",
161
- "import": "./dist/modules/channels/fake-platform.mjs",
162
- "default": "./dist/modules/channels/fake-platform.mjs"
163
- },
164
- "./sandboxes/egress": {
165
- "types": "./dist/modules/sandboxes/egress.d.mts",
166
- "import": "./dist/modules/sandboxes/egress.mjs",
167
- "default": "./dist/modules/sandboxes/egress.mjs"
168
- },
169
- "./sandboxes/egress-bootstrap": {
170
- "types": "./dist/modules/sandboxes/egress-bootstrap.d.mts",
171
- "import": "./dist/modules/sandboxes/egress-bootstrap.mjs",
172
- "default": "./dist/modules/sandboxes/egress-bootstrap.mjs"
173
- },
174
123
  "./integrations": {
175
124
  "types": "./dist/modules/integrations.d.mts",
176
125
  "import": "./dist/modules/integrations.mjs",
@@ -183,12 +132,11 @@
183
132
  },
184
133
  "dependencies": {
185
134
  "@agentclientprotocol/sdk": "1.8.0",
186
- "@finalai/acp-session": "0.2.0",
187
- "@finalai/agent-protocol": "0.9.0",
188
- "@finalai/agent-provider": "0.10.0",
135
+ "@finalai/agent-protocol": "0.11.0",
136
+ "@finalai/agent-provider": "0.12.0",
189
137
  "@finalai/computers": "0.3.1",
190
138
  "zod": "4.6.6",
191
- "@finalai/agent-definition": "0.9.0"
139
+ "@finalai/agent-definition": "0.11.0"
192
140
  },
193
141
  "engines": {
194
142
  "node": ">=26"