@agentick/sandbox-local 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +211 -0
  2. package/dist/executor/base.d.ts +15 -0
  3. package/dist/executor/base.d.ts.map +1 -0
  4. package/dist/executor/base.js +20 -0
  5. package/dist/executor/base.js.map +1 -0
  6. package/dist/executor/darwin.d.ts +16 -0
  7. package/dist/executor/darwin.d.ts.map +1 -0
  8. package/dist/executor/darwin.js +44 -0
  9. package/dist/executor/darwin.js.map +1 -0
  10. package/dist/executor/linux.d.ts +22 -0
  11. package/dist/executor/linux.d.ts.map +1 -0
  12. package/dist/executor/linux.js +50 -0
  13. package/dist/executor/linux.js.map +1 -0
  14. package/dist/executor/select.d.ts +12 -0
  15. package/dist/executor/select.d.ts.map +1 -0
  16. package/dist/executor/select.js +23 -0
  17. package/dist/executor/select.js.map +1 -0
  18. package/dist/executor/types.d.ts +29 -0
  19. package/dist/executor/types.d.ts.map +1 -0
  20. package/dist/executor/types.js +4 -0
  21. package/dist/executor/types.js.map +1 -0
  22. package/dist/index.d.ts +12 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +12 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/linux/bwrap.d.ts +11 -0
  27. package/dist/linux/bwrap.d.ts.map +1 -0
  28. package/dist/linux/bwrap.js +46 -0
  29. package/dist/linux/bwrap.js.map +1 -0
  30. package/dist/linux/cgroup.d.ts +27 -0
  31. package/dist/linux/cgroup.d.ts.map +1 -0
  32. package/dist/linux/cgroup.js +80 -0
  33. package/dist/linux/cgroup.js.map +1 -0
  34. package/dist/linux/unshare.d.ts +11 -0
  35. package/dist/linux/unshare.d.ts.map +1 -0
  36. package/dist/linux/unshare.js +22 -0
  37. package/dist/linux/unshare.js.map +1 -0
  38. package/dist/local-sandbox.d.ts +42 -0
  39. package/dist/local-sandbox.d.ts.map +1 -0
  40. package/dist/local-sandbox.js +235 -0
  41. package/dist/local-sandbox.js.map +1 -0
  42. package/dist/network/ca.d.ts +38 -0
  43. package/dist/network/ca.d.ts.map +1 -0
  44. package/dist/network/ca.js +143 -0
  45. package/dist/network/ca.js.map +1 -0
  46. package/dist/network/proxy.d.ts +46 -0
  47. package/dist/network/proxy.d.ts.map +1 -0
  48. package/dist/network/proxy.js +144 -0
  49. package/dist/network/proxy.js.map +1 -0
  50. package/dist/network/rules.d.ts +23 -0
  51. package/dist/network/rules.d.ts.map +1 -0
  52. package/dist/network/rules.js +64 -0
  53. package/dist/network/rules.js.map +1 -0
  54. package/dist/paths.d.ts +29 -0
  55. package/dist/paths.d.ts.map +1 -0
  56. package/dist/paths.js +129 -0
  57. package/dist/paths.js.map +1 -0
  58. package/dist/platform/detect.d.ts +17 -0
  59. package/dist/platform/detect.d.ts.map +1 -0
  60. package/dist/platform/detect.js +114 -0
  61. package/dist/platform/detect.js.map +1 -0
  62. package/dist/platform/types.d.ts +16 -0
  63. package/dist/platform/types.d.ts.map +1 -0
  64. package/dist/platform/types.js +4 -0
  65. package/dist/platform/types.js.map +1 -0
  66. package/dist/provider.d.ts +33 -0
  67. package/dist/provider.d.ts.map +1 -0
  68. package/dist/provider.js +137 -0
  69. package/dist/provider.js.map +1 -0
  70. package/dist/resources.d.ts +30 -0
  71. package/dist/resources.d.ts.map +1 -0
  72. package/dist/resources.js +94 -0
  73. package/dist/resources.js.map +1 -0
  74. package/dist/seatbelt/profile.d.ts +30 -0
  75. package/dist/seatbelt/profile.d.ts.map +1 -0
  76. package/dist/seatbelt/profile.js +106 -0
  77. package/dist/seatbelt/profile.js.map +1 -0
  78. package/dist/testing.d.ts +22 -0
  79. package/dist/testing.d.ts.map +1 -0
  80. package/dist/testing.js +39 -0
  81. package/dist/testing.js.map +1 -0
  82. package/dist/workspace.d.ts +30 -0
  83. package/dist/workspace.d.ts.map +1 -0
  84. package/dist/workspace.js +68 -0
  85. package/dist/workspace.js.map +1 -0
  86. package/package.json +64 -0
  87. package/src/index.ts +17 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Local Sandbox Provider
