@smithers-orchestrator/sandbox 0.20.3 → 0.21.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.
package/src/index.d.ts CHANGED
@@ -7,6 +7,7 @@ type SandboxBundleManifest$1 = {
7
7
  status: "finished" | "failed" | "cancelled";
8
8
  runId?: string;
9
9
  patches?: string[];
10
+ diffBundle?: SandboxDiffBundleLike;
10
11
  };
11
12
 
12
13
  type ValidatedSandboxBundle$1 = {
@@ -39,6 +40,7 @@ declare function writeSandboxBundle(params: {
39
40
  path: string;
40
41
  content: string;
41
42
  }>;
43
+ diffBundle?: unknown;
42
44
  }): Promise<void>;
43
45
  /** @typedef {import("./SandboxBundleManifest.ts").SandboxBundleManifest} SandboxBundleManifest */
44
46
  /** @typedef {import("./ValidatedSandboxBundle.ts").ValidatedSandboxBundle} ValidatedSandboxBundle */
@@ -55,12 +57,34 @@ type ValidatedSandboxBundle = ValidatedSandboxBundle$1;
55
57
 
56
58
  type SandboxRuntime$1 = "bubblewrap" | "docker" | "codeplane";
57
59
 
60
+ type SandboxPortMapping = {
61
+ host: number;
62
+ container: number;
63
+ };
64
+ type SandboxVolumeMount = {
65
+ host: string;
66
+ container: string;
67
+ readonly?: boolean;
68
+ };
69
+ type SandboxWorkspaceSpec = {
70
+ name: string;
71
+ snapshotId?: string;
72
+ idleTimeoutSecs?: number;
73
+ persistence?: "ephemeral" | "sticky";
74
+ };
58
75
  type SandboxTransportConfig$1 = {
59
76
  runId: string;
60
77
  sandboxId: string;
61
78
  runtime: SandboxRuntime$1;
62
79
  rootDir: string;
63
80
  image?: string;
81
+ allowNetwork?: boolean;
82
+ env?: Record<string, string>;
83
+ ports?: SandboxPortMapping[];
84
+ volumes?: SandboxVolumeMount[];
85
+ memoryLimit?: string;
86
+ cpuLimit?: string;
87
+ workspace?: SandboxWorkspaceSpec;
64
88
  };
65
89
 
66
90
  type SandboxHandle = {
@@ -70,6 +94,14 @@ type SandboxHandle = {
70
94
  sandboxRoot: string;
71
95
  requestPath: string;
72
96
  resultPath: string;
97
+ image?: string;
98
+ allowNetwork?: boolean;
99
+ env?: Record<string, string>;
100
+ ports?: SandboxPortMapping[];
101
+ volumes?: SandboxVolumeMount[];
102
+ memoryLimit?: string;
103
+ cpuLimit?: string;
104
+ workspace?: SandboxWorkspaceSpec;
73
105
  containerId?: string;
74
106
  workspaceId?: string;
75
107
  };
@@ -113,12 +145,71 @@ type ExecuteSandboxChildWorkflow = (parentWorkflow: SandboxWorkflow | undefined,
113
145
  status: string;
114
146
  output: unknown;
115
147
  }>;
148
+ type SandboxBundleStatus = "finished" | "failed" | "cancelled";
149
+ type SandboxDiffBundleLike = {
150
+ seq: number;
151
+ baseRef: string;
152
+ patches: Array<{
153
+ path: string;
154
+ operation: "add" | "modify" | "delete";
155
+ diff: string;
156
+ binaryContent?: string;
157
+ }>;
158
+ };
159
+ type SandboxProviderRequest = {
160
+ runId: string;
161
+ sandboxId: string;
162
+ input?: unknown;
163
+ rootDir: string;
164
+ requestBundlePath: string;
165
+ resultBundlePath: string;
166
+ workflow: SandboxChildWorkflowDefinition;
167
+ parentWorkflow?: SandboxWorkflow;
168
+ executeChildWorkflow: ExecuteSandboxChildWorkflow;
169
+ allowNetwork: boolean;
170
+ maxOutputBytes: number;
171
+ toolTimeoutMs: number;
172
+ config: Record<string, unknown>;
173
+ signal?: AbortSignal;
174
+ heartbeat: (data?: unknown) => void;
175
+ };
176
+ type SandboxProviderResult = {
177
+ bundlePath: string;
178
+ remoteRunId?: string;
179
+ workspaceId?: string;
180
+ containerId?: string;
181
+ } | {
182
+ status: SandboxBundleStatus;
183
+ output?: unknown;
184
+ outputs?: unknown;
185
+ runId?: string;
186
+ remoteRunId?: string;
187
+ workspaceId?: string;
188
+ containerId?: string;
189
+ diffBundle?: SandboxDiffBundleLike;
190
+ patches?: Array<{
191
+ path: string;
192
+ content: string;
193
+ }>;
194
+ artifacts?: Array<{
195
+ path: string;
196
+ content: string;
197
+ }>;
198
+ streamLogPath?: string | null;
199
+ };
200
+ type SandboxProvider = {
201
+ id: string;
202
+ run: (request: SandboxProviderRequest) => Promise<SandboxProviderResult> | SandboxProviderResult;
203
+ cleanup?: (request: SandboxProviderRequest) => Promise<void> | void;
204
+ };
116
205
  type ExecuteSandboxOptions$1 = {
117
206
  parentWorkflow?: SandboxWorkflow;
118
207
  sandboxId: string;
208
+ provider?: SandboxProvider | string;
119
209
  runtime?: SandboxRuntime$1;
120
210
  workflow: SandboxChildWorkflowDefinition;
121
211
  executeChildWorkflow: ExecuteSandboxChildWorkflow;
212
+ applyDiffBundle?: (bundle: SandboxDiffBundleLike, targetDir: string) => Promise<void>;
122
213
  input?: unknown;
123
214
  rootDir: string;
124
215
  allowNetwork: boolean;
@@ -126,9 +217,13 @@ type ExecuteSandboxOptions$1 = {
126
217
  toolTimeoutMs: number;
127
218
  reviewDiffs?: boolean;
128
219
  autoAcceptDiffs?: boolean;
220
+ allowNested?: boolean;
129
221
  config?: Record<string, unknown>;
130
222
  };
131
223
 
224
+ declare function registerSandboxProvider(provider: SandboxProvider): () => void;
225
+ declare function resolveSandboxProvider(value: unknown): SandboxProvider | undefined;
226
+
132
227
  /**
133
228
  * @param {ExecuteSandboxOptions} options
134
229
  * @returns {Promise<unknown>}
@@ -161,4 +256,4 @@ type SandboxBundleResult = SandboxBundleResult$1;
161
256
  type SandboxTransportConfig = SandboxTransportConfig$1;
162
257
  type SandboxRuntime = SandboxRuntime$1;
163
258
 
164
- export { type ExecuteSandboxOptions, SANDBOX_BUNDLE_OUTPUT_MAX_ARRAY_LENGTH, SANDBOX_BUNDLE_OUTPUT_MAX_DEPTH, SANDBOX_BUNDLE_OUTPUT_MAX_STRING_LENGTH, SANDBOX_BUNDLE_PATH_MAX_LENGTH, SANDBOX_BUNDLE_RUN_ID_MAX_LENGTH, SANDBOX_MAX_BUNDLE_BYTES, SANDBOX_MAX_PATCH_FILES, SANDBOX_MAX_README_BYTES, type SandboxBundleManifest, type SandboxBundleResult, SandboxTransport, type SandboxTransportConfig, type SmithersEvent, type ValidatedSandboxBundle, executeSandbox, layerForSandboxRuntime, makeSandboxTransportLayer, resolveSandboxRuntime, validateSandboxBundle, writeSandboxBundle };
259
+ export { type ExecuteSandboxOptions, SANDBOX_BUNDLE_OUTPUT_MAX_ARRAY_LENGTH, SANDBOX_BUNDLE_OUTPUT_MAX_DEPTH, SANDBOX_BUNDLE_OUTPUT_MAX_STRING_LENGTH, SANDBOX_BUNDLE_PATH_MAX_LENGTH, SANDBOX_BUNDLE_RUN_ID_MAX_LENGTH, SANDBOX_MAX_BUNDLE_BYTES, SANDBOX_MAX_PATCH_FILES, SANDBOX_MAX_README_BYTES, type SandboxBundleManifest, type SandboxBundleResult, type SandboxBundleStatus, type SandboxDiffBundleLike, type SandboxProvider, type SandboxProviderRequest, type SandboxProviderResult, SandboxTransport, type SandboxTransportConfig, type SmithersEvent, type ValidatedSandboxBundle, executeSandbox, layerForSandboxRuntime, makeSandboxTransportLayer, registerSandboxProvider, resolveSandboxProvider, resolveSandboxRuntime, validateSandboxBundle, writeSandboxBundle };
@@ -50,11 +50,7 @@ export function assertPathWithinRootEffect(rootDir, resolvedPath) {
50
50
  if (code && code !== "ENOENT" && code !== "ENOTDIR") {
51
51
  return yield* Effect.fail(err);
52
52
  }
53
- const parent = dirname(current);
54
- if (parent === current) {
55
- return yield* Effect.fail(new SmithersError("TOOL_PATH_ESCAPE", "Path escapes sandbox root (via symlink)"));
56
- }
57
- current = parent;
53
+ current = dirname(current);
58
54
  }
59
55
  });
60
56
  }
package/src/transport.js CHANGED
@@ -6,10 +6,10 @@
6
6
  // @smithers-type-exports-end
7
7
 
8
8
  import { Context, Effect, Layer } from "effect";
9
+ import { SmithersError } from "@smithers-orchestrator/errors/SmithersError";
9
10
  import { CodeplaneSandboxExecutorLive, DockerSandboxExecutorLive, } from "./effect/http-runner.js";
10
11
  import { makeSandboxTransportServiceEffect, } from "./effect/sandbox-entity.js";
11
12
  import { BubblewrapSandboxExecutorLive } from "./effect/socket-runner.js";
12
- import {} from "@smithers-orchestrator/errors/SmithersError";
13
13
  /** @typedef {import("./SandboxRuntime.ts").SandboxRuntime} SandboxRuntime */
14
14
 
15
15
  const SandboxTransportTag = /** @type {Context.TagClass<SandboxTransport, "SandboxTransport", SandboxTransportService>} */ (
@@ -35,8 +35,11 @@ export function layerForSandboxRuntime(runtime) {
35
35
  case "codeplane":
36
36
  return makeSandboxTransportLayer(CodeplaneSandboxExecutorLive);
37
37
  case "bubblewrap":
38
- default:
39
38
  return makeSandboxTransportLayer(BubblewrapSandboxExecutorLive);
39
+ default:
40
+ throw new SmithersError("INVALID_INPUT", `Unsupported sandbox runtime: ${String(runtime)}`, {
41
+ runtime,
42
+ });
40
43
  }
41
44
  }
42
45
  /**
@@ -44,8 +47,10 @@ export function layerForSandboxRuntime(runtime) {
44
47
  * @returns {SandboxRuntime}
45
48
  */
46
49
  export function resolveSandboxRuntime(requested) {
47
- if (requested !== "docker")
48
- return requested;
49
- const hasDocker = typeof Bun !== "undefined" ? Boolean(Bun.which("docker")) : false;
50
- return hasDocker ? "docker" : "bubblewrap";
50
+ if (requested !== "docker" && requested !== "codeplane" && requested !== "bubblewrap") {
51
+ throw new SmithersError("INVALID_INPUT", `Unsupported sandbox runtime: ${String(requested)}`, {
52
+ runtime: requested,
53
+ });
54
+ }
55
+ return requested;
51
56
  }