@hatchet-dev/sandbox 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { HatchetClient } from '@hatchet-dev/typescript-sdk/v1';
2
+ import { z } from 'zod';
2
3
  import * as fs from 'fs/promises';
3
4
 
4
5
  // src/sandbox.ts
@@ -10,10 +11,40 @@ var FilesystemError = class extends Error {
10
11
  }
11
12
  code;
12
13
  };
13
- var toEntry = (e) => ({
14
- ...e,
15
- modifiedTime: e.modifiedTime ? new Date(e.modifiedTime) : void 0
14
+ var path = z.string().min(1);
15
+ var positiveInt = z.int().positive();
16
+ var httpsUrl = z.url({ protocol: /^https$/ });
17
+ var fileData = z.union([
18
+ z.string(),
19
+ z.instanceof(Uint8Array),
20
+ z.instanceof(ArrayBuffer),
21
+ z.instanceof(Blob)
22
+ ]);
23
+ var writeEntries = z.strictObject({ path, data: fileData }).array();
24
+ var readOpts = z.strictObject({ format: z.enum(["text", "bytes", "blob"]).optional() });
25
+ var listOpts = z.strictObject({ depth: positiveInt.optional() });
26
+ var transferOpts = z.strictObject({ timeoutMs: positiveInt.optional() });
27
+ var entry = z.looseObject({
28
+ name: z.string(),
29
+ path: z.string(),
30
+ type: z.enum(["file", "dir"]),
31
+ size: z.number(),
32
+ mode: z.number(),
33
+ permissions: z.string(),
34
+ modifiedTime: z.coerce.date().optional()
16
35
  });
36
+ var fsOutput = z.looseObject({
37
+ content: z.string().optional(),
38
+ stagedKey: z.string().optional(),
39
+ url: z.string().optional(),
40
+ putUrl: z.string().optional(),
41
+ getUrl: z.string().optional(),
42
+ entry: entry.nullish(),
43
+ entries: entry.array().optional(),
44
+ created: z.boolean().optional(),
45
+ error: z.object({ code: z.string(), message: z.string() }).optional()
46
+ });
47
+ var fsOutputWithEntry = fsOutput.extend({ entry });
17
48
  var STAGE_OVER_BYTES = 2 << 20;
18
49
  async function toBytes(data) {
19
50
  if (typeof data === "string") return Buffer.from(data, "utf8");
@@ -49,16 +80,18 @@ var Files = class {
49
80
  this.turn = turn;
50
81
  }
51
82
  turn;
52
- async call(fn, input, fresh = false) {
53
- const out = await this.turn(`$fs.${fn}`, input, fresh);
54
- if (out.error) throw new FilesystemError(out.error.code, out.error.message);
55
- return out;
56
- }
57
- async read(path, opts = {}) {
58
- const out = await this.call("read", { path });
83
+ async call(fn, input, fresh = false, schema = fsOutput) {
84
+ const out = fsOutput.parse(await this.turn(`$fs.${fn}`, input, fresh));
85
+ if (out.error)
86
+ throw new FilesystemError(out.error.code, out.error.message);
87
+ return schema.parse(out);
88
+ }
89
+ async read(p, opts = {}) {
90
+ const { format } = readOpts.parse(opts);
91
+ const out = await this.call("read", { path: path.parse(p) });
59
92
  const bytes = out.url ? await this.readStaged(out.url, out.stagedKey) : Buffer.from(out.content ?? "", "base64");
60
- if (opts.format === "bytes") return new Uint8Array(bytes);
61
- if (opts.format === "blob") return new Blob([new Uint8Array(bytes)]);
93
+ if (format === "bytes") return new Uint8Array(bytes);
94
+ if (format === "blob") return new Blob([new Uint8Array(bytes)]);
62
95
  return bytes.toString("utf8");
63
96
  }
64
97
  /** A replayed durable read may hold a URL that has expired; the provider signs the same staged file again. The renewal is a plain run, not a durable child, so the replayed child sequence stays aligned. */
@@ -73,11 +106,12 @@ var Files = class {
73
106
  }
74
107
  async write(pathOrFiles, data) {
75
108
  if (typeof pathOrFiles !== "string") return this.writeFiles(pathOrFiles);
76
- const [entry] = await this.writeFiles([{ path: pathOrFiles, data: data ?? "" }]);
77
- return entry;
109
+ const [entry2] = await this.writeFiles([{ path: pathOrFiles, data: data ?? "" }]);
110
+ return entry2;
78
111
  }
79
112
  /** Writes several files in one task. */
80
113
  async writeFiles(files) {
114
+ writeEntries.parse(files);
81
115
  const bytes = await Promise.all(files.map((f) => toBytes(f.data)));
82
116
  const encoded = [];
83
117
  for (const [i, f] of files.entries()) {
@@ -97,58 +131,70 @@ var Files = class {
97
131
  }
98
132
  }
99
133
  const { entries = [] } = await this.call("write", { files: encoded });
100
- return entries.map(toEntry);
134
+ return entries;
101
135
  }
102
136
  /** Lists a directory. `depth` 1 (default) is the directory itself; higher values recurse. No snapshot is made. */
103
- async list(path = ".", opts = {}) {
104
- const { entries = [] } = await this.call("list", { path, depth: opts.depth ?? 1 });
105
- return entries.map(toEntry);
137
+ async list(p = ".", opts = {}) {
138
+ const { depth = 1 } = listOpts.parse(opts);
139
+ const { entries = [] } = await this.call("list", { path: path.parse(p), depth });
140
+ return entries;
106
141
  }
107
142
  /** True if the path exists. No snapshot is made. */
108
- async exists(path) {
109
- const { entry } = await this.call("stat", { path });
110
- return entry != null;
143
+ async exists(p) {
144
+ const { entry: entry2 } = await this.call("stat", { path: path.parse(p) });
145
+ return entry2 != null;
111
146
  }
112
147
  /** Metadata of a file or directory. Throws `FilesystemError` with code `not_found` if absent. */
113
- async getInfo(path) {
114
- const { entry } = await this.call("stat", { path });
115
- if (!entry) throw new FilesystemError("not_found", `${path} does not exist`);
116
- return toEntry(entry);
148
+ async getInfo(p) {
149
+ const { entry: entry2 } = await this.call("stat", { path: path.parse(p) });
150
+ if (!entry2) throw new FilesystemError("not_found", `${p} does not exist`);
151
+ return entry2;
117
152
  }
118
153
  /** Creates a directory and its parents. Returns false if it already existed. */
119
- async makeDir(path) {
120
- const { created } = await this.call("mkdir", { path });
154
+ async makeDir(p) {
155
+ const { created } = await this.call("mkdir", { path: path.parse(p) });
121
156
  return created === true;
122
157
  }
123
158
  /** Renames or moves a file or directory. */
124
159
  async rename(oldPath, newPath) {
125
- const { entry } = await this.call("rename", { path: oldPath, newPath });
126
- return toEntry(entry);
160
+ const { entry: entry2 } = await this.call(
161
+ "rename",
162
+ { path: path.parse(oldPath), newPath: path.parse(newPath) },
163
+ false,
164
+ fsOutputWithEntry
165
+ );
166
+ return entry2;
127
167
  }
128
168
  /** Copies a file or directory tree. */
129
169
  async copy(srcPath, dstPath) {
130
- const { entry } = await this.call("copy", { path: srcPath, newPath: dstPath });
131
- return toEntry(entry);
170
+ const { entry: entry2 } = await this.call(
171
+ "copy",
172
+ { path: path.parse(srcPath), newPath: path.parse(dstPath) },
173
+ false,
174
+ fsOutputWithEntry
175
+ );
176
+ return entry2;
132
177
  }
133
178
  /** Deletes a file or directory tree. */
134
- async remove(path) {
135
- await this.call("remove", { path });
179
+ async remove(p) {
180
+ await this.call("remove", { path: path.parse(p) });
136
181
  }
137
182
  /** The provider fetches an https URL into the workspace. The sandbox needs no network. Private and loopback addresses are refused. */
138
- async download(url, path, opts = {}) {
139
- const { entry } = await this.call("download", {
140
- url,
141
- path,
142
- ...opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}
143
- });
144
- return toEntry(entry);
183
+ async download(url, p, opts = {}) {
184
+ const { entry: entry2 } = await this.call(
185
+ "download",
186
+ { url: httpsUrl.parse(url), path: path.parse(p), ...transferOpts.parse(opts) },
187
+ false,
188
+ fsOutputWithEntry
189
+ );
190
+ return entry2;
145
191
  }
146
192
  /** The provider sends a workspace file to an https URL with HTTP PUT, for example a presigned URL. */
147
- async upload(path, url, opts = {}) {
193
+ async upload(p, url, opts = {}) {
148
194
  await this.call("upload", {
149
- path,
150
- url,
151
- ...opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}
195
+ path: path.parse(p),
196
+ url: httpsUrl.parse(url),
197
+ ...transferOpts.parse(opts)
152
198
  });
153
199
  }
154
200
  };
@@ -170,6 +216,43 @@ async function setupTelemetry() {
170
216
  console.error(`sandbox: opentelemetry disabled: ${err.message}`);
171
217
  }
172
218
  }
219
+ var positiveInt2 = z.int().positive();
220
+ var metadata = z.record(z.string(), z.string());
221
+ var resources = z.strictObject({
222
+ vcpu: positiveInt2.optional(),
223
+ memoryMib: positiveInt2.optional(),
224
+ diskMib: positiveInt2.optional()
225
+ });
226
+ var turnInput = z.strictObject({
227
+ fn: z.string().min(1),
228
+ input: z.record(z.string(), z.unknown()),
229
+ sandboxId: z.string().min(1).optional(),
230
+ image: z.string().min(1).optional(),
231
+ snapshotId: z.string().min(1).optional(),
232
+ metadata: metadata.optional(),
233
+ idleTtlMs: positiveInt2.optional(),
234
+ inheritMetadata: z.boolean().optional(),
235
+ resources: resources.optional()
236
+ });
237
+ var turnResult = z.looseObject({
238
+ output: z.looseObject({}),
239
+ sandboxId: z.string(),
240
+ snapshotId: z.string().optional(),
241
+ timings: z.record(z.string(), z.number()).optional()
242
+ });
243
+ var commandOutput = z.looseObject({
244
+ stdout: z.string(),
245
+ stderr: z.string(),
246
+ exitCode: z.int()
247
+ });
248
+ var sandboxInfo = z.looseObject({
249
+ sandboxId: z.string(),
250
+ metadata: metadata.optional(),
251
+ live: z.boolean(),
252
+ latestSnapshot: z.string().optional(),
253
+ createdAt: z.coerce.date(),
254
+ lastUsed: z.coerce.date().optional()
255
+ });
173
256
 
174
257
  // src/sandbox.ts
175
258
  var TASK_NAMES = ["hatchet-sandbox", "brickie-sandbox"];
@@ -207,6 +290,11 @@ function resolveTaskName(client) {
207
290
  }
208
291
  return pending;
209
292
  }
293
+ var positiveInt3 = z.int().positive();
294
+ var nonEmpty = z.string().min(1);
295
+ var commandResult = commandOutput.extend(
296
+ turnResult.pick({ snapshotId: true, timings: true }).shape
297
+ );
210
298
  var UNITS = {
211
299
  K: 1e3,
212
300
  M: 1e6,
@@ -217,38 +305,55 @@ var UNITS = {
217
305
  Gi: 2 ** 30,
218
306
  Ti: 2 ** 40
219
307
  };
220
- function toMib(value, field) {
221
- if (typeof value === "number") {
222
- if (!Number.isInteger(value) || value <= 0)
223
- throw new Error(`resources.${field}: expected a positive whole number of MiB`);
224
- return value;
225
- }
226
- const m = /^(\d+(?:\.\d+)?)\s*([KMGT]i?)?B?$/.exec(value.trim());
227
- if (!m)
228
- throw new Error(
229
- `resources.${field}: expected a quantity like '512Mi', '4Gi' or '8G', got ${JSON.stringify(value)}`
230
- );
231
- const bytes = Number(m[1]) * (m[2] ? UNITS[m[2]] : UNITS.Mi);
232
- const mib = Math.ceil(bytes / UNITS.Mi);
233
- if (mib <= 0) throw new Error(`resources.${field}: must be at least 1Mi`);
234
- return mib;
235
- }
236
- function wireResources(r) {
237
- const out = {};
238
- if (r.vcpu !== void 0) {
239
- if (!Number.isInteger(r.vcpu) || r.vcpu <= 0)
240
- throw new Error("resources.vcpu: expected a positive whole number of cores");
241
- out.vcpu = r.vcpu;
242
- }
243
- if (r.memory !== void 0) out.memoryMib = toMib(r.memory, "memory");
244
- if (r.disk !== void 0) out.diskMib = toMib(r.disk, "disk");
245
- if (Object.keys(out).length === 0)
246
- throw new Error("resources: set at least one of vcpu, memory, disk");
247
- return out;
248
- }
308
+ var QUANTITY = /^(\d+(?:\.\d+)?)\s*([KMGT]i?)B?$/;
309
+ var mib = z.union(
310
+ [
311
+ positiveInt3,
312
+ z.string().trim().regex(QUANTITY).transform((s) => {
313
+ const [, n, unit] = QUANTITY.exec(s);
314
+ return Math.ceil(Number(n) * UNITS[unit] / UNITS.Mi);
315
+ }).pipe(z.int().min(1))
316
+ ],
317
+ {
318
+ error: "expected a positive whole number of MiB or a quantity with a unit like '512Mi', '4Gi' or '8G'"
319
+ }
320
+ );
321
+ var resources2 = z.strictObject({
322
+ vcpu: positiveInt3.optional(),
323
+ memory: mib.optional(),
324
+ disk: mib.optional()
325
+ }).refine(
326
+ (r) => r.vcpu !== void 0 || r.memory !== void 0 || r.disk !== void 0,
327
+ "set at least one of vcpu, memory, disk"
328
+ ).transform(({ vcpu, memory, disk }) => ({ vcpu, memoryMib: memory, diskMib: disk }));
329
+ var sandboxOpts = z.strictObject({
330
+ id: z.string().regex(/^[a-z0-9-]+$/, "lowercase letters, digits, and hyphens only").optional(),
331
+ template: nonEmpty.optional(),
332
+ from: nonEmpty.optional(),
333
+ metadata: metadata.optional(),
334
+ idleTimeoutMs: positiveInt3.optional(),
335
+ inheritParentMetadata: z.boolean().optional(),
336
+ provider: nonEmpty.optional(),
337
+ resources: resources2.optional()
338
+ }).refine((o) => !o.inheritParentMetadata || o.from !== void 0, {
339
+ error: "inheritParentMetadata needs from",
340
+ path: ["inheritParentMetadata"]
341
+ });
342
+ var execOpts = z.strictObject({ timeoutMs: positiveInt3.optional() });
343
+ var connectOpts = z.strictObject({ template: nonEmpty.optional() });
344
+ var listOpts2 = z.strictObject({
345
+ sandboxId: nonEmpty.optional(),
346
+ metadata: metadata.optional()
347
+ });
348
+ var deleteOpts = listOpts2.refine(
349
+ (o) => o.sandboxId !== void 0 || Object.keys(o.metadata ?? {}).length > 0,
350
+ "delete needs a sandboxId or a metadata filter"
351
+ );
249
352
  function turnRunner(client) {
250
353
  const resolved = resolveTaskName(client);
251
- return async (input, opts) => {
354
+ return async (raw, opts) => {
355
+ const input = turnInput.parse(raw);
356
+ const payload = input;
252
357
  const name = await resolved;
253
358
  const additionalMetadata = {
254
359
  "hatchet.sandbox.fn": input.fn,
@@ -256,10 +361,10 @@ function turnRunner(client) {
256
361
  ...input.image ? { "hatchet.sandbox.image": input.image } : {},
257
362
  ...input.snapshotId ? { "hatchet.sandbox.from": input.snapshotId } : {}
258
363
  };
259
- const result = opts?.fresh ? await (await client.admin.runWorkflow(name, input, {
364
+ const result = opts?.fresh ? await (await client.admin.runWorkflow(name, payload, {
260
365
  additionalMetadata
261
- })).result() : await client.workflow({ name }).run(input, { additionalMetadata });
262
- return result[name] ?? result;
366
+ })).result() : await client.workflow({ name }).run(payload, { additionalMetadata });
367
+ return turnResult.parse(result[name] ?? result);
263
368
  };
264
369
  }
265
370
  var Sandbox = class _Sandbox {
@@ -276,54 +381,40 @@ var Sandbox = class _Sandbox {
276
381
  files;
277
382
  /** Starts a new sandbox. Prefer `hatchet.sandbox.create`. */
278
383
  static async create(client, opts = {}) {
384
+ const o = sandboxOpts.parse(opts);
279
385
  await setupTelemetry();
280
386
  const run = turnRunner(client);
281
- const metadata = opts.provider ? { ...opts.metadata, provider: opts.provider } : opts.metadata;
282
387
  const created = await run({
283
388
  fn: "$create",
284
389
  input: {},
285
- ...opts.id ? { sandboxId: opts.id } : {},
286
- ...opts.template ? { image: opts.template } : {},
287
- ...opts.from ? { snapshotId: opts.from } : {},
288
- ...metadata ? { metadata } : {},
289
- ...opts.idleTimeoutMs ? { idleTtlMs: opts.idleTimeoutMs } : {},
290
- ...opts.inheritParentMetadata ? { inheritMetadata: true } : {},
291
- ...opts.resources ? { resources: wireResources(opts.resources) } : {}
390
+ sandboxId: o.id,
391
+ image: o.template,
392
+ snapshotId: o.from,
393
+ metadata: o.provider ? { ...o.metadata, provider: o.provider } : o.metadata,
394
+ idleTtlMs: o.idleTimeoutMs,
395
+ inheritMetadata: o.inheritParentMetadata,
396
+ resources: o.resources
292
397
  });
293
- return new _Sandbox(run, created.sandboxId, opts.template);
398
+ return new _Sandbox(run, created.sandboxId, o.template);
294
399
  }
295
400
  /** Attaches to a sandbox by ID. Prefer `hatchet.sandbox.connect`. */
296
401
  static async connect(client, sandboxId, opts = {}) {
402
+ const id = nonEmpty.parse(sandboxId);
403
+ const o = connectOpts.parse(opts);
297
404
  await setupTelemetry();
298
405
  const run = turnRunner(client);
299
- await run({
300
- fn: "$connect",
301
- input: {},
302
- sandboxId,
303
- ...opts.template ? { image: opts.template } : {}
304
- });
305
- return new _Sandbox(run, sandboxId, opts.template);
406
+ await run({ fn: "$connect", input: {}, sandboxId: id, image: o.template });
407
+ return new _Sandbox(run, id, o.template);
306
408
  }
307
409
  /** Lists sandboxes on the provider. Prefer `hatchet.sandbox.list`. */
308
410
  static async list(client, opts = {}) {
309
- const result = await turnRunner(client)({
310
- fn: "$list",
311
- input: {
312
- ...opts.sandboxId ? { sandboxId: opts.sandboxId } : {},
313
- ...opts.metadata ? { metadata: opts.metadata } : {}
314
- }
315
- });
316
- const raw = result.output.sandboxes ?? [];
317
- return raw.map((s) => ({
318
- ...s,
319
- createdAt: new Date(s.createdAt),
320
- lastUsed: s.lastUsed ? new Date(s.lastUsed) : void 0
321
- }));
411
+ const o = listOpts2.parse(opts);
412
+ const result = await turnRunner(client)({ fn: "$list", input: o });
413
+ return sandboxInfo.array().parse(result.output.sandboxes ?? []);
322
414
  }
323
415
  /** Deletes every sandbox matching the filter, with all their snapshots and files. Prefer `hatchet.sandbox.delete`. */
324
416
  static async delete(client, opts) {
325
- if (!opts.sandboxId && Object.keys(opts.metadata ?? {}).length === 0)
326
- throw new Error("delete needs a sandboxId or a metadata filter");
417
+ deleteOpts.parse(opts);
327
418
  const run = turnRunner(client);
328
419
  const ids = [];
329
420
  for (const { sandboxId } of await _Sandbox.list(client, opts)) {
@@ -334,10 +425,8 @@ var Sandbox = class _Sandbox {
334
425
  }
335
426
  /** Runs a shell command with `sh -c` in the workspace and makes a snapshot. A timeout gives `exitCode` 124, not an error. */
336
427
  async exec(cmd, opts = {}) {
337
- return this.turn("$command", {
338
- cmd,
339
- ...opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}
340
- });
428
+ const input = { cmd: nonEmpty.parse(cmd), ...execOpts.parse(opts) };
429
+ return commandResult.parse(await this.turn("$command", input));
341
430
  }
342
431
  /** Removes the sandbox. Its snapshots stay; `connect` can bring it back. */
343
432
  async kill() {
@@ -349,12 +438,7 @@ var Sandbox = class _Sandbox {
349
438
  }
350
439
  async turn(fn, input, fresh = false) {
351
440
  const result = await this.run(
352
- {
353
- sandboxId: this.sandboxId,
354
- ...this.template ? { image: this.template } : {},
355
- fn,
356
- input
357
- },
441
+ { sandboxId: this.sandboxId, image: this.template, fn, input },
358
442
  { fresh }
359
443
  );
360
444
  return {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/files.ts","../src/otel.ts","../src/sandbox.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import * as fs from 'node:fs/promises';\nimport type { JsonObject } from '@hatchet-dev/typescript-sdk/v1';\n\nexport type FileType = 'file' | 'dir';\n\nexport interface EntryInfo {\n name: string;\n path: string;\n type: FileType;\n size: number;\n mode: number;\n permissions: string;\n modifiedTime?: Date;\n}\n\nexport type FileData = string | ArrayBuffer | Uint8Array | Blob;\n\nexport interface WriteEntry {\n path: string;\n data: FileData;\n}\n\nexport interface ReadOpts {\n format?: 'text' | 'bytes' | 'blob';\n}\n\nexport interface TransferOpts {\n /** Give up after this long. */\n timeoutMs?: number;\n}\n\nexport interface ListOpts {\n depth?: number;\n}\n\nexport type FilesystemErrorCode =\n | 'staging_failed'\n | 'not_found'\n | 'invalid_path'\n | 'invalid_url'\n | 'invalid_content'\n | 'invalid'\n | 'is_a_directory'\n | 'not_a_directory'\n | 'too_large'\n | 'transfer_failed';\n\n/** Thrown for caller mistakes such as a missing file or a path outside the workspace. */\nexport class FilesystemError extends Error {\n constructor(\n readonly code: FilesystemErrorCode,\n message: string\n ) {\n super(message);\n this.name = 'FilesystemError';\n }\n}\n\ntype RawEntry = Omit<EntryInfo, 'modifiedTime'> & { modifiedTime?: string };\n\ninterface FsOutput extends JsonObject {\n content?: string;\n stagedKey?: string;\n url?: string;\n putUrl?: string;\n getUrl?: string;\n entry?: RawEntry | null;\n entries?: RawEntry[];\n created?: boolean;\n error?: { code: FilesystemErrorCode; message: string };\n}\n\n/** @internal */\nexport type FsTurn = (fn: string, input: JsonObject, fresh?: boolean) => Promise<FsOutput>;\n\nconst toEntry = (e: RawEntry): EntryInfo => ({\n ...e,\n modifiedTime: e.modifiedTime ? new Date(e.modifiedTime) : undefined,\n});\n\nconst STAGE_OVER_BYTES = 2 << 20;\n\nasync function toBytes(data: FileData): Promise<Buffer> {\n if (typeof data === 'string') return Buffer.from(data, 'utf8');\n if (data instanceof Blob) return Buffer.from(await data.arrayBuffer());\n if (data instanceof Uint8Array) return Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n return Buffer.from(data);\n}\n\nasync function putStaged(url: string, bytes: Buffer): Promise<void> {\n if (url.startsWith('file://')) {\n await fs.writeFile(decodeURIComponent(url.slice('file://'.length)), bytes);\n return;\n }\n const res = await fetch(url, {\n method: 'PUT',\n body: new Uint8Array(bytes),\n headers: { 'Content-Type': 'application/octet-stream' },\n });\n if (!res.ok)\n throw new FilesystemError('staging_failed', `stage upload failed: HTTP ${res.status}`);\n}\n\nasync function getStaged(url: string): Promise<Buffer> {\n if (url.startsWith('file://')) {\n return fs.readFile(decodeURIComponent(url.slice('file://'.length)));\n }\n const res = await fetch(url);\n if (!res.ok)\n throw new FilesystemError('staging_failed', `stage download failed: HTTP ${res.status}`);\n return Buffer.from(await res.arrayBuffer());\n}\n/** File operations on a sandbox workspace. Paths are relative to the workspace. Each call is one Hatchet task. */\nexport class Files {\n /** @internal */\n constructor(private readonly turn: FsTurn) {}\n\n private async call(fn: string, input: JsonObject, fresh = false): Promise<FsOutput> {\n const out = await this.turn(`$fs.${fn}`, input, fresh);\n if (out.error) throw new FilesystemError(out.error.code, out.error.message);\n return out;\n }\n\n /** Reads a file as text (default), bytes, or a Blob. Files over the provider's `--max-file-bytes` (2 MiB) come through the provider's `--store` instead of Hatchet. */\n read(path: string, opts?: ReadOpts & { format?: 'text' }): Promise<string>;\n read(path: string, opts: ReadOpts & { format: 'bytes' }): Promise<Uint8Array>;\n read(path: string, opts: ReadOpts & { format: 'blob' }): Promise<Blob>;\n async read(path: string, opts: ReadOpts = {}): Promise<string | Uint8Array | Blob> {\n const out = await this.call('read', { path });\n const bytes = out.url\n ? await this.readStaged(out.url, out.stagedKey!)\n : Buffer.from(out.content ?? '', 'base64');\n if (opts.format === 'bytes') return new Uint8Array(bytes);\n if (opts.format === 'blob') return new Blob([new Uint8Array(bytes)]);\n return bytes.toString('utf8');\n }\n\n /** A replayed durable read may hold a URL that has expired; the provider signs the same staged file again. The renewal is a plain run, not a durable child, so the replayed child sequence stays aligned. */\n private async readStaged(url: string, stagedKey: string): Promise<Buffer> {\n try {\n return await getStaged(url);\n } catch (e) {\n if (url.startsWith('file://') || !(e instanceof FilesystemError)) throw e;\n const { getUrl } = await this.call('presign', { stagedKey }, true);\n return getStaged(getUrl!);\n }\n }\n\n /** Writes one file or several. Parent directories are created. Bytes are stored exactly. Files over 2 MiB go through the provider's `--store` instead of Hatchet. */\n write(path: string, data: FileData): Promise<EntryInfo>;\n write(files: WriteEntry[]): Promise<EntryInfo[]>;\n async write(\n pathOrFiles: string | WriteEntry[],\n data?: FileData\n ): Promise<EntryInfo | EntryInfo[]> {\n if (typeof pathOrFiles !== 'string') return this.writeFiles(pathOrFiles);\n const [entry] = await this.writeFiles([{ path: pathOrFiles, data: data ?? '' }]);\n return entry;\n }\n\n /** Writes several files in one task. */\n async writeFiles(files: WriteEntry[]): Promise<EntryInfo[]> {\n const bytes = await Promise.all(files.map((f) => toBytes(f.data)));\n const encoded: Array<{ path: string; content?: string; stagedKey?: string }> = [];\n for (const [i, f] of files.entries()) {\n const b = bytes[i];\n if (b.length <= STAGE_OVER_BYTES) {\n encoded.push({ path: f.path, content: b.toString('base64') });\n continue;\n }\n const { stagedKey, putUrl } = await this.call('presign', {});\n try {\n await putStaged(putUrl!, b);\n encoded.push({ path: f.path, stagedKey: stagedKey! });\n } catch {\n const again = await this.call('presign', {}, true);\n await putStaged(again.putUrl!, b);\n encoded.push({ path: f.path, stagedKey: again.stagedKey! });\n }\n }\n const { entries = [] } = await this.call('write', { files: encoded });\n return entries.map(toEntry);\n }\n\n /** Lists a directory. `depth` 1 (default) is the directory itself; higher values recurse. No snapshot is made. */\n async list(path = '.', opts: ListOpts = {}): Promise<EntryInfo[]> {\n const { entries = [] } = await this.call('list', { path, depth: opts.depth ?? 1 });\n return entries.map(toEntry);\n }\n\n /** True if the path exists. No snapshot is made. */\n async exists(path: string): Promise<boolean> {\n const { entry } = await this.call('stat', { path });\n return entry != null;\n }\n\n /** Metadata of a file or directory. Throws `FilesystemError` with code `not_found` if absent. */\n async getInfo(path: string): Promise<EntryInfo> {\n const { entry } = await this.call('stat', { path });\n if (!entry) throw new FilesystemError('not_found', `${path} does not exist`);\n return toEntry(entry);\n }\n\n /** Creates a directory and its parents. Returns false if it already existed. */\n async makeDir(path: string): Promise<boolean> {\n const { created } = await this.call('mkdir', { path });\n return created === true;\n }\n\n /** Renames or moves a file or directory. */\n async rename(oldPath: string, newPath: string): Promise<EntryInfo> {\n const { entry } = await this.call('rename', { path: oldPath, newPath });\n return toEntry(entry!);\n }\n\n /** Copies a file or directory tree. */\n async copy(srcPath: string, dstPath: string): Promise<EntryInfo> {\n const { entry } = await this.call('copy', { path: srcPath, newPath: dstPath });\n return toEntry(entry!);\n }\n\n /** Deletes a file or directory tree. */\n async remove(path: string): Promise<void> {\n await this.call('remove', { path });\n }\n /** The provider fetches an https URL into the workspace. The sandbox needs no network. Private and loopback addresses are refused. */\n async download(url: string, path: string, opts: TransferOpts = {}): Promise<EntryInfo> {\n const { entry } = await this.call('download', {\n url,\n path,\n ...(opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}),\n });\n return toEntry(entry!);\n }\n /** The provider sends a workspace file to an https URL with HTTP PUT, for example a presigned URL. */\n async upload(path: string, url: string, opts: TransferOpts = {}): Promise<void> {\n await this.call('upload', {\n path,\n url,\n ...(opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}),\n });\n }\n}\n","let telemetryStarted = false;\n\nexport async function setupTelemetry(): Promise<void> {\n if (\n telemetryStarted ||\n process.env.HATCHET_SANDBOX_OTEL === 'false' ||\n process.env.BRICKIE_OTEL === 'false'\n ) {\n return;\n }\n telemetryStarted = true;\n try {\n const [{ registerInstrumentations }, { HatchetInstrumentor }] = await Promise.all([\n import('@opentelemetry/instrumentation'),\n import('@hatchet-dev/typescript-sdk/opentelemetry/index.js'),\n ]);\n registerInstrumentations({ instrumentations: [new HatchetInstrumentor()] });\n } catch (err) {\n console.error(`sandbox: opentelemetry disabled: ${(err as Error).message}`);\n }\n}\n","import { HatchetClient, JsonObject } from '@hatchet-dev/typescript-sdk/v1';\nimport { Files } from './files.js';\nimport { setupTelemetry } from './otel.js';\n\nconst TASK_NAMES = ['hatchet-sandbox', 'brickie-sandbox'];\nconst taskNames = new WeakMap<HatchetClient, Promise<string>>();\n\nasync function registered(client: HatchetClient, name: string): Promise<boolean> {\n const namespace = client.config.namespace ?? '';\n const full = name.startsWith(namespace) ? name : `${namespace}${name}`;\n for (let offset = 0; ;) {\n const { rows = [] } = await client.workflows.list({ name: full, limit: 100, offset });\n if (rows.some((w) => w.name === full)) return true;\n if (rows.length === 0) return false;\n offset += rows.length;\n }\n}\n\nasync function probe(client: HatchetClient): Promise<string | undefined> {\n for (const name of TASK_NAMES) {\n if (await registered(client, name)) return name;\n }\n return undefined;\n}\n\nfunction resolveTaskName(client: HatchetClient): Promise<string> {\n let pending = taskNames.get(client);\n if (!pending) {\n pending = probe(client).then(\n (name) => {\n if (!name) taskNames.delete(client);\n return name ?? TASK_NAMES[TASK_NAMES.length - 1];\n },\n (err) => {\n taskNames.delete(client);\n throw err;\n }\n );\n taskNames.set(client, pending);\n }\n return pending;\n}\n\ninterface TurnInput extends JsonObject {\n sandboxId?: string;\n image?: string;\n fn: string;\n input: JsonObject;\n snapshotId?: string;\n metadata?: Record<string, string>;\n idleTtlMs?: number;\n inheritMetadata?: boolean;\n}\n\ninterface TurnResult extends JsonObject {\n output: JsonObject;\n sandboxId: string;\n snapshotId?: string;\n timings?: Record<string, number>;\n}\n\nexport interface Timings {\n /** Snapshot made after this turn. Absent for turns that do not change the workspace. */\n snapshotId?: string;\n /** Milliseconds per phase: `claim`, `restore`, `exec`, `checkpoint`. */\n timings?: Record<string, number>;\n}\n\nexport interface CommandResult extends Timings {\n stdout: string;\n stderr: string;\n /** A non-zero code is a normal result, not an error. */\n exitCode: number;\n}\n\nexport interface SandboxOpts {\n /** Sandbox ID to use instead of a generated one. Lowercase letters, digits, and hyphens; must be new on the provider. */\n id?: string;\n /** Container image. Defaults to the provider's image. */\n template?: string;\n /** Snapshot to start from. Two sandboxes with the same `from` are a fork. */\n from?: string;\n /** Key-value tags, used to find the sandbox again with {@link SandboxNamespace.list}. */\n metadata?: Record<string, string>;\n /** Milliseconds without a turn before the provider removes the sandbox. Capped by the provider. */\n idleTimeoutMs?: number;\n /** With `from`, start from the metadata of the sandbox that made that snapshot. Pairs given in `metadata` take precedence over inherited ones. */\n inheritParentMetadata?: boolean;\n /** Name of the sandbox provider to create on. Required when the tenant has more than one; with `from`, it must be the provider that holds the snapshot. */\n provider?: string;\n /** Machine size. Providers that cannot honour a field fail the create with their own message. Providers that do not know the option ignore it. */\n resources?: Resources;\n}\n\nexport interface Resources {\n /** Whole cores. */\n vcpu?: number;\n /** A number is MiB. A string takes a Kubernetes quantity such as `'512Mi'`, `'4Gi'` or `'8G'`. */\n memory?: number | string;\n /** Same format as `memory`. */\n disk?: number | string;\n}\n\nconst UNITS: Record<string, number> = {\n K: 1e3,\n M: 1e6,\n G: 1e9,\n T: 1e12,\n Ki: 2 ** 10,\n Mi: 2 ** 20,\n Gi: 2 ** 30,\n Ti: 2 ** 40,\n};\n\nfunction toMib(value: number | string, field: string): number {\n if (typeof value === 'number') {\n if (!Number.isInteger(value) || value <= 0)\n throw new Error(`resources.${field}: expected a positive whole number of MiB`);\n return value;\n }\n const m = /^(\\d+(?:\\.\\d+)?)\\s*([KMGT]i?)?B?$/.exec(value.trim());\n if (!m)\n throw new Error(\n `resources.${field}: expected a quantity like '512Mi', '4Gi' or '8G', got ${JSON.stringify(value)}`\n );\n const bytes = Number(m[1]) * (m[2] ? UNITS[m[2]] : UNITS.Mi);\n const mib = Math.ceil(bytes / UNITS.Mi);\n if (mib <= 0) throw new Error(`resources.${field}: must be at least 1Mi`);\n return mib;\n}\n\nfunction wireResources(r: Resources): JsonObject {\n const out: JsonObject = {};\n if (r.vcpu !== undefined) {\n if (!Number.isInteger(r.vcpu) || r.vcpu <= 0)\n throw new Error('resources.vcpu: expected a positive whole number of cores');\n out.vcpu = r.vcpu;\n }\n if (r.memory !== undefined) out.memoryMib = toMib(r.memory, 'memory');\n if (r.disk !== undefined) out.diskMib = toMib(r.disk, 'disk');\n if (Object.keys(out).length === 0)\n throw new Error('resources: set at least one of vcpu, memory, disk');\n return out;\n}\n\nexport interface ExecOpts {\n /** Kill the command after this long. The result then has `exitCode` 124. */\n timeoutMs?: number;\n}\n\nexport interface ConnectOpts {\n /** Image to use if the sandbox has to be started again. Defaults to the provider's image. */\n template?: string;\n}\n\nexport interface SandboxListOpts {\n /** Only the sandbox with this ID. */\n sandboxId?: string;\n /** Only sandboxes whose metadata contains every one of these pairs. */\n metadata?: Record<string, string>;\n}\n\nexport interface SandboxInfo {\n sandboxId: string;\n metadata?: Record<string, string>;\n /** True while the sandbox is running. A sandbox that is not live is started again by `connect`. */\n live: boolean;\n latestSnapshot?: string;\n createdAt: Date;\n lastUsed?: Date;\n}\n\ntype RunTurn = (input: TurnInput, opts?: { fresh?: boolean }) => Promise<TurnResult>;\n\nfunction turnRunner(client: HatchetClient): RunTurn {\n const resolved = resolveTaskName(client);\n return async (input, opts) => {\n const name = await resolved;\n const additionalMetadata = {\n 'hatchet.sandbox.fn': input.fn,\n ...(input.sandboxId ? { 'hatchet.sandbox.id': input.sandboxId } : {}),\n ...(input.image ? { 'hatchet.sandbox.image': input.image } : {}),\n ...(input.snapshotId ? { 'hatchet.sandbox.from': input.snapshotId } : {}),\n };\n const result = opts?.fresh\n ? await (\n await client.admin.runWorkflow<TurnInput, Record<string, TurnResult>>(name, input, {\n additionalMetadata,\n })\n ).result()\n : await client\n .workflow<TurnInput, Record<string, TurnResult>>({ name })\n .run(input, { additionalMetadata });\n return result[name] ?? (result as unknown as TurnResult);\n };\n}\n\n/** One sandbox. Every method is one Hatchet task on the tenant's sandbox provider. */\nexport class Sandbox {\n /** File operations on the workspace. */\n readonly files: Files;\n\n private constructor(\n private readonly run: RunTurn,\n readonly sandboxId: string,\n private readonly template?: string\n ) {\n this.files = new Files((fn, input, fresh) => this.turn(fn, input, fresh));\n }\n\n /** Starts a new sandbox. Prefer `hatchet.sandbox.create`. */\n static async create(client: HatchetClient, opts: SandboxOpts = {}): Promise<Sandbox> {\n await setupTelemetry();\n const run = turnRunner(client);\n const metadata = opts.provider ? { ...opts.metadata, provider: opts.provider } : opts.metadata;\n const created = await run({\n fn: '$create',\n input: {},\n ...(opts.id ? { sandboxId: opts.id } : {}),\n ...(opts.template ? { image: opts.template } : {}),\n ...(opts.from ? { snapshotId: opts.from } : {}),\n ...(metadata ? { metadata } : {}),\n ...(opts.idleTimeoutMs ? { idleTtlMs: opts.idleTimeoutMs } : {}),\n ...(opts.inheritParentMetadata ? { inheritMetadata: true } : {}),\n ...(opts.resources ? { resources: wireResources(opts.resources) } : {}),\n });\n return new Sandbox(run, created.sandboxId, opts.template);\n }\n\n /** Attaches to a sandbox by ID. Prefer `hatchet.sandbox.connect`. */\n static async connect(\n client: HatchetClient,\n sandboxId: string,\n opts: ConnectOpts = {}\n ): Promise<Sandbox> {\n await setupTelemetry();\n const run = turnRunner(client);\n await run({\n fn: '$connect',\n input: {},\n sandboxId,\n ...(opts.template ? { image: opts.template } : {}),\n });\n return new Sandbox(run, sandboxId, opts.template);\n }\n\n /** Lists sandboxes on the provider. Prefer `hatchet.sandbox.list`. */\n static async list(client: HatchetClient, opts: SandboxListOpts = {}): Promise<SandboxInfo[]> {\n const result = await turnRunner(client)({\n fn: '$list',\n input: {\n ...(opts.sandboxId ? { sandboxId: opts.sandboxId } : {}),\n ...(opts.metadata ? { metadata: opts.metadata } : {}),\n },\n });\n const raw = (result.output.sandboxes ?? []) as Array<\n Omit<SandboxInfo, 'createdAt' | 'lastUsed'> & { createdAt: string; lastUsed?: string }\n >;\n return raw.map((s) => ({\n ...s,\n createdAt: new Date(s.createdAt),\n lastUsed: s.lastUsed ? new Date(s.lastUsed) : undefined,\n }));\n }\n\n /** Deletes every sandbox matching the filter, with all their snapshots and files. Prefer `hatchet.sandbox.delete`. */\n static async delete(client: HatchetClient, opts: SandboxListOpts): Promise<string[]> {\n if (!opts.sandboxId && Object.keys(opts.metadata ?? {}).length === 0)\n throw new Error('delete needs a sandboxId or a metadata filter');\n const run = turnRunner(client);\n const ids: string[] = [];\n for (const { sandboxId } of await Sandbox.list(client, opts)) {\n await run({ fn: '$delete', input: {}, sandboxId });\n ids.push(sandboxId);\n }\n return ids;\n }\n\n /** Runs a shell command with `sh -c` in the workspace and makes a snapshot. A timeout gives `exitCode` 124, not an error. */\n async exec(cmd: string, opts: ExecOpts = {}): Promise<CommandResult> {\n return this.turn<CommandResult>('$command', {\n cmd,\n ...(opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}),\n });\n }\n\n /** Removes the sandbox. Its snapshots stay; `connect` can bring it back. */\n async kill(): Promise<void> {\n await this.turn('$destroy', {});\n }\n\n /** Removes the sandbox and deletes every snapshot and file the provider stored for it. `connect` fails afterwards. */\n async delete(): Promise<void> {\n await this.turn('$delete', {});\n }\n\n private async turn<T = JsonObject>(fn: string, input: JsonObject, fresh = false): Promise<T> {\n const result = await this.run(\n {\n sandboxId: this.sandboxId,\n ...(this.template ? { image: this.template } : {}),\n fn,\n input,\n },\n { fresh }\n );\n return {\n ...result.output,\n snapshotId: result.snapshotId,\n timings: result.timings,\n } as unknown as T;\n }\n}\n\n/** `hatchet.sandbox`, added to `HatchetClient` by importing `@hatchet-dev/sandbox`. */\nexport interface SandboxNamespace {\n /** Starts a new sandbox. Inside a durable task this is a durable step. */\n create(opts?: SandboxOpts): Promise<Sandbox>;\n /** Attaches to a sandbox by ID. If it is not running, the provider starts it from its latest snapshot. */\n connect(sandboxId: string, opts?: ConnectOpts): Promise<Sandbox>;\n /** Lists sandboxes the provider knows, filtered by ID or metadata. */\n list(opts?: SandboxListOpts): Promise<SandboxInfo[]>;\n /** Deletes the sandboxes matching the filter, with every snapshot and file stored for them. Returns their IDs. */\n delete(opts: SandboxListOpts): Promise<string[]>;\n}\n\ndeclare module '@hatchet-dev/typescript-sdk/v1' {\n interface HatchetClient {\n readonly sandbox: SandboxNamespace;\n }\n}\n\nObject.defineProperty(HatchetClient.prototype, 'sandbox', {\n configurable: true,\n get(this: HatchetClient): SandboxNamespace {\n return {\n create: (opts) => Sandbox.create(this, opts),\n connect: (sandboxId, opts) => Sandbox.connect(this, sandboxId, opts),\n list: (opts) => Sandbox.list(this, opts),\n delete: (opts) => Sandbox.delete(this, opts),\n };\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/files.ts","../src/otel.ts","../src/wire.ts","../src/sandbox.ts"],"names":["entry","positiveInt","z","resources","listOpts"],"mappings":"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","file":"index.js","sourcesContent":["import * as fs from 'node:fs/promises';\nimport type { JsonObject } from '@hatchet-dev/typescript-sdk/v1';\nimport { z } from 'zod';\n\nexport type FileType = 'file' | 'dir';\n\nexport interface EntryInfo {\n name: string;\n path: string;\n type: FileType;\n size: number;\n mode: number;\n permissions: string;\n modifiedTime?: Date;\n}\n\nexport type FileData = string | ArrayBuffer | Uint8Array | Blob;\n\nexport interface WriteEntry {\n path: string;\n data: FileData;\n}\n\nexport interface ReadOpts {\n format?: 'text' | 'bytes' | 'blob';\n}\n\nexport interface TransferOpts {\n /** Give up after this long. */\n timeoutMs?: number;\n}\n\nexport interface ListOpts {\n depth?: number;\n}\n\nexport type FilesystemErrorCode =\n | 'staging_failed'\n | 'not_found'\n | 'invalid_path'\n | 'invalid_url'\n | 'invalid_content'\n | 'invalid'\n | 'is_a_directory'\n | 'not_a_directory'\n | 'too_large'\n | 'transfer_failed';\n\n/** Thrown for caller mistakes such as a missing file or a path outside the workspace. */\nexport class FilesystemError extends Error {\n constructor(\n readonly code: FilesystemErrorCode,\n message: string\n ) {\n super(message);\n this.name = 'FilesystemError';\n }\n}\n\nconst path = z.string().min(1);\nconst positiveInt = z.int().positive();\nconst httpsUrl = z.url({ protocol: /^https$/ });\nconst fileData = z.union([\n z.string(),\n z.instanceof(Uint8Array),\n z.instanceof(ArrayBuffer),\n z.instanceof(Blob),\n]);\nconst writeEntries = z.strictObject({ path, data: fileData }).array();\nconst readOpts = z.strictObject({ format: z.enum(['text', 'bytes', 'blob']).optional() });\nconst listOpts = z.strictObject({ depth: positiveInt.optional() });\nconst transferOpts = z.strictObject({ timeoutMs: positiveInt.optional() });\n\nconst entry = z.looseObject({\n name: z.string(),\n path: z.string(),\n type: z.enum(['file', 'dir']),\n size: z.number(),\n mode: z.number(),\n permissions: z.string(),\n modifiedTime: z.coerce.date().optional(),\n});\n\nconst fsOutput = z.looseObject({\n content: z.string().optional(),\n stagedKey: z.string().optional(),\n url: z.string().optional(),\n putUrl: z.string().optional(),\n getUrl: z.string().optional(),\n entry: entry.nullish(),\n entries: entry.array().optional(),\n created: z.boolean().optional(),\n error: z.object({ code: z.string(), message: z.string() }).optional(),\n});\ntype FsOutput = z.infer<typeof fsOutput>;\nconst fsOutputWithEntry = fsOutput.extend({ entry });\n\n/** @internal */\nexport type FsTurn = (fn: string, input: JsonObject, fresh?: boolean) => Promise<JsonObject>;\n\nconst STAGE_OVER_BYTES = 2 << 20;\n\nasync function toBytes(data: FileData): Promise<Buffer> {\n if (typeof data === 'string') return Buffer.from(data, 'utf8');\n if (data instanceof Blob) return Buffer.from(await data.arrayBuffer());\n if (data instanceof Uint8Array) return Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n return Buffer.from(data);\n}\n\nasync function putStaged(url: string, bytes: Buffer): Promise<void> {\n if (url.startsWith('file://')) {\n await fs.writeFile(decodeURIComponent(url.slice('file://'.length)), bytes);\n return;\n }\n const res = await fetch(url, {\n method: 'PUT',\n body: new Uint8Array(bytes),\n headers: { 'Content-Type': 'application/octet-stream' },\n });\n if (!res.ok)\n throw new FilesystemError('staging_failed', `stage upload failed: HTTP ${res.status}`);\n}\n\nasync function getStaged(url: string): Promise<Buffer> {\n if (url.startsWith('file://')) {\n return fs.readFile(decodeURIComponent(url.slice('file://'.length)));\n }\n const res = await fetch(url);\n if (!res.ok)\n throw new FilesystemError('staging_failed', `stage download failed: HTTP ${res.status}`);\n return Buffer.from(await res.arrayBuffer());\n}\n/** File operations on a sandbox workspace. Paths are relative to the workspace. Each call is one Hatchet task. */\nexport class Files {\n /** @internal */\n constructor(private readonly turn: FsTurn) {}\n\n private call(fn: string, input: JsonObject, fresh?: boolean): Promise<FsOutput>;\n private call<S extends z.ZodType<FsOutput>>(\n fn: string,\n input: JsonObject,\n fresh: boolean,\n schema: S\n ): Promise<z.infer<S>>;\n private async call(\n fn: string,\n input: JsonObject,\n fresh = false,\n schema: z.ZodType<FsOutput> = fsOutput\n ): Promise<FsOutput> {\n const out = fsOutput.parse(await this.turn(`$fs.${fn}`, input, fresh));\n if (out.error)\n throw new FilesystemError(out.error.code as FilesystemErrorCode, out.error.message);\n return schema.parse(out);\n }\n\n /** Reads a file as text (default), bytes, or a Blob. Files over the provider's `--max-file-bytes` (2 MiB) come through the provider's `--store` instead of Hatchet. */\n read(path: string, opts?: ReadOpts & { format?: 'text' }): Promise<string>;\n read(path: string, opts: ReadOpts & { format: 'bytes' }): Promise<Uint8Array>;\n read(path: string, opts: ReadOpts & { format: 'blob' }): Promise<Blob>;\n async read(p: string, opts: ReadOpts = {}): Promise<string | Uint8Array | Blob> {\n const { format } = readOpts.parse(opts);\n const out = await this.call('read', { path: path.parse(p) });\n const bytes = out.url\n ? await this.readStaged(out.url, out.stagedKey!)\n : Buffer.from(out.content ?? '', 'base64');\n if (format === 'bytes') return new Uint8Array(bytes);\n if (format === 'blob') return new Blob([new Uint8Array(bytes)]);\n return bytes.toString('utf8');\n }\n\n /** A replayed durable read may hold a URL that has expired; the provider signs the same staged file again. The renewal is a plain run, not a durable child, so the replayed child sequence stays aligned. */\n private async readStaged(url: string, stagedKey: string): Promise<Buffer> {\n try {\n return await getStaged(url);\n } catch (e) {\n if (url.startsWith('file://') || !(e instanceof FilesystemError)) throw e;\n const { getUrl } = await this.call('presign', { stagedKey }, true);\n return getStaged(getUrl!);\n }\n }\n\n /** Writes one file or several. Parent directories are created. Bytes are stored exactly. Files over 2 MiB go through the provider's `--store` instead of Hatchet. */\n write(path: string, data: FileData): Promise<EntryInfo>;\n write(files: WriteEntry[]): Promise<EntryInfo[]>;\n async write(\n pathOrFiles: string | WriteEntry[],\n data?: FileData\n ): Promise<EntryInfo | EntryInfo[]> {\n if (typeof pathOrFiles !== 'string') return this.writeFiles(pathOrFiles);\n const [entry] = await this.writeFiles([{ path: pathOrFiles, data: data ?? '' }]);\n return entry;\n }\n\n /** Writes several files in one task. */\n async writeFiles(files: WriteEntry[]): Promise<EntryInfo[]> {\n writeEntries.parse(files);\n const bytes = await Promise.all(files.map((f) => toBytes(f.data)));\n const encoded: Array<{ path: string; content?: string; stagedKey?: string }> = [];\n for (const [i, f] of files.entries()) {\n const b = bytes[i];\n if (b.length <= STAGE_OVER_BYTES) {\n encoded.push({ path: f.path, content: b.toString('base64') });\n continue;\n }\n const { stagedKey, putUrl } = await this.call('presign', {});\n try {\n await putStaged(putUrl!, b);\n encoded.push({ path: f.path, stagedKey: stagedKey! });\n } catch {\n const again = await this.call('presign', {}, true);\n await putStaged(again.putUrl!, b);\n encoded.push({ path: f.path, stagedKey: again.stagedKey! });\n }\n }\n const { entries = [] } = await this.call('write', { files: encoded });\n return entries;\n }\n\n /** Lists a directory. `depth` 1 (default) is the directory itself; higher values recurse. No snapshot is made. */\n async list(p = '.', opts: ListOpts = {}): Promise<EntryInfo[]> {\n const { depth = 1 } = listOpts.parse(opts);\n const { entries = [] } = await this.call('list', { path: path.parse(p), depth });\n return entries;\n }\n\n /** True if the path exists. No snapshot is made. */\n async exists(p: string): Promise<boolean> {\n const { entry } = await this.call('stat', { path: path.parse(p) });\n return entry != null;\n }\n\n /** Metadata of a file or directory. Throws `FilesystemError` with code `not_found` if absent. */\n async getInfo(p: string): Promise<EntryInfo> {\n const { entry } = await this.call('stat', { path: path.parse(p) });\n if (!entry) throw new FilesystemError('not_found', `${p} does not exist`);\n return entry;\n }\n\n /** Creates a directory and its parents. Returns false if it already existed. */\n async makeDir(p: string): Promise<boolean> {\n const { created } = await this.call('mkdir', { path: path.parse(p) });\n return created === true;\n }\n\n /** Renames or moves a file or directory. */\n async rename(oldPath: string, newPath: string): Promise<EntryInfo> {\n const { entry } = await this.call(\n 'rename',\n { path: path.parse(oldPath), newPath: path.parse(newPath) },\n false,\n fsOutputWithEntry\n );\n return entry;\n }\n\n /** Copies a file or directory tree. */\n async copy(srcPath: string, dstPath: string): Promise<EntryInfo> {\n const { entry } = await this.call(\n 'copy',\n { path: path.parse(srcPath), newPath: path.parse(dstPath) },\n false,\n fsOutputWithEntry\n );\n return entry;\n }\n\n /** Deletes a file or directory tree. */\n async remove(p: string): Promise<void> {\n await this.call('remove', { path: path.parse(p) });\n }\n /** The provider fetches an https URL into the workspace. The sandbox needs no network. Private and loopback addresses are refused. */\n async download(url: string, p: string, opts: TransferOpts = {}): Promise<EntryInfo> {\n const { entry } = await this.call(\n 'download',\n { url: httpsUrl.parse(url), path: path.parse(p), ...transferOpts.parse(opts) },\n false,\n fsOutputWithEntry\n );\n return entry;\n }\n /** The provider sends a workspace file to an https URL with HTTP PUT, for example a presigned URL. */\n async upload(p: string, url: string, opts: TransferOpts = {}): Promise<void> {\n await this.call('upload', {\n path: path.parse(p),\n url: httpsUrl.parse(url),\n ...transferOpts.parse(opts),\n });\n }\n}\n","let telemetryStarted = false;\n\nexport async function setupTelemetry(): Promise<void> {\n if (\n telemetryStarted ||\n process.env.HATCHET_SANDBOX_OTEL === 'false' ||\n process.env.BRICKIE_OTEL === 'false'\n ) {\n return;\n }\n telemetryStarted = true;\n try {\n const [{ registerInstrumentations }, { HatchetInstrumentor }] = await Promise.all([\n import('@opentelemetry/instrumentation'),\n import('@hatchet-dev/typescript-sdk/opentelemetry/index.js'),\n ]);\n registerInstrumentations({ instrumentations: [new HatchetInstrumentor()] });\n } catch (err) {\n console.error(`sandbox: opentelemetry disabled: ${(err as Error).message}`);\n }\n}\n","import { z } from 'zod';\n\nconst positiveInt = z.int().positive();\n\n/** Tags on a sandbox. */\nexport const metadata = z.record(z.string(), z.string());\n\n/** Machine size as the provider receives it. Sizes are MiB. */\nexport const resources = z.strictObject({\n vcpu: positiveInt.optional(),\n memoryMib: positiveInt.optional(),\n diskMib: positiveInt.optional(),\n});\n\n/** Input of one sandbox task run. `fn` names the operation, such as `$create`, `$command` or `$fs.read`. */\nexport const turnInput = z.strictObject({\n fn: z.string().min(1),\n input: z.record(z.string(), z.unknown()),\n sandboxId: z.string().min(1).optional(),\n image: z.string().min(1).optional(),\n snapshotId: z.string().min(1).optional(),\n metadata: metadata.optional(),\n idleTtlMs: positiveInt.optional(),\n inheritMetadata: z.boolean().optional(),\n resources: resources.optional(),\n});\nexport type TurnInput = z.input<typeof turnInput>;\n\n/** Output of one sandbox task run. `output` is the operation's own result. */\nexport const turnResult = z.looseObject({\n output: z.looseObject({}),\n sandboxId: z.string(),\n snapshotId: z.string().optional(),\n timings: z.record(z.string(), z.number()).optional(),\n});\nexport type TurnResult = z.infer<typeof turnResult>;\n\n/** `output` of a `$command` turn. */\nexport const commandOutput = z.looseObject({\n stdout: z.string(),\n stderr: z.string(),\n exitCode: z.int(),\n});\n\n/** One row of a `$list` turn's `output.sandboxes`. */\nexport const sandboxInfo = z.looseObject({\n sandboxId: z.string(),\n metadata: metadata.optional(),\n live: z.boolean(),\n latestSnapshot: z.string().optional(),\n createdAt: z.coerce.date(),\n lastUsed: z.coerce.date().optional(),\n});\n","import { HatchetClient, JsonObject } from '@hatchet-dev/typescript-sdk/v1';\nimport { z } from 'zod';\nimport { Files } from './files.js';\nimport { setupTelemetry } from './otel.js';\nimport {\n commandOutput,\n metadata,\n sandboxInfo,\n turnInput,\n turnResult,\n type TurnInput,\n type TurnResult,\n} from './wire.js';\n\nconst TASK_NAMES = ['hatchet-sandbox', 'brickie-sandbox'];\nconst taskNames = new WeakMap<HatchetClient, Promise<string>>();\n\nasync function registered(client: HatchetClient, name: string): Promise<boolean> {\n const namespace = client.config.namespace ?? '';\n const full = name.startsWith(namespace) ? name : `${namespace}${name}`;\n for (let offset = 0; ;) {\n const { rows = [] } = await client.workflows.list({ name: full, limit: 100, offset });\n if (rows.some((w) => w.name === full)) return true;\n if (rows.length === 0) return false;\n offset += rows.length;\n }\n}\n\nasync function probe(client: HatchetClient): Promise<string | undefined> {\n for (const name of TASK_NAMES) {\n if (await registered(client, name)) return name;\n }\n return undefined;\n}\n\nfunction resolveTaskName(client: HatchetClient): Promise<string> {\n let pending = taskNames.get(client);\n if (!pending) {\n pending = probe(client).then(\n (name) => {\n if (!name) taskNames.delete(client);\n return name ?? TASK_NAMES[TASK_NAMES.length - 1];\n },\n (err) => {\n taskNames.delete(client);\n throw err;\n }\n );\n taskNames.set(client, pending);\n }\n return pending;\n}\n\nconst positiveInt = z.int().positive();\nconst nonEmpty = z.string().min(1);\n\nexport interface Timings {\n /** Snapshot made after this turn. Absent for turns that do not change the workspace. */\n snapshotId?: string;\n /** Milliseconds per phase: `claim`, `restore`, `exec`, `checkpoint`. */\n timings?: Record<string, number>;\n}\n\nexport interface CommandResult extends Timings {\n stdout: string;\n stderr: string;\n /** A non-zero code is a normal result, not an error. */\n exitCode: number;\n}\n\nconst commandResult = commandOutput.extend(\n turnResult.pick({ snapshotId: true, timings: true }).shape\n);\n\nexport interface SandboxOpts {\n /** Sandbox ID to use instead of a generated one. Lowercase letters, digits, and hyphens; must be new on the provider. */\n id?: string;\n /** Container image. Defaults to the provider's image. */\n template?: string;\n /** Snapshot to start from. Two sandboxes with the same `from` are a fork. */\n from?: string;\n /** Key-value tags, used to find the sandbox again with {@link SandboxNamespace.list}. */\n metadata?: Record<string, string>;\n /** Milliseconds without a turn before the provider removes the sandbox. Capped by the provider. */\n idleTimeoutMs?: number;\n /** With `from`, start from the metadata of the sandbox that made that snapshot. Pairs given in `metadata` take precedence over inherited ones. */\n inheritParentMetadata?: boolean;\n /** Name of the sandbox provider to create on. Required when the tenant has more than one; with `from`, it must be the provider that holds the snapshot. */\n provider?: string;\n /** Machine size. Providers that cannot honour a field fail the create with their own message. Providers that do not know the option ignore it. */\n resources?: Resources;\n}\n\nexport interface Resources {\n /** Whole cores. */\n vcpu?: number;\n /** A number is MiB. A string takes a Kubernetes quantity with a unit, such as `'512Mi'`, `'4Gi'` or `'8G'`. A string without a unit is rejected. */\n memory?: number | string;\n /** Same format as `memory`. */\n disk?: number | string;\n}\n\nconst UNITS: Record<string, number> = {\n K: 1e3,\n M: 1e6,\n G: 1e9,\n T: 1e12,\n Ki: 2 ** 10,\n Mi: 2 ** 20,\n Gi: 2 ** 30,\n Ti: 2 ** 40,\n};\nconst QUANTITY = /^(\\d+(?:\\.\\d+)?)\\s*([KMGT]i?)B?$/;\n\nconst mib = z.union(\n [\n positiveInt,\n z\n .string()\n .trim()\n .regex(QUANTITY)\n .transform((s) => {\n const [, n, unit] = QUANTITY.exec(s)!;\n return Math.ceil((Number(n) * UNITS[unit]) / UNITS.Mi);\n })\n .pipe(z.int().min(1)),\n ],\n {\n error:\n \"expected a positive whole number of MiB or a quantity with a unit like '512Mi', '4Gi' or '8G'\",\n }\n);\n\nconst resources = z\n .strictObject({\n vcpu: positiveInt.optional(),\n memory: mib.optional(),\n disk: mib.optional(),\n })\n .refine(\n (r) => r.vcpu !== undefined || r.memory !== undefined || r.disk !== undefined,\n 'set at least one of vcpu, memory, disk'\n )\n .transform(({ vcpu, memory, disk }) => ({ vcpu, memoryMib: memory, diskMib: disk }));\n\nconst sandboxOpts = z\n .strictObject({\n id: z\n .string()\n .regex(/^[a-z0-9-]+$/, 'lowercase letters, digits, and hyphens only')\n .optional(),\n template: nonEmpty.optional(),\n from: nonEmpty.optional(),\n metadata: metadata.optional(),\n idleTimeoutMs: positiveInt.optional(),\n inheritParentMetadata: z.boolean().optional(),\n provider: nonEmpty.optional(),\n resources: resources.optional(),\n })\n .refine((o) => !o.inheritParentMetadata || o.from !== undefined, {\n error: 'inheritParentMetadata needs from',\n path: ['inheritParentMetadata'],\n });\n\nexport interface ExecOpts {\n /** Kill the command after this long. The result then has `exitCode` 124. */\n timeoutMs?: number;\n}\n\nconst execOpts = z.strictObject({ timeoutMs: positiveInt.optional() });\n\nexport interface ConnectOpts {\n /** Image to use if the sandbox has to be started again. Defaults to the provider's image. */\n template?: string;\n}\n\nconst connectOpts = z.strictObject({ template: nonEmpty.optional() });\n\nexport interface SandboxListOpts {\n /** Only the sandbox with this ID. */\n sandboxId?: string;\n /** Only sandboxes whose metadata contains every one of these pairs. */\n metadata?: Record<string, string>;\n}\n\nconst listOpts = z.strictObject({\n sandboxId: nonEmpty.optional(),\n metadata: metadata.optional(),\n});\n\nconst deleteOpts = listOpts.refine(\n (o) => o.sandboxId !== undefined || Object.keys(o.metadata ?? {}).length > 0,\n 'delete needs a sandboxId or a metadata filter'\n);\n\nexport interface SandboxInfo {\n sandboxId: string;\n metadata?: Record<string, string>;\n /** True while the sandbox is running. A sandbox that is not live is started again by `connect`. */\n live: boolean;\n latestSnapshot?: string;\n createdAt: Date;\n lastUsed?: Date;\n}\n\ntype RunTurn = (input: TurnInput, opts?: { fresh?: boolean }) => Promise<TurnResult>;\n\nfunction turnRunner(client: HatchetClient): RunTurn {\n const resolved = resolveTaskName(client);\n return async (raw, opts) => {\n const input = turnInput.parse(raw);\n const payload = input as JsonObject;\n const name = await resolved;\n const additionalMetadata = {\n 'hatchet.sandbox.fn': input.fn,\n ...(input.sandboxId ? { 'hatchet.sandbox.id': input.sandboxId } : {}),\n ...(input.image ? { 'hatchet.sandbox.image': input.image } : {}),\n ...(input.snapshotId ? { 'hatchet.sandbox.from': input.snapshotId } : {}),\n };\n const result = opts?.fresh\n ? await (\n await client.admin.runWorkflow<JsonObject, Record<string, JsonObject>>(name, payload, {\n additionalMetadata,\n })\n ).result()\n : await client\n .workflow<JsonObject, Record<string, JsonObject>>({ name })\n .run(payload, { additionalMetadata });\n return turnResult.parse(result[name] ?? result);\n };\n}\n\n/** One sandbox. Every method is one Hatchet task on the tenant's sandbox provider. */\nexport class Sandbox {\n /** File operations on the workspace. */\n readonly files: Files;\n\n private constructor(\n private readonly run: RunTurn,\n readonly sandboxId: string,\n private readonly template?: string\n ) {\n this.files = new Files((fn, input, fresh) => this.turn(fn, input, fresh));\n }\n\n /** Starts a new sandbox. Prefer `hatchet.sandbox.create`. */\n static async create(client: HatchetClient, opts: SandboxOpts = {}): Promise<Sandbox> {\n const o = sandboxOpts.parse(opts);\n await setupTelemetry();\n const run = turnRunner(client);\n const created = await run({\n fn: '$create',\n input: {},\n sandboxId: o.id,\n image: o.template,\n snapshotId: o.from,\n metadata: o.provider ? { ...o.metadata, provider: o.provider } : o.metadata,\n idleTtlMs: o.idleTimeoutMs,\n inheritMetadata: o.inheritParentMetadata,\n resources: o.resources,\n });\n return new Sandbox(run, created.sandboxId, o.template);\n }\n\n /** Attaches to a sandbox by ID. Prefer `hatchet.sandbox.connect`. */\n static async connect(\n client: HatchetClient,\n sandboxId: string,\n opts: ConnectOpts = {}\n ): Promise<Sandbox> {\n const id = nonEmpty.parse(sandboxId);\n const o = connectOpts.parse(opts);\n await setupTelemetry();\n const run = turnRunner(client);\n await run({ fn: '$connect', input: {}, sandboxId: id, image: o.template });\n return new Sandbox(run, id, o.template);\n }\n\n /** Lists sandboxes on the provider. Prefer `hatchet.sandbox.list`. */\n static async list(client: HatchetClient, opts: SandboxListOpts = {}): Promise<SandboxInfo[]> {\n const o = listOpts.parse(opts);\n const result = await turnRunner(client)({ fn: '$list', input: o });\n return sandboxInfo.array().parse(result.output.sandboxes ?? []);\n }\n\n /** Deletes every sandbox matching the filter, with all their snapshots and files. Prefer `hatchet.sandbox.delete`. */\n static async delete(client: HatchetClient, opts: SandboxListOpts): Promise<string[]> {\n deleteOpts.parse(opts);\n const run = turnRunner(client);\n const ids: string[] = [];\n for (const { sandboxId } of await Sandbox.list(client, opts)) {\n await run({ fn: '$delete', input: {}, sandboxId });\n ids.push(sandboxId);\n }\n return ids;\n }\n\n /** Runs a shell command with `sh -c` in the workspace and makes a snapshot. A timeout gives `exitCode` 124, not an error. */\n async exec(cmd: string, opts: ExecOpts = {}): Promise<CommandResult> {\n const input = { cmd: nonEmpty.parse(cmd), ...execOpts.parse(opts) };\n return commandResult.parse(await this.turn('$command', input));\n }\n\n /** Removes the sandbox. Its snapshots stay; `connect` can bring it back. */\n async kill(): Promise<void> {\n await this.turn('$destroy', {});\n }\n\n /** Removes the sandbox and deletes every snapshot and file the provider stored for it. `connect` fails afterwards. */\n async delete(): Promise<void> {\n await this.turn('$delete', {});\n }\n\n private async turn(fn: string, input: JsonObject, fresh = false): Promise<JsonObject> {\n const result = await this.run(\n { sandboxId: this.sandboxId, image: this.template, fn, input },\n { fresh }\n );\n return {\n ...result.output,\n snapshotId: result.snapshotId,\n timings: result.timings,\n } as JsonObject;\n }\n}\n\n/** `hatchet.sandbox`, added to `HatchetClient` by importing `@hatchet-dev/sandbox`. */\nexport interface SandboxNamespace {\n /** Starts a new sandbox. Inside a durable task this is a durable step. */\n create(opts?: SandboxOpts): Promise<Sandbox>;\n /** Attaches to a sandbox by ID. If it is not running, the provider starts it from its latest snapshot. */\n connect(sandboxId: string, opts?: ConnectOpts): Promise<Sandbox>;\n /** Lists sandboxes the provider knows, filtered by ID or metadata. */\n list(opts?: SandboxListOpts): Promise<SandboxInfo[]>;\n /** Deletes the sandboxes matching the filter, with every snapshot and file stored for them. Returns their IDs. */\n delete(opts: SandboxListOpts): Promise<string[]>;\n}\n\ndeclare module '@hatchet-dev/typescript-sdk/v1' {\n interface HatchetClient {\n readonly sandbox: SandboxNamespace;\n }\n}\n\nObject.defineProperty(HatchetClient.prototype, 'sandbox', {\n configurable: true,\n get(this: HatchetClient): SandboxNamespace {\n return {\n create: (opts) => Sandbox.create(this, opts),\n connect: (sandboxId, opts) => Sandbox.connect(this, sandboxId, opts),\n list: (opts) => Sandbox.list(this, opts),\n delete: (opts) => Sandbox.delete(this, opts),\n };\n },\n});\n"]}