3
+ *
4
+ * Factory function that creates a SandboxProvider backed by OS-level sandboxing.
5
+ */
6
+ import { randomBytes } from "node:crypto";
7
+ import { detectCapabilities, selectStrategy } from "./platform/detect";
8
+ import { selectExecutor } from "./executor/select";
9
+ import { createWorkspace, destroyWorkspace, resolveMounts } from "./workspace";
10
+ import { filterEnv } from "./paths";
11
+ import { ResourceEnforcer } from "./resources";
12
+ import { CgroupManager } from "./linux/cgroup";
13
+ import { LocalSandbox } from "./local-sandbox";
14
+ import { NetworkProxyServer } from "./network/proxy";
15
+ /**
16
+ * Create a local sandbox provider.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { localProvider } from "@agentick/sandbox-local";
21
+ *
22
+ * const provider = localProvider();
23
+ * const sandbox = await provider.create({ workspace: true });
24
+ * const result = await sandbox.exec("echo hello");
25
+ * await sandbox.destroy();
26
+ * ```
27
+ */
28
+ export function localProvider(config) {
29
+ const cleanupDefault = config?.cleanupWorkspace ?? true;
30
+ return {
31
+ name: "local",
32
+ async create(options) {
33
+ const caps = await detectCapabilities();
34
+ const strategy = selectStrategy(caps, config?.strategy);
35
+ // Workspace
36
+ const workspace = await createWorkspace(options.workspace, config?.tmpBase);
37
+ const mounts = await resolveMounts(options.mounts);
38
+ // Permissions
39
+ const permissions = resolvePermissions(options.permissions ?? {}, workspace.path, mounts.map((m) => ({ path: m.hostPath, mode: m.mode })));
40
+ // CgroupManager (Linux only)
41
+ let cgroup;
42
+ if (caps.hasCgroupsV2 && options.limits) {
43
+ const id = randomBytes(4).toString("hex");
44
+ cgroup = new CgroupManager(id);
45
+ await cgroup.create(options.limits);
46
+ }
47
+ // Executor
48
+ const executor = selectExecutor(strategy, cgroup);
49
+ // Environment
50
+ const baseEnv = {
51
+ HOME: workspace.path,
52
+ PATH: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
53
+ TERM: "dumb",
54
+ };
55
+ if (options.permissions?.inheritEnv) {
56
+ Object.assign(baseEnv, filterEnv(process.env));
57
+ }
58
+ if (options.env) {
59
+ Object.assign(baseEnv, options.env);
60
+ }
61
+ // Network proxy
62
+ let proxy;
63
+ const netRules = Array.isArray(options.permissions?.net)
64
+ ? options.permissions.net
65
+ : undefined;
66
+ if (netRules && netRules.length > 0) {
67
+ proxy = new NetworkProxyServer(netRules, config?.network);
68
+ await proxy.start();
69
+ // Inject proxy env vars
70
+ baseEnv.HTTP_PROXY = proxy.proxyUrl;
71
+ baseEnv.http_proxy = proxy.proxyUrl;
72
+ baseEnv.HTTPS_PROXY = proxy.proxyUrl;
73
+ baseEnv.https_proxy = proxy.proxyUrl;
74
+ }
75
+ // Resource enforcement
76
+ const resources = new ResourceEnforcer(workspace.path, options.limits ?? {});
77
+ await resources.start();
78
+ const sandboxId = randomBytes(8).toString("hex");
79
+ return new LocalSandbox({
80
+ id: sandboxId,
81
+ workspacePath: workspace.path,
82
+ executor,
83
+ env: baseEnv,
84
+ mounts,
85
+ permissions,
86
+ resources,
87
+ proxy,
88
+ cleanupWorkspace: cleanupDefault,
89
+ destroyWorkspace: () => destroyWorkspace(workspace.path, workspace.autoCreated && cleanupDefault),
90
+ });
91
+ },
92
+ async restore(snapshot) {
93
+ const caps = await detectCapabilities();
94
+ const strategy = selectStrategy(caps, config?.strategy);
95
+ const executor = selectExecutor(strategy);
96
+ const resources = new ResourceEnforcer(snapshot.workspacePath, {});
97
+ await resources.start();
98
+ return new LocalSandbox({
99
+ id: snapshot.id,
100
+ workspacePath: snapshot.workspacePath,
101
+ executor,
102
+ env: {
103
+ HOME: snapshot.workspacePath,
104
+ PATH: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
105
+ TERM: "dumb",
106
+ },
107
+ mounts: [],
108
+ permissions: {
109
+ readPaths: [snapshot.workspacePath],
110
+ writePaths: [snapshot.workspacePath],
111
+ network: false,
112
+ childProcess: true,
113
+ },
114
+ resources,
115
+ cleanupWorkspace: false,
116
+ destroyWorkspace: async () => { },
117
+ });
118
+ },
119
+ };
120
+ }
121
+ function resolvePermissions(perms, workspacePath, mounts) {
122
+ const readPaths = [workspacePath];
123
+ const writePaths = [workspacePath];
124
+ for (const mount of mounts) {
125
+ readPaths.push(mount.path);
126
+ if (mount.mode === "rw") {
127
+ writePaths.push(mount.path);
128
+ }
129
+ }
130
+ return {
131
+ readPaths,
132
+ writePaths,
133
+ network: perms.net ?? false,
134
+ childProcess: perms.childProcess ?? true,
135
+ };
136
+ }
137
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resource Enforcement
3
+ *
4
+ * Timeout management, disk monitoring, and process tracking.
5
+ * cgroups-based limits are handled separately by CgroupManager (Linux only).
6
+ */
7
+ import type { ChildProcess } from "node:child_process";
8
+ import type { ResourceLimits } from "@agentick/sandbox";
9
+ export declare class ResourceEnforcer {
10
+ private readonly workspacePath;
11
+ private readonly limits;
12
+ private diskTimer?;
13
+ private trackedProcesses;
14
+ private stopped;
15
+ constructor(workspacePath: string, limits: ResourceLimits);
16
+ /** Start resource monitoring. */
17
+ start(): Promise<void>;
18
+ /** Track a child process for cleanup on resource violations. */
19
+ trackProcess(child: ChildProcess): void;
20
+ /**
21
+ * Create an AbortSignal that fires after the given timeout.
22
+ * Falls back to the global timeout limit if no per-command timeout.
23
+ */
24
+ createTimeoutSignal(timeout?: number): AbortSignal | undefined;
25
+ /** Stop all monitoring and kill tracked processes. */
26
+ stop(): Promise<void>;
27
+ private checkDisk;
28
+ private killAllProcesses;
29
+ }
30
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMxD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,SAAS,CAAC,CAAiC;IACnD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,OAAO,CAAS;gBAEZ,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc;IAKzD,iCAAiC;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,gEAAgE;IAChE,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAKvC;;;OAGG;IACH,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAM9D,sDAAsD;IAChD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAYb,SAAS;IAevB,OAAO,CAAC,gBAAgB;CAuBzB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Resource Enforcement
3
+ *
4
+ * Timeout management, disk monitoring, and process tracking.
5
+ * cgroups-based limits are handled separately by CgroupManager (Linux only).
6
+ */
7
+ import { execFile } from "node:child_process";
8
+ import { promisify } from "node:util";
9
+ const execFileAsync = promisify(execFile);
10
+ const DISK_POLL_INTERVAL = 5000; // 5 seconds
11
+ export class ResourceEnforcer {
12
+ workspacePath;
13
+ limits;
14
+ diskTimer;
15
+ trackedProcesses = new Set();
16
+ stopped = false;
17
+ constructor(workspacePath, limits) {
18
+ this.workspacePath = workspacePath;
19
+ this.limits = limits;
20
+ }
21
+ /** Start resource monitoring. */
22
+ async start() {
23
+ if (this.limits.disk) {
24
+ this.diskTimer = setInterval(() => this.checkDisk(), DISK_POLL_INTERVAL);
25
+ this.diskTimer.unref();
26
+ }
27
+ }
28
+ /** Track a child process for cleanup on resource violations. */
29
+ trackProcess(child) {
30
+ this.trackedProcesses.add(child);
31
+ child.on("exit", () => this.trackedProcesses.delete(child));
32
+ }
33
+ /**
34
+ * Create an AbortSignal that fires after the given timeout.
35
+ * Falls back to the global timeout limit if no per-command timeout.
36
+ */
37
+ createTimeoutSignal(timeout) {
38
+ const ms = timeout ?? this.limits.timeout;
39
+ if (!ms)
40
+ return undefined;
41
+ return AbortSignal.timeout(ms);
42
+ }
43
+ /** Stop all monitoring and kill tracked processes. */
44
+ async stop() {
45
+ if (this.stopped)
46
+ return;
47
+ this.stopped = true;
48
+ if (this.diskTimer) {
49
+ clearInterval(this.diskTimer);
50
+ this.diskTimer = undefined;
51
+ }
52
+ this.killAllProcesses();
53
+ }
54
+ async checkDisk() {
55
+ if (!this.limits.disk || this.stopped)
56
+ return;
57
+ try {
58
+ // du -sk works on both macOS and Linux (-sb is Linux-only)
59
+ const { stdout } = await execFileAsync("du", ["-sk", this.workspacePath]);
60
+ const bytes = parseInt(stdout.split("\t")[0], 10) * 1024;
61
+ if (bytes > this.limits.disk) {
62
+ this.killAllProcesses();
63
+ }
64
+ }
65
+ catch {
66
+ // du may fail if workspace was destroyed — ignore
67
+ }
68
+ }
69
+ killAllProcesses() {
70
+ for (const child of this.trackedProcesses) {
71
+ try {
72
+ // Kill process group if possible
73
+ if (child.pid) {
74
+ process.kill(-child.pid, "SIGTERM");
75
+ }
76
+ }
77
+ catch {
78
+ // Process may have already exited
79
+ }
80
+ // Forceful kill after 5 seconds
81
+ setTimeout(() => {
82
+ try {
83
+ if (child.pid) {
84
+ process.kill(-child.pid, "SIGKILL");
85
+ }
86
+ }
87
+ catch {
88
+ // Already gone
89
+ }
90
+ }, 5000).unref();
91
+ }
92
+ }
93
+ }
94
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * macOS Seatbelt Profile Generation
3
+ *
4
+ * Compiles SpawnOptions into Apple Seatbelt Profile Language (SBPL).
5
+ *
6
+ * Security model: "safe by default"
7
+ *
8
+ * SBPL resolves conflicting rules by specificity — more specific wins.
9
+ * At equal specificity, deny beats allow. This lets us:
10
+ *
11
+ * 1. (allow file-read*) — system reads (needed for bash)
12
+ * 2. (deny file-read* (subpath "/Users")) — deny user home dirs
13
+ * 3. (allow file-read* (subpath "{workspace}")) — re-allow workspace
14
+ *
15
+ * The deny at step 2 is more specific than the allow at step 1, so it wins
16
+ * for paths under /Users. The allow at step 3 is more specific than the deny
17
+ * at step 2, so workspace access works even if it's under /Users.
18
+ *
19
+ * This prevents sandboxed processes from reading SSH keys, credentials,
20
+ * browser profiles, and other sensitive user data — while still allowing
21
+ * system libraries and executables to load normally.
22
+ *
23
+ * Write restrictions are always tight: only workspace, mounts, /tmp, /dev.
24
+ */
25
+ import type { SpawnOptions } from "../executor/types";
26
+ /**
27
+ * Compile a seatbelt profile string from spawn options.
28
+ */
29
+ export declare function compileSeatbeltProfile(options: SpawnOptions): string;
30
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/seatbelt/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAqBtD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAqEpE"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * macOS Seatbelt Profile Generation
3
+ *
4
+ * Compiles SpawnOptions into Apple Seatbelt Profile Language (SBPL).
5
+ *
6
+ * Security model: "safe by default"
7
+ *
8
+ * SBPL resolves conflicting rules by specificity — more specific wins.
9
+ * At equal specificity, deny beats allow. This lets us:
10
+ *
11
+ * 1. (allow file-read*) — system reads (needed for bash)
12
+ * 2. (deny file-read* (subpath "/Users")) — deny user home dirs
13
+ * 3. (allow file-read* (subpath "{workspace}")) — re-allow workspace
14
+ *
15
+ * The deny at step 2 is more specific than the allow at step 1, so it wins
16
+ * for paths under /Users. The allow at step 3 is more specific than the deny
17
+ * at step 2, so workspace access works even if it's under /Users.
18
+ *
19
+ * This prevents sandboxed processes from reading SSH keys, credentials,
20
+ * browser profiles, and other sensitive user data — while still allowing
21
+ * system libraries and executables to load normally.
22
+ *
23
+ * Write restrictions are always tight: only workspace, mounts, /tmp, /dev.
24
+ */
25
+ /**
26
+ * Paths that sandboxed processes cannot read.
27
+ *
28
+ * /Users — home directories (SSH keys, .env, browser profiles, credentials)
29
+ * /private/var/root — root's home directory
30
+ * /Volumes — mounted drives, encrypted volumes, network shares
31
+ * /Network — network-mounted resources
32
+ * /Library/Keychains — system-level keychains and certificates
33
+ * /private/var/db/dslocal — local directory service (user account data, password hashes)
34
+ */
35
+ const DENIED_READ_PATHS = [
36
+ "/Users",
37
+ "/private/var/root",
38
+ "/Volumes",
39
+ "/Network",
40
+ "/Library/Keychains",
41
+ "/private/var/db/dslocal",
42
+ ];
43
+ /**
44
+ * Compile a seatbelt profile string from spawn options.
45
+ */
46
+ export function compileSeatbeltProfile(options) {
47
+ const lines = [];
48
+ const emit = (line) => lines.push(line);
49
+ const comment = (text) => emit(`\n;; ${text}`);
50
+ const allow = (...parts) => emit(`(allow ${parts.join(" ")})`);
51
+ const deny = (...parts) => emit(`(deny ${parts.join(" ")})`);
52
+ const subpath = (p) => `(subpath "${p}")`;
53
+ emit("(version 1)");
54
+ deny("default");
55
+ // Process execution
56
+ comment("Process execution");
57
+ allow("process*");
58
+ allow("signal");
59
+ allow("sysctl*");
60
+ // File reads — allow system, deny sensitive, re-allow workspace/mounts.
61
+ // SBPL specificity: subpath filter > unfiltered, so deny(subpath) > allow(*).
62
+ comment("File reads — safe by default");
63
+ allow("file-read*");
64
+ comment("Deny reads to sensitive paths (home dirs, volumes, keychains, etc.)");
65
+ for (const p of DENIED_READ_PATHS) {
66
+ deny("file-read*", subpath(p));
67
+ }
68
+ // Re-allow workspace reads (more specific than /Users deny)
69
+ comment("Re-allow workspace reads");
70
+ allow("file-read*", subpath(options.workspacePath));
71
+ // Re-allow mount reads
72
+ if (options.mounts.length > 0) {
73
+ comment("Re-allow mount reads");
74
+ for (const mount of options.mounts) {
75
+ allow("file-read*", subpath(mount.hostPath));
76
+ }
77
+ }
78
+ // File writes — restricted to workspace, mounts, and temp
79
+ comment("File writes (restricted)");
80
+ allow("file-write*", subpath(options.workspacePath));
81
+ allow("file-write*", subpath("/private/tmp"));
82
+ allow("file-write*", subpath("/tmp"));
83
+ allow("file-write*", subpath("/dev"));
84
+ // Mount writes
85
+ if (options.mounts.length > 0) {
86
+ comment("Mount writes");
87
+ for (const mount of options.mounts) {
88
+ if (mount.mode === "rw") {
89
+ allow("file-write*", subpath(mount.hostPath));
90
+ }
91
+ }
92
+ }
93
+ // Network
94
+ comment("Network");
95
+ const net = options.permissions.network;
96
+ if (net === false) {
97
+ deny("network*");
98
+ }
99
+ else {
100
+ // net === true or NetworkRule[] — allow all at seatbelt level.
101
+ // NetworkRule enforcement happens via the proxy layer, not seatbelt.
102
+ allow("network*");
103
+ }
104
+ return lines.join("\n") + "\n";
105
+ }
106
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/seatbelt/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Sandbox Local Testing Utilities
3
+ *
4
+ * Helpers for testing sandbox consumers and the local provider itself.
5
+ */
6
+ import type { LocalProviderConfig } from "./provider";
7
+ import type { SandboxProvider } from "@agentick/sandbox";
8
+ import type { PlatformCapabilities } from "./platform/types";
9
+ /**
10
+ * Create a test provider with unsandboxed executor by default.
11
+ * Useful for CI and cross-platform tests that don't need OS isolation.
12
+ */
13
+ export declare function createTestProvider(config?: Partial<LocalProviderConfig>): SandboxProvider;
14
+ /** Whether the current platform is macOS. */
15
+ export declare const isDarwin: boolean;
16
+ /** Whether the current platform is Linux. */
17
+ export declare const isLinux: boolean;
18
+ /**
19
+ * Create mock PlatformCapabilities for testing.
20
+ */
21
+ export declare function createMockCapabilities(overrides?: Partial<PlatformCapabilities>): PlatformCapabilities;
22
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,eAAe,CAMzF;AAED,6CAA6C;AAC7C,eAAO,MAAM,QAAQ,SAAgC,CAAC;AAEtD,6CAA6C;AAC7C,eAAO,MAAM,OAAO,SAA+B,CAAC;AAEpD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACxC,oBAAoB,CAatB"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Sandbox Local Testing Utilities
3
+ *
4
+ * Helpers for testing sandbox consumers and the local provider itself.
5
+ */
6
+ import { localProvider } from "./provider";
7
+ /**
8
+ * Create a test provider with unsandboxed executor by default.
9
+ * Useful for CI and cross-platform tests that don't need OS isolation.
10
+ */
11
+ export function createTestProvider(config) {
12
+ return localProvider({
13
+ strategy: "none",
14
+ cleanupWorkspace: true,
15
+ ...config,
16
+ });
17
+ }
18
+ /** Whether the current platform is macOS. */
19
+ export const isDarwin = process.platform === "darwin";
20
+ /** Whether the current platform is Linux. */
21
+ export const isLinux = process.platform === "linux";
22
+ /**
23
+ * Create mock PlatformCapabilities for testing.
24
+ */
25
+ export function createMockCapabilities(overrides) {
26
+ return {
27
+ platform: "darwin",
28
+ arch: "arm64",
29
+ hasSandboxExec: true,
30
+ hasBwrap: false,
31
+ hasUnshare: false,
32
+ hasCgroupsV2: false,
33
+ userNamespaces: false,
34
+ uid: 501,
35
+ recommended: "seatbelt",
36
+ ...overrides,
37
+ };
38
+ }
39
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK3C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAqC;IACtE,OAAO,aAAa,CAAC;QACnB,QAAQ,EAAE,MAAM;QAChB,gBAAgB,EAAE,IAAI;QACtB,GAAG,MAAM;KACV,CAAC,CAAC;AACL,CAAC;AAED,6CAA6C;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAEtD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAEpD;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAyC;IAEzC,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,OAAO;QACb,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,KAAK;QACrB,GAAG,EAAE,GAAG;QACR,WAAW,EAAE,UAAU;QACvB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Workspace Management
3
+ *
4
+ * Create, validate, and destroy workspace directories. Resolve mounts
5
+ * from SandboxCreateOptions into host-path ResolvedMounts.
6
+ */
7
+ import type { Mount } from "@agentick/sandbox";
8
+ import type { ResolvedMount } from "./executor/types";
9
+ /**
10
+ * Create a workspace directory.
11
+ *
12
+ * @param workspace - Explicit path, or `true` for auto-generated temp dir
13
+ * @param tmpBase - Base directory for temp workspaces (default: os.tmpdir())
14
+ * @returns Object with the workspace path and whether it was auto-created
15
+ */
16
+ export declare function createWorkspace(workspace: string | true | undefined, tmpBase?: string): Promise<{
17
+ path: string;
18
+ autoCreated: boolean;
19
+ }>;
20
+ /**
21
+ * Destroy a workspace directory.
22
+ * Only removes auto-created workspaces (safety: never delete user-specified dirs).
23
+ */
24
+ export declare function destroyWorkspace(path: string, autoCreated: boolean): Promise<void>;
25
+ /**
26
+ * Resolve mounts from user-specified Mount[] to ResolvedMount[].
27
+ * Validates that host paths exist and are accessible.
28
+ */
29
+ export declare function resolveMounts(mounts?: Mount[]): Promise<ResolvedMount[]>;
30
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,OAAO,GAAE,MAAiB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CAYjD;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAQxF;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,MAAM,GAAE,KAAK,EAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAqBlF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Workspace Management
3
+ *
4
+ * Create, validate, and destroy workspace directories. Resolve mounts
5
+ * from SandboxCreateOptions into host-path ResolvedMounts.
6
+ */
7
+ import { mkdir, rm, access, realpath } from "node:fs/promises";
8
+ import { constants } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { randomBytes } from "node:crypto";
12
+ /**
13
+ * Create a workspace directory.
14
+ *
15
+ * @param workspace - Explicit path, or `true` for auto-generated temp dir
16
+ * @param tmpBase - Base directory for temp workspaces (default: os.tmpdir())
17
+ * @returns Object with the workspace path and whether it was auto-created
18
+ */
19
+ export async function createWorkspace(workspace, tmpBase = tmpdir()) {
20
+ if (workspace === true || workspace === undefined) {
21
+ const id = randomBytes(8).toString("hex");
22
+ const raw = join(tmpBase, `agentick-sandbox-${id}`);
23
+ await mkdir(raw, { recursive: true, mode: 0o700 });
24
+ // Always return realpath'd (e.g. macOS /var → /private/var)
25
+ return { path: await realpath(raw), autoCreated: true };
26
+ }
27
+ // Explicit path — ensure it exists
28
+ await mkdir(workspace, { recursive: true });
29
+ return { path: await realpath(workspace), autoCreated: false };
30
+ }
31
+ /**
32
+ * Destroy a workspace directory.
33
+ * Only removes auto-created workspaces (safety: never delete user-specified dirs).
34
+ */
35
+ export async function destroyWorkspace(path, autoCreated) {
36
+ if (!autoCreated)
37
+ return;
38
+ try {
39
+ await rm(path, { recursive: true, force: true });
40
+ }
41
+ catch (err) {
42
+ console.warn(`[sandbox-local] Failed to destroy workspace ${path}:`, err);
43
+ }
44
+ }
45
+ /**
46
+ * Resolve mounts from user-specified Mount[] to ResolvedMount[].
47
+ * Validates that host paths exist and are accessible.
48
+ */
49
+ export async function resolveMounts(mounts = []) {
50
+ const resolved = [];
51
+ for (const mount of mounts) {
52
+ // Validate host path exists
53
+ try {
54
+ await access(mount.host, constants.R_OK);
55
+ }
56
+ catch {
57
+ throw new Error(`Mount host path not accessible: ${mount.host}`);
58
+ }
59
+ const hostPath = await realpath(mount.host);
60
+ resolved.push({
61
+ hostPath,
62
+ sandboxPath: mount.sandbox,
63
+ mode: mount.mode ?? "rw",
64
+ });
65
+ }
66
+ return resolved;
67
+ }
68
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAAoC,EACpC,UAAkB,MAAM,EAAE;IAE1B,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAClD,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,4DAA4D;QAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC1D,CAAC;IAED,mCAAmC;IACnC,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,WAAoB;IACvE,IAAI,CAAC,WAAW;QAAE,OAAO;IAEzB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,+CAA+C,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAkB,EAAE;IACtD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,4BAA4B;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE5C,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ;YACR,WAAW,EAAE,KAAK,CAAC,OAAO;YAC1B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;SACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}