@hatchet-dev/sandbox 0.1.2 → 0.1.4
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/CHANGELOG.md +12 -0
- package/README.md +10 -9
- package/dist/index.cjs +41 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +41 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,18 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Eac
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.4] - 2026-11-09
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `resources.memory` and `resources.disk` strings without a unit were read as MiB, so a byte count such as `'1073741824'` asked for a billion MiB. A string now has to carry a unit (`Ki`, `Mi`, `Gi`, `Ti`, `K`, `M`, `G`, `T`) and is rejected otherwise. Pass a number for MiB.
|
|
14
|
+
|
|
15
|
+
## [0.1.3] - 2026-11-09
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `create({ resources })` asks the provider for a machine size, `{ vcpu, memory, disk }`. `memory` and `disk` take a number of MiB or a Kubernetes quantity such as `'512Mi'`, `'4Gi'` or `'8G'`, and travel as `memoryMib` and `diskMib` on the wire. A provider that cannot honour a field fails the create with its own message, so plan limits show up as the task error. A provider that does not know the option ignores it. On Hatchet Cloud, Archil sizes the sandbox on create and forks keep the source's size, so `resources` with `from` is rejected there. Daytona and Freestyle resize after create, which on Daytona needs resizing enabled for the organization and on Freestyle can only grow. E2B sizes on the template and rejects the option.
|
|
20
|
+
|
|
9
21
|
## [0.1.2] - 2026-11-03
|
|
10
22
|
|
|
11
23
|
### Added
|
package/README.md
CHANGED
|
@@ -86,15 +86,16 @@ const sandbox = await hatchet.sandbox.create({ provider: 'e2b' });
|
|
|
86
86
|
|
|
87
87
|
Options for `create`:
|
|
88
88
|
|
|
89
|
-
| Option | What it does
|
|
90
|
-
| ----------------------- |
|
|
91
|
-
| `provider` | Which sandbox provider to create on, by its name. Needed when the tenant has several; a fork always uses its snapshot's.
|
|
92
|
-
| `id` | Pick your own sandbox ID. Lowercase letters, digits, and hyphens. It must not exist yet.
|
|
93
|
-
| `template` | The image or template, in the provider's own terms. Defaults to the provider's default.
|
|
94
|
-
| `from` | Start from this snapshot. Create two sandboxes from the same snapshot and you have a fork.
|
|
95
|
-
| `metadata` | Tags you can search for with `list`.
|
|
96
|
-
| `inheritParentMetadata` | With `from`, copy the tags of the sandbox that made the snapshot onto the new one. Tags given in `metadata` take precedence.
|
|
97
|
-
| `idleTimeoutMs` | Stop the sandbox after this long with no calls. The provider sets the maximum.
|
|
89
|
+
| Option | What it does |
|
|
90
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
91
|
+
| `provider` | Which sandbox provider to create on, by its name. Needed when the tenant has several; a fork always uses its snapshot's. |
|
|
92
|
+
| `id` | Pick your own sandbox ID. Lowercase letters, digits, and hyphens. It must not exist yet. |
|
|
93
|
+
| `template` | The image or template, in the provider's own terms. Defaults to the provider's default. |
|
|
94
|
+
| `from` | Start from this snapshot. Create two sandboxes from the same snapshot and you have a fork. |
|
|
95
|
+
| `metadata` | Tags you can search for with `list`. |
|
|
96
|
+
| `inheritParentMetadata` | With `from`, copy the tags of the sandbox that made the snapshot onto the new one. Tags given in `metadata` take precedence. |
|
|
97
|
+
| `idleTimeoutMs` | Stop the sandbox after this long with no calls. The provider sets the maximum. |
|
|
98
|
+
| `resources` | Machine size as `{ vcpu, memory, disk }`. `memory` and `disk` take a number of MiB or a quantity with a unit like `'4Gi'`. Providers that cannot honour a field fail the create with their own message. |
|
|
98
99
|
|
|
99
100
|
### `Sandbox`
|
|
100
101
|
|
package/dist/index.cjs
CHANGED
|
@@ -229,6 +229,45 @@ function resolveTaskName(client) {
|
|
|
229
229
|
}
|
|
230
230
|
return pending;
|
|
231
231
|
}
|
|
232
|
+
var UNITS = {
|
|
233
|
+
K: 1e3,
|
|
234
|
+
M: 1e6,
|
|
235
|
+
G: 1e9,
|
|
236
|
+
T: 1e12,
|
|
237
|
+
Ki: 2 ** 10,
|
|
238
|
+
Mi: 2 ** 20,
|
|
239
|
+
Gi: 2 ** 30,
|
|
240
|
+
Ti: 2 ** 40
|
|
241
|
+
};
|
|
242
|
+
function toMib(value, field) {
|
|
243
|
+
if (typeof value === "number") {
|
|
244
|
+
if (!Number.isInteger(value) || value <= 0)
|
|
245
|
+
throw new Error(`resources.${field}: expected a positive whole number of MiB`);
|
|
246
|
+
return value;
|
|
247
|
+
}
|
|
248
|
+
const m = /^(\d+(?:\.\d+)?)\s*([KMGT]i?)B?$/.exec(value.trim());
|
|
249
|
+
if (!m)
|
|
250
|
+
throw new Error(
|
|
251
|
+
`resources.${field}: expected a quantity with a unit like '512Mi', '4Gi' or '8G', or a number of MiB, got ${JSON.stringify(value)}`
|
|
252
|
+
);
|
|
253
|
+
const bytes = Number(m[1]) * UNITS[m[2]];
|
|
254
|
+
const mib = Math.ceil(bytes / UNITS.Mi);
|
|
255
|
+
if (mib <= 0) throw new Error(`resources.${field}: must be at least 1Mi`);
|
|
256
|
+
return mib;
|
|
257
|
+
}
|
|
258
|
+
function wireResources(r) {
|
|
259
|
+
const out = {};
|
|
260
|
+
if (r.vcpu !== void 0) {
|
|
261
|
+
if (!Number.isInteger(r.vcpu) || r.vcpu <= 0)
|
|
262
|
+
throw new Error("resources.vcpu: expected a positive whole number of cores");
|
|
263
|
+
out.vcpu = r.vcpu;
|
|
264
|
+
}
|
|
265
|
+
if (r.memory !== void 0) out.memoryMib = toMib(r.memory, "memory");
|
|
266
|
+
if (r.disk !== void 0) out.diskMib = toMib(r.disk, "disk");
|
|
267
|
+
if (Object.keys(out).length === 0)
|
|
268
|
+
throw new Error("resources: set at least one of vcpu, memory, disk");
|
|
269
|
+
return out;
|
|
270
|
+
}
|
|
232
271
|
function turnRunner(client) {
|
|
233
272
|
const resolved = resolveTaskName(client);
|
|
234
273
|
return async (input, opts) => {
|
|
@@ -270,7 +309,8 @@ var Sandbox = class _Sandbox {
|
|
|
270
309
|
...opts.from ? { snapshotId: opts.from } : {},
|
|
271
310
|
...metadata ? { metadata } : {},
|
|
272
311
|
...opts.idleTimeoutMs ? { idleTtlMs: opts.idleTimeoutMs } : {},
|
|
273
|
-
...opts.inheritParentMetadata ? { inheritMetadata: true } : {}
|
|
312
|
+
...opts.inheritParentMetadata ? { inheritMetadata: true } : {},
|
|
313
|
+
...opts.resources ? { resources: wireResources(opts.resources) } : {}
|
|
274
314
|
});
|
|
275
315
|
return new _Sandbox(run, created.sandboxId, opts.template);
|
|
276
316
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/files.ts","../src/otel.ts","../src/sandbox.ts"],"names":["fs","HatchetClient"],"mappings":"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","file":"index.cjs","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}\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 });\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/sandbox.ts"],"names":["fs","HatchetClient"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgDO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EACzC,WAAA,CACW,MACT,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHJ,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAIT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AAAA,EALW,IAAA;AAMb;AAmBA,IAAM,OAAA,GAAU,CAAC,CAAA,MAA4B;AAAA,EAC3C,GAAG,CAAA;AAAA,EACH,cAAc,CAAA,CAAE,YAAA,GAAe,IAAI,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,GAAI;AAC5D,CAAA,CAAA;AAEA,IAAM,mBAAmB,CAAA,IAAK,EAAA;AAE9B,eAAe,QAAQ,IAAA,EAAiC;AACtD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,SAAiB,MAAA,CAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAC7D,EAAA,IAAI,IAAA,YAAgB,MAAM,OAAO,MAAA,CAAO,KAAK,MAAM,IAAA,CAAK,aAAa,CAAA;AACrE,EAAA,IAAI,IAAA,YAAgB,UAAA,EAAY,OAAO,MAAA,CAAO,IAAA,CAAK,KAAK,MAAA,EAAQ,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,UAAU,CAAA;AAChG,EAAA,OAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACzB;AAEA,eAAe,SAAA,CAAU,KAAa,KAAA,EAA8B;AAClE,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC7B,IAAA,MAASA,aAAA,CAAA,SAAA,CAAU,mBAAmB,GAAA,CAAI,KAAA,CAAM,UAAU,MAAM,CAAC,GAAG,KAAK,CAAA;AACzE,IAAA;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAC3B,MAAA,EAAQ,KAAA;AAAA,IACR,IAAA,EAAM,IAAI,UAAA,CAAW,KAAK,CAAA;AAAA,IAC1B,OAAA,EAAS,EAAE,cAAA,EAAgB,0BAAA;AAA2B,GACvD,CAAA;AACD,EAAA,IAAI,CAAC,GAAA,CAAI,EAAA;AACP,IAAA,MAAM,IAAI,eAAA,CAAgB,gBAAA,EAAkB,CAAA,0BAAA,EAA6B,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACzF;AAEA,eAAe,UAAU,GAAA,EAA8B;AACrD,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAUA,uBAAS,kBAAA,CAAmB,GAAA,CAAI,MAAM,SAAA,CAAU,MAAM,CAAC,CAAC,CAAA;AAAA,EACpE;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,IAAI,CAAC,GAAA,CAAI,EAAA;AACP,IAAA,MAAM,IAAI,eAAA,CAAgB,gBAAA,EAAkB,CAAA,4BAAA,EAA+B,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACzF,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,GAAA,CAAI,aAAa,CAAA;AAC5C;AAEO,IAAM,QAAN,MAAY;AAAA;AAAA,EAEjB,YAA6B,IAAA,EAAc;AAAd,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAe;AAAA,EAAf,IAAA;AAAA,EAE7B,MAAc,IAAA,CAAK,EAAA,EAAY,KAAA,EAAmB,QAAQ,KAAA,EAA0B;AAClF,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,IAAA,CAAK,OAAO,EAAE,CAAA,CAAA,EAAI,OAAO,KAAK,CAAA;AACrD,IAAA,IAAI,GAAA,CAAI,KAAA,EAAO,MAAM,IAAI,eAAA,CAAgB,IAAI,KAAA,CAAM,IAAA,EAAM,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AAC1E,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAMA,MAAM,IAAA,CAAK,IAAA,EAAc,IAAA,GAAiB,EAAC,EAAwC;AACjF,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,KAAK,MAAA,EAAQ,EAAE,MAAM,CAAA;AAC5C,IAAA,MAAM,QAAQ,GAAA,CAAI,GAAA,GACd,MAAM,IAAA,CAAK,WAAW,GAAA,CAAI,GAAA,EAAK,GAAA,CAAI,SAAU,IAC7C,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,OAAA,IAAW,IAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,KAAK,MAAA,KAAW,OAAA,EAAS,OAAO,IAAI,WAAW,KAAK,CAAA;AACxD,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAQ,OAAO,IAAI,IAAA,CAAK,CAAC,IAAI,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AACnE,IAAA,OAAO,KAAA,CAAM,SAAS,MAAM,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAc,UAAA,CAAW,GAAA,EAAa,SAAA,EAAoC;AACxE,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,UAAU,GAAG,CAAA;AAAA,IAC5B,SAAS,CAAA,EAAG;AACV,MAAA,IAAI,IAAI,UAAA,CAAW,SAAS,KAAK,EAAE,CAAA,YAAa,kBAAkB,MAAM,CAAA;AACxE,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,KAAK,SAAA,EAAW,EAAE,SAAA,EAAU,EAAG,IAAI,CAAA;AACjE,MAAA,OAAO,UAAU,MAAO,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAKA,MAAM,KAAA,CACJ,WAAA,EACA,IAAA,EACkC;AAClC,IAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,EAAU,OAAO,IAAA,CAAK,WAAW,WAAW,CAAA;AACvE,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,KAAK,UAAA,CAAW,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,IAAA,IAAQ,EAAA,EAAI,CAAC,CAAA;AAC/E,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,WAAW,KAAA,EAA2C;AAC1D,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AACjE,IAAA,MAAM,UAAyE,EAAC;AAChF,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,KAAA,CAAM,SAAQ,EAAG;AACpC,MAAA,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AACjB,MAAA,IAAI,CAAA,CAAE,UAAU,gBAAA,EAAkB;AAChC,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,SAAS,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA,EAAG,CAAA;AAC5D,QAAA;AAAA,MACF;AACA,MAAA,MAAM,EAAE,WAAW,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,CAAA;AAC3D,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,CAAU,QAAS,CAAC,CAAA;AAC1B,QAAA,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,WAAuB,CAAA;AAAA,MACtD,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,KAAK,SAAA,EAAW,IAAI,IAAI,CAAA;AACjD,QAAA,MAAM,SAAA,CAAU,KAAA,CAAM,MAAA,EAAS,CAAC,CAAA;AAChC,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,SAAA,EAAW,KAAA,CAAM,WAAY,CAAA;AAAA,MAC5D;AAAA,IACF;AACA,IAAA,MAAM,EAAE,OAAA,GAAU,EAAC,EAAE,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA;AACpE,IAAA,OAAO,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,IAAA,GAAO,GAAA,EAAK,IAAA,GAAiB,EAAC,EAAyB;AAChE,IAAA,MAAM,EAAE,OAAA,GAAU,EAAC,KAAM,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,GAAG,CAAA;AACjF,IAAA,OAAO,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,OAAO,IAAA,EAAgC;AAC3C,IAAA,MAAM,EAAE,OAAM,GAAI,MAAM,KAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,CAAA;AAClD,IAAA,OAAO,KAAA,IAAS,IAAA;AAAA,EAClB;AAAA;AAAA,EAGA,MAAM,QAAQ,IAAA,EAAkC;AAC9C,IAAA,MAAM,EAAE,OAAM,GAAI,MAAM,KAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,CAAA;AAClD,IAAA,IAAI,CAAC,OAAO,MAAM,IAAI,gBAAgB,WAAA,EAAa,CAAA,EAAG,IAAI,CAAA,eAAA,CAAiB,CAAA;AAC3E,IAAA,OAAO,QAAQ,KAAK,CAAA;AAAA,EACtB;AAAA;AAAA,EAGA,MAAM,QAAQ,IAAA,EAAgC;AAC5C,IAAA,MAAM,EAAE,SAAQ,GAAI,MAAM,KAAK,IAAA,CAAK,OAAA,EAAS,EAAE,IAAA,EAAM,CAAA;AACrD,IAAA,OAAO,OAAA,KAAY,IAAA;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,MAAA,CAAO,OAAA,EAAiB,OAAA,EAAqC;AACjE,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,CAAA;AACtE,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,OAAA,EAAiB,OAAA,EAAqC;AAC/D,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,CAAA;AAC7E,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,OAAO,IAAA,EAA6B;AACxC,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,EAAE,MAAM,CAAA;AAAA,EACpC;AAAA;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,IAAA,EAAc,IAAA,GAAqB,EAAC,EAAuB;AACrF,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,KAAK,UAAA,EAAY;AAAA,MAC5C,GAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AACD,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAEA,MAAM,MAAA,CAAO,IAAA,EAAc,GAAA,EAAa,IAAA,GAAqB,EAAC,EAAkB;AAC9E,IAAA,MAAM,IAAA,CAAK,KAAK,QAAA,EAAU;AAAA,MACxB,IAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AAAA,EACH;AACF;;;AClPA,IAAI,gBAAA,GAAmB,KAAA;AAEvB,eAAsB,cAAA,GAAgC;AACpD,EAAA,IACE,gBAAA,IACA,QAAQ,GAAA,CAAI,oBAAA,KAAyB,WACrC,OAAA,CAAQ,GAAA,CAAI,iBAAiB,OAAA,EAC7B;AACA,IAAA;AAAA,EACF;AACA,EAAA,gBAAA,GAAmB,IAAA;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,CAAC,EAAE,wBAAA,EAAyB,EAAG,EAAE,qBAAqB,CAAA,GAAI,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,MAChF,OAAO,gCAAgC,CAAA;AAAA,MACvC,OAAO,oDAAoD;AAAA,KAC5D,CAAA;AACD,IAAA,wBAAA,CAAyB,EAAE,gBAAA,EAAkB,CAAC,IAAI,mBAAA,EAAqB,GAAG,CAAA;AAAA,EAC5E,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iCAAA,EAAqC,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,EAC5E;AACF;;;AChBA,IAAM,UAAA,GAAa,CAAC,iBAAA,EAAmB,iBAAiB,CAAA;AACxD,IAAM,SAAA,uBAAgB,OAAA,EAAwC;AAE9D,eAAe,UAAA,CAAW,QAAuB,IAAA,EAAgC;AAC/E,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAA;AAC7C,EAAA,MAAM,IAAA,GAAO,KAAK,UAAA,CAAW,SAAS,IAAI,IAAA,GAAO,CAAA,EAAG,SAAS,CAAA,EAAG,IAAI,CAAA,CAAA;AACpE,EAAA,KAAA,IAAS,SAAS,CAAA,MAAM;AACtB,IAAA,MAAM,EAAE,IAAA,GAAO,EAAC,KAAM,MAAM,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,QAAQ,CAAA;AACpF,IAAA,IAAI,IAAA,CAAK,KAAK,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,IAAI,GAAG,OAAO,IAAA;AAC9C,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAC9B,IAAA,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,EACjB;AACF;AAEA,eAAe,MAAM,MAAA,EAAoD;AACvE,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,IAAI,MAAM,UAAA,CAAW,MAAA,EAAQ,IAAI,GAAG,OAAO,IAAA;AAAA,EAC7C;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,gBAAgB,MAAA,EAAwC;AAC/D,EAAA,IAAI,OAAA,GAAU,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA;AAClC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,KAAA,CAAM,MAAM,CAAA,CAAE,IAAA;AAAA,MACtB,CAAC,IAAA,KAAS;AACR,QAAA,IAAI,CAAC,IAAA,EAAM,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAClC,QAAA,OAAO,IAAA,IAAQ,UAAA,CAAW,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA;AAAA,MACjD,CAAA;AAAA,MACA,CAAC,GAAA,KAAQ;AACP,QAAA,SAAA,CAAU,OAAO,MAAM,CAAA;AACvB,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,KACF;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,OAAA;AACT;AA8DA,IAAM,KAAA,GAAgC;AAAA,EACpC,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,IAAA;AAAA,EACH,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK;AACX,CAAA;AAEA,SAAS,KAAA,CAAM,OAAwB,KAAA,EAAuB;AAC5D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,KAAK,KAAA,IAAS,CAAA;AACvC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,UAAA,EAAa,KAAK,CAAA,yCAAA,CAA2C,CAAA;AAC/E,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,CAAA,GAAI,kCAAA,CAAmC,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC9D,EAAA,IAAI,CAAC,CAAA;AACH,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,aAAa,KAAK,CAAA,uFAAA,EAA0F,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,KACnI;AACF,EAAA,MAAM,KAAA,GAAQ,OAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,KAAA,CAAM,CAAA,CAAE,CAAC,CAAC,CAAA;AACvC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,KAAA,GAAQ,MAAM,EAAE,CAAA;AACtC,EAAA,IAAI,OAAO,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,UAAA,EAAa,KAAK,CAAA,sBAAA,CAAwB,CAAA;AACxE,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,cAAc,CAAA,EAA0B;AAC/C,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,IAAI,CAAA,CAAE,SAAS,MAAA,EAAW;AACxB,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,EAAE,IAAI,CAAA,IAAK,EAAE,IAAA,IAAQ,CAAA;AACzC,MAAA,MAAM,IAAI,MAAM,2DAA2D,CAAA;AAC7E,IAAA,GAAA,CAAI,OAAO,CAAA,CAAE,IAAA;AAAA,EACf;AACA,EAAA,IAAI,CAAA,CAAE,WAAW,MAAA,EAAW,GAAA,CAAI,YAAY,KAAA,CAAM,CAAA,CAAE,QAAQ,QAAQ,CAAA;AACpE,EAAA,IAAI,CAAA,CAAE,SAAS,MAAA,EAAW,GAAA,CAAI,UAAU,KAAA,CAAM,CAAA,CAAE,MAAM,MAAM,CAAA;AAC5D,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,KAAW,CAAA;AAC9B,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AACrE,EAAA,OAAO,GAAA;AACT;AA+BA,SAAS,WAAW,MAAA,EAAgC;AAClD,EAAA,MAAM,QAAA,GAAW,gBAAgB,MAAM,CAAA;AACvC,EAAA,OAAO,OAAO,OAAO,IAAA,KAAS;AAC5B,IAAA,MAAM,OAAO,MAAM,QAAA;AACnB,IAAA,MAAM,kBAAA,GAAqB;AAAA,MACzB,sBAAsB,KAAA,CAAM,EAAA;AAAA,MAC5B,GAAI,MAAM,SAAA,GAAY,EAAE,sBAAsB,KAAA,CAAM,SAAA,KAAc,EAAC;AAAA,MACnE,GAAI,MAAM,KAAA,GAAQ,EAAE,yBAAyB,KAAA,CAAM,KAAA,KAAU,EAAC;AAAA,MAC9D,GAAI,MAAM,UAAA,GAAa,EAAE,wBAAwB,KAAA,CAAM,UAAA,KAAe;AAAC,KACzE;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,GACjB,MAAA,CACE,MAAM,MAAA,CAAO,KAAA,CAAM,WAAA,CAAmD,IAAA,EAAM,KAAA,EAAO;AAAA,MACjF;AAAA,KACD,CAAA,EACD,MAAA,EAAO,GACT,MAAM,MAAA,CACH,QAAA,CAAgD,EAAE,IAAA,EAAM,CAAA,CACxD,GAAA,CAAI,KAAA,EAAO,EAAE,oBAAoB,CAAA;AACxC,IAAA,OAAO,MAAA,CAAO,IAAI,CAAA,IAAM,MAAA;AAAA,EAC1B,CAAA;AACF;AAGO,IAAM,OAAA,GAAN,MAAM,QAAA,CAAQ;AAAA,EAIX,WAAA,CACW,GAAA,EACR,SAAA,EACQ,QAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AACR,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACQ,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAEjB,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAA,CAAM,CAAC,EAAA,EAAI,KAAA,EAAO,KAAA,KAAU,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EAC1E;AAAA,EALmB,GAAA;AAAA,EACR,SAAA;AAAA,EACQ,QAAA;AAAA;AAAA,EALV,KAAA;AAAA;AAAA,EAWT,aAAa,MAAA,CAAO,MAAA,EAAuB,IAAA,GAAoB,EAAC,EAAqB;AACnF,IAAA,MAAM,cAAA,EAAe;AACrB,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,GAAW,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,QAAA,EAAU,IAAA,CAAK,QAAA,EAAS,GAAI,IAAA,CAAK,QAAA;AACtF,IAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI;AAAA,MACxB,EAAA,EAAI,SAAA;AAAA,MACJ,OAAO,EAAC;AAAA,MACR,GAAI,KAAK,EAAA,GAAK,EAAE,WAAW,IAAA,CAAK,EAAA,KAAO,EAAC;AAAA,MACxC,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,MAChD,GAAI,KAAK,IAAA,GAAO,EAAE,YAAY,IAAA,CAAK,IAAA,KAAS,EAAC;AAAA,MAC7C,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,MAC/B,GAAI,KAAK,aAAA,GAAgB,EAAE,WAAW,IAAA,CAAK,aAAA,KAAkB,EAAC;AAAA,MAC9D,GAAI,IAAA,CAAK,qBAAA,GAAwB,EAAE,eAAA,EAAiB,IAAA,KAAS,EAAC;AAAA,MAC9D,GAAI,IAAA,CAAK,SAAA,GAAY,EAAE,SAAA,EAAW,cAAc,IAAA,CAAK,SAAS,CAAA,EAAE,GAAI;AAAC,KACtE,CAAA;AACD,IAAA,OAAO,IAAI,QAAA,CAAQ,GAAA,EAAK,OAAA,CAAQ,SAAA,EAAW,KAAK,QAAQ,CAAA;AAAA,EAC1D;AAAA;AAAA,EAGA,aAAa,OAAA,CACX,MAAA,EACA,SAAA,EACA,IAAA,GAAoB,EAAC,EACH;AAClB,IAAA,MAAM,cAAA,EAAe;AACrB,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,GAAA,CAAI;AAAA,MACR,EAAA,EAAI,UAAA;AAAA,MACJ,OAAO,EAAC;AAAA,MACR,SAAA;AAAA,MACA,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa;AAAC,KACjD,CAAA;AACD,IAAA,OAAO,IAAI,QAAA,CAAQ,GAAA,EAAK,SAAA,EAAW,KAAK,QAAQ,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,aAAa,IAAA,CAAK,MAAA,EAAuB,IAAA,GAAwB,EAAC,EAA2B;AAC3F,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAM,CAAA,CAAE;AAAA,MACtC,EAAA,EAAI,OAAA;AAAA,MACJ,KAAA,EAAO;AAAA,QACL,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc,EAAC;AAAA,QACtD,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa;AAAC;AACrD,KACD,CAAA;AACD,IAAA,MAAM,GAAA,GAAO,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAC;AAGzC,IAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACrB,GAAG,CAAA;AAAA,MACH,SAAA,EAAW,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAAA,MAC/B,UAAU,CAAA,CAAE,QAAA,GAAW,IAAI,IAAA,CAAK,CAAA,CAAE,QAAQ,CAAA,GAAI;AAAA,KAChD,CAAE,CAAA;AAAA,EACJ;AAAA;AAAA,EAGA,aAAa,MAAA,CAAO,MAAA,EAAuB,IAAA,EAA0C;AACnF,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,KAAK,QAAA,IAAY,EAAE,CAAA,CAAE,MAAA,KAAW,CAAA;AACjE,MAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AACjE,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,MAAgB,EAAC;AACvB,IAAA,KAAA,MAAW,EAAE,WAAU,IAAK,MAAM,SAAQ,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA,EAAG;AAC5D,MAAA,MAAM,GAAA,CAAI,EAAE,EAAA,EAAI,SAAA,EAAW,OAAO,EAAC,EAAG,WAAW,CAAA;AACjD,MAAA,GAAA,CAAI,KAAK,SAAS,CAAA;AAAA,IACpB;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,GAAA,EAAa,IAAA,GAAiB,EAAC,EAA2B;AACnE,IAAA,OAAO,IAAA,CAAK,KAAoB,UAAA,EAAY;AAAA,MAC1C,GAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,EAAE,CAAA;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,MAAA,GAAwB;AAC5B,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAc,IAAA,CAAqB,EAAA,EAAY,KAAA,EAAmB,QAAQ,KAAA,EAAmB;AAC3F,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA;AAAA,MACxB;AAAA,QACE,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,QAChD,EAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,EAAE,KAAA;AAAM,KACV;AACA,IAAA,OAAO;AAAA,MACL,GAAG,MAAA,CAAO,MAAA;AAAA,MACV,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,SAAS,MAAA,CAAO;AAAA,KAClB;AAAA,EACF;AACF;AAoBA,MAAA,CAAO,cAAA,CAAeC,gBAAA,CAAc,SAAA,EAAW,SAAA,EAAW;AAAA,EACxD,YAAA,EAAc,IAAA;AAAA,EACd,GAAA,GAA2C;AACzC,IAAA,OAAO;AAAA,MACL,QAAQ,CAAC,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,MAC3C,OAAA,EAAS,CAAC,SAAA,EAAW,IAAA,KAAS,QAAQ,OAAA,CAAQ,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,MACnE,MAAM,CAAC,IAAA,KAAS,OAAA,CAAQ,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,MACvC,QAAQ,CAAC,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAM,IAAI;AAAA,KAC7C;AAAA,EACF;AACF,CAAC,CAAA","file":"index.cjs","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 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};\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 with a unit like '512Mi', '4Gi' or '8G', or a number of MiB, got ${JSON.stringify(value)}`\n );\n const bytes = Number(m[1]) * UNITS[m[2]];\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -120,6 +120,16 @@ interface SandboxOpts {
|
|
|
120
120
|
inheritParentMetadata?: boolean;
|
|
121
121
|
/** 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. */
|
|
122
122
|
provider?: string;
|
|
123
|
+
/** Machine size. Providers that cannot honour a field fail the create with their own message. Providers that do not know the option ignore it. */
|
|
124
|
+
resources?: Resources;
|
|
125
|
+
}
|
|
126
|
+
interface Resources {
|
|
127
|
+
/** Whole cores. */
|
|
128
|
+
vcpu?: number;
|
|
129
|
+
/** 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. */
|
|
130
|
+
memory?: number | string;
|
|
131
|
+
/** Same format as `memory`. */
|
|
132
|
+
disk?: number | string;
|
|
123
133
|
}
|
|
124
134
|
interface ExecOpts {
|
|
125
135
|
/** Kill the command after this long. The result then has `exitCode` 124. */
|
|
@@ -185,4 +195,4 @@ declare module '@hatchet-dev/typescript-sdk/v1' {
|
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
export { type CommandResult, type ConnectOpts, type EntryInfo, type ExecOpts, type FileData, type FileType, Files, FilesystemError, type FilesystemErrorCode, type ListOpts, type ReadOpts, Sandbox, type SandboxInfo, type SandboxListOpts, type SandboxNamespace, type SandboxOpts, type Timings, type TransferOpts, type WriteEntry };
|
|
198
|
+
export { type CommandResult, type ConnectOpts, type EntryInfo, type ExecOpts, type FileData, type FileType, Files, FilesystemError, type FilesystemErrorCode, type ListOpts, type ReadOpts, type Resources, Sandbox, type SandboxInfo, type SandboxListOpts, type SandboxNamespace, type SandboxOpts, type Timings, type TransferOpts, type WriteEntry };
|
package/dist/index.d.ts
CHANGED
|
@@ -120,6 +120,16 @@ interface SandboxOpts {
|
|
|
120
120
|
inheritParentMetadata?: boolean;
|
|
121
121
|
/** 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. */
|
|
122
122
|
provider?: string;
|
|
123
|
+
/** Machine size. Providers that cannot honour a field fail the create with their own message. Providers that do not know the option ignore it. */
|
|
124
|
+
resources?: Resources;
|
|
125
|
+
}
|
|
126
|
+
interface Resources {
|
|
127
|
+
/** Whole cores. */
|
|
128
|
+
vcpu?: number;
|
|
129
|
+
/** 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. */
|
|
130
|
+
memory?: number | string;
|
|
131
|
+
/** Same format as `memory`. */
|
|
132
|
+
disk?: number | string;
|
|
123
133
|
}
|
|
124
134
|
interface ExecOpts {
|
|
125
135
|
/** Kill the command after this long. The result then has `exitCode` 124. */
|
|
@@ -185,4 +195,4 @@ declare module '@hatchet-dev/typescript-sdk/v1' {
|
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
export { type CommandResult, type ConnectOpts, type EntryInfo, type ExecOpts, type FileData, type FileType, Files, FilesystemError, type FilesystemErrorCode, type ListOpts, type ReadOpts, Sandbox, type SandboxInfo, type SandboxListOpts, type SandboxNamespace, type SandboxOpts, type Timings, type TransferOpts, type WriteEntry };
|
|
198
|
+
export { type CommandResult, type ConnectOpts, type EntryInfo, type ExecOpts, type FileData, type FileType, Files, FilesystemError, type FilesystemErrorCode, type ListOpts, type ReadOpts, type Resources, Sandbox, type SandboxInfo, type SandboxListOpts, type SandboxNamespace, type SandboxOpts, type Timings, type TransferOpts, type WriteEntry };
|
package/dist/index.js
CHANGED
|
@@ -207,6 +207,45 @@ function resolveTaskName(client) {
|
|
|
207
207
|
}
|
|
208
208
|
return pending;
|
|
209
209
|
}
|
|
210
|
+
var UNITS = {
|
|
211
|
+
K: 1e3,
|
|
212
|
+
M: 1e6,
|
|
213
|
+
G: 1e9,
|
|
214
|
+
T: 1e12,
|
|
215
|
+
Ki: 2 ** 10,
|
|
216
|
+
Mi: 2 ** 20,
|
|
217
|
+
Gi: 2 ** 30,
|
|
218
|
+
Ti: 2 ** 40
|
|
219
|
+
};
|
|
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 with a unit like '512Mi', '4Gi' or '8G', or a number of MiB, got ${JSON.stringify(value)}`
|
|
230
|
+
);
|
|
231
|
+
const bytes = Number(m[1]) * UNITS[m[2]];
|
|
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
|
+
}
|
|
210
249
|
function turnRunner(client) {
|
|
211
250
|
const resolved = resolveTaskName(client);
|
|
212
251
|
return async (input, opts) => {
|
|
@@ -248,7 +287,8 @@ var Sandbox = class _Sandbox {
|
|
|
248
287
|
...opts.from ? { snapshotId: opts.from } : {},
|
|
249
288
|
...metadata ? { metadata } : {},
|
|
250
289
|
...opts.idleTimeoutMs ? { idleTtlMs: opts.idleTimeoutMs } : {},
|
|
251
|
-
...opts.inheritParentMetadata ? { inheritMetadata: true } : {}
|
|
290
|
+
...opts.inheritParentMetadata ? { inheritMetadata: true } : {},
|
|
291
|
+
...opts.resources ? { resources: wireResources(opts.resources) } : {}
|
|
252
292
|
});
|
|
253
293
|
return new _Sandbox(run, created.sandboxId, opts.template);
|
|
254
294
|
}
|
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}\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 });\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/sandbox.ts"],"names":[],"mappings":";;;;AAgDO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EACzC,WAAA,CACW,MACT,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHJ,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAIT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AAAA,EALW,IAAA;AAMb;AAmBA,IAAM,OAAA,GAAU,CAAC,CAAA,MAA4B;AAAA,EAC3C,GAAG,CAAA;AAAA,EACH,cAAc,CAAA,CAAE,YAAA,GAAe,IAAI,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,GAAI;AAC5D,CAAA,CAAA;AAEA,IAAM,mBAAmB,CAAA,IAAK,EAAA;AAE9B,eAAe,QAAQ,IAAA,EAAiC;AACtD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,SAAiB,MAAA,CAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAC7D,EAAA,IAAI,IAAA,YAAgB,MAAM,OAAO,MAAA,CAAO,KAAK,MAAM,IAAA,CAAK,aAAa,CAAA;AACrE,EAAA,IAAI,IAAA,YAAgB,UAAA,EAAY,OAAO,MAAA,CAAO,IAAA,CAAK,KAAK,MAAA,EAAQ,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,UAAU,CAAA;AAChG,EAAA,OAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACzB;AAEA,eAAe,SAAA,CAAU,KAAa,KAAA,EAA8B;AAClE,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC7B,IAAA,MAAS,EAAA,CAAA,SAAA,CAAU,mBAAmB,GAAA,CAAI,KAAA,CAAM,UAAU,MAAM,CAAC,GAAG,KAAK,CAAA;AACzE,IAAA;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAC3B,MAAA,EAAQ,KAAA;AAAA,IACR,IAAA,EAAM,IAAI,UAAA,CAAW,KAAK,CAAA;AAAA,IAC1B,OAAA,EAAS,EAAE,cAAA,EAAgB,0BAAA;AAA2B,GACvD,CAAA;AACD,EAAA,IAAI,CAAC,GAAA,CAAI,EAAA;AACP,IAAA,MAAM,IAAI,eAAA,CAAgB,gBAAA,EAAkB,CAAA,0BAAA,EAA6B,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACzF;AAEA,eAAe,UAAU,GAAA,EAA8B;AACrD,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAU,YAAS,kBAAA,CAAmB,GAAA,CAAI,MAAM,SAAA,CAAU,MAAM,CAAC,CAAC,CAAA;AAAA,EACpE;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,IAAI,CAAC,GAAA,CAAI,EAAA;AACP,IAAA,MAAM,IAAI,eAAA,CAAgB,gBAAA,EAAkB,CAAA,4BAAA,EAA+B,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACzF,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,GAAA,CAAI,aAAa,CAAA;AAC5C;AAEO,IAAM,QAAN,MAAY;AAAA;AAAA,EAEjB,YAA6B,IAAA,EAAc;AAAd,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAe;AAAA,EAAf,IAAA;AAAA,EAE7B,MAAc,IAAA,CAAK,EAAA,EAAY,KAAA,EAAmB,QAAQ,KAAA,EAA0B;AAClF,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,IAAA,CAAK,OAAO,EAAE,CAAA,CAAA,EAAI,OAAO,KAAK,CAAA;AACrD,IAAA,IAAI,GAAA,CAAI,KAAA,EAAO,MAAM,IAAI,eAAA,CAAgB,IAAI,KAAA,CAAM,IAAA,EAAM,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AAC1E,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAMA,MAAM,IAAA,CAAK,IAAA,EAAc,IAAA,GAAiB,EAAC,EAAwC;AACjF,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,KAAK,MAAA,EAAQ,EAAE,MAAM,CAAA;AAC5C,IAAA,MAAM,QAAQ,GAAA,CAAI,GAAA,GACd,MAAM,IAAA,CAAK,WAAW,GAAA,CAAI,GAAA,EAAK,GAAA,CAAI,SAAU,IAC7C,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,OAAA,IAAW,IAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,KAAK,MAAA,KAAW,OAAA,EAAS,OAAO,IAAI,WAAW,KAAK,CAAA;AACxD,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAQ,OAAO,IAAI,IAAA,CAAK,CAAC,IAAI,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AACnE,IAAA,OAAO,KAAA,CAAM,SAAS,MAAM,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAc,UAAA,CAAW,GAAA,EAAa,SAAA,EAAoC;AACxE,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,UAAU,GAAG,CAAA;AAAA,IAC5B,SAAS,CAAA,EAAG;AACV,MAAA,IAAI,IAAI,UAAA,CAAW,SAAS,KAAK,EAAE,CAAA,YAAa,kBAAkB,MAAM,CAAA;AACxE,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,KAAK,SAAA,EAAW,EAAE,SAAA,EAAU,EAAG,IAAI,CAAA;AACjE,MAAA,OAAO,UAAU,MAAO,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAKA,MAAM,KAAA,CACJ,WAAA,EACA,IAAA,EACkC;AAClC,IAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,EAAU,OAAO,IAAA,CAAK,WAAW,WAAW,CAAA;AACvE,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,KAAK,UAAA,CAAW,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,IAAA,IAAQ,EAAA,EAAI,CAAC,CAAA;AAC/E,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,WAAW,KAAA,EAA2C;AAC1D,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AACjE,IAAA,MAAM,UAAyE,EAAC;AAChF,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,KAAA,CAAM,SAAQ,EAAG;AACpC,MAAA,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AACjB,MAAA,IAAI,CAAA,CAAE,UAAU,gBAAA,EAAkB;AAChC,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,SAAS,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA,EAAG,CAAA;AAC5D,QAAA;AAAA,MACF;AACA,MAAA,MAAM,EAAE,WAAW,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,CAAA;AAC3D,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,CAAU,QAAS,CAAC,CAAA;AAC1B,QAAA,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,WAAuB,CAAA;AAAA,MACtD,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,KAAK,SAAA,EAAW,IAAI,IAAI,CAAA;AACjD,QAAA,MAAM,SAAA,CAAU,KAAA,CAAM,MAAA,EAAS,CAAC,CAAA;AAChC,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,SAAA,EAAW,KAAA,CAAM,WAAY,CAAA;AAAA,MAC5D;AAAA,IACF;AACA,IAAA,MAAM,EAAE,OAAA,GAAU,EAAC,EAAE,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA;AACpE,IAAA,OAAO,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,IAAA,GAAO,GAAA,EAAK,IAAA,GAAiB,EAAC,EAAyB;AAChE,IAAA,MAAM,EAAE,OAAA,GAAU,EAAC,KAAM,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,GAAG,CAAA;AACjF,IAAA,OAAO,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,OAAO,IAAA,EAAgC;AAC3C,IAAA,MAAM,EAAE,OAAM,GAAI,MAAM,KAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,CAAA;AAClD,IAAA,OAAO,KAAA,IAAS,IAAA;AAAA,EAClB;AAAA;AAAA,EAGA,MAAM,QAAQ,IAAA,EAAkC;AAC9C,IAAA,MAAM,EAAE,OAAM,GAAI,MAAM,KAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,CAAA;AAClD,IAAA,IAAI,CAAC,OAAO,MAAM,IAAI,gBAAgB,WAAA,EAAa,CAAA,EAAG,IAAI,CAAA,eAAA,CAAiB,CAAA;AAC3E,IAAA,OAAO,QAAQ,KAAK,CAAA;AAAA,EACtB;AAAA;AAAA,EAGA,MAAM,QAAQ,IAAA,EAAgC;AAC5C,IAAA,MAAM,EAAE,SAAQ,GAAI,MAAM,KAAK,IAAA,CAAK,OAAA,EAAS,EAAE,IAAA,EAAM,CAAA;AACrD,IAAA,OAAO,OAAA,KAAY,IAAA;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,MAAA,CAAO,OAAA,EAAiB,OAAA,EAAqC;AACjE,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,CAAA;AACtE,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,OAAA,EAAiB,OAAA,EAAqC;AAC/D,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,CAAA;AAC7E,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,OAAO,IAAA,EAA6B;AACxC,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,EAAE,MAAM,CAAA;AAAA,EACpC;AAAA;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,IAAA,EAAc,IAAA,GAAqB,EAAC,EAAuB;AACrF,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,KAAK,UAAA,EAAY;AAAA,MAC5C,GAAA;AAAA,MACA,IAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AACD,IAAA,OAAO,QAAQ,KAAM,CAAA;AAAA,EACvB;AAAA;AAAA,EAEA,MAAM,MAAA,CAAO,IAAA,EAAc,GAAA,EAAa,IAAA,GAAqB,EAAC,EAAkB;AAC9E,IAAA,MAAM,IAAA,CAAK,KAAK,QAAA,EAAU;AAAA,MACxB,IAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AAAA,EACH;AACF;;;AClPA,IAAI,gBAAA,GAAmB,KAAA;AAEvB,eAAsB,cAAA,GAAgC;AACpD,EAAA,IACE,gBAAA,IACA,QAAQ,GAAA,CAAI,oBAAA,KAAyB,WACrC,OAAA,CAAQ,GAAA,CAAI,iBAAiB,OAAA,EAC7B;AACA,IAAA;AAAA,EACF;AACA,EAAA,gBAAA,GAAmB,IAAA;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,CAAC,EAAE,wBAAA,EAAyB,EAAG,EAAE,qBAAqB,CAAA,GAAI,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,MAChF,OAAO,gCAAgC,CAAA;AAAA,MACvC,OAAO,oDAAoD;AAAA,KAC5D,CAAA;AACD,IAAA,wBAAA,CAAyB,EAAE,gBAAA,EAAkB,CAAC,IAAI,mBAAA,EAAqB,GAAG,CAAA;AAAA,EAC5E,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iCAAA,EAAqC,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,EAC5E;AACF;;;AChBA,IAAM,UAAA,GAAa,CAAC,iBAAA,EAAmB,iBAAiB,CAAA;AACxD,IAAM,SAAA,uBAAgB,OAAA,EAAwC;AAE9D,eAAe,UAAA,CAAW,QAAuB,IAAA,EAAgC;AAC/E,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAA;AAC7C,EAAA,MAAM,IAAA,GAAO,KAAK,UAAA,CAAW,SAAS,IAAI,IAAA,GAAO,CAAA,EAAG,SAAS,CAAA,EAAG,IAAI,CAAA,CAAA;AACpE,EAAA,KAAA,IAAS,SAAS,CAAA,MAAM;AACtB,IAAA,MAAM,EAAE,IAAA,GAAO,EAAC,KAAM,MAAM,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,QAAQ,CAAA;AACpF,IAAA,IAAI,IAAA,CAAK,KAAK,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,IAAI,GAAG,OAAO,IAAA;AAC9C,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAC9B,IAAA,MAAA,IAAU,IAAA,CAAK,MAAA;AAAA,EACjB;AACF;AAEA,eAAe,MAAM,MAAA,EAAoD;AACvE,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,IAAI,MAAM,UAAA,CAAW,MAAA,EAAQ,IAAI,GAAG,OAAO,IAAA;AAAA,EAC7C;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,gBAAgB,MAAA,EAAwC;AAC/D,EAAA,IAAI,OAAA,GAAU,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA;AAClC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,KAAA,CAAM,MAAM,CAAA,CAAE,IAAA;AAAA,MACtB,CAAC,IAAA,KAAS;AACR,QAAA,IAAI,CAAC,IAAA,EAAM,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAClC,QAAA,OAAO,IAAA,IAAQ,UAAA,CAAW,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA;AAAA,MACjD,CAAA;AAAA,MACA,CAAC,GAAA,KAAQ;AACP,QAAA,SAAA,CAAU,OAAO,MAAM,CAAA;AACvB,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,KACF;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,OAAA;AACT;AA8DA,IAAM,KAAA,GAAgC;AAAA,EACpC,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,GAAA;AAAA,EACH,CAAA,EAAG,IAAA;AAAA,EACH,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK,EAAA;AAAA,EACT,IAAI,CAAA,IAAK;AACX,CAAA;AAEA,SAAS,KAAA,CAAM,OAAwB,KAAA,EAAuB;AAC5D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,KAAK,KAAA,IAAS,CAAA;AACvC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,UAAA,EAAa,KAAK,CAAA,yCAAA,CAA2C,CAAA;AAC/E,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,CAAA,GAAI,kCAAA,CAAmC,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC9D,EAAA,IAAI,CAAC,CAAA;AACH,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,aAAa,KAAK,CAAA,uFAAA,EAA0F,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,KACnI;AACF,EAAA,MAAM,KAAA,GAAQ,OAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,KAAA,CAAM,CAAA,CAAE,CAAC,CAAC,CAAA;AACvC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,KAAA,GAAQ,MAAM,EAAE,CAAA;AACtC,EAAA,IAAI,OAAO,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,UAAA,EAAa,KAAK,CAAA,sBAAA,CAAwB,CAAA;AACxE,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,cAAc,CAAA,EAA0B;AAC/C,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,IAAI,CAAA,CAAE,SAAS,MAAA,EAAW;AACxB,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,EAAE,IAAI,CAAA,IAAK,EAAE,IAAA,IAAQ,CAAA;AACzC,MAAA,MAAM,IAAI,MAAM,2DAA2D,CAAA;AAC7E,IAAA,GAAA,CAAI,OAAO,CAAA,CAAE,IAAA;AAAA,EACf;AACA,EAAA,IAAI,CAAA,CAAE,WAAW,MAAA,EAAW,GAAA,CAAI,YAAY,KAAA,CAAM,CAAA,CAAE,QAAQ,QAAQ,CAAA;AACpE,EAAA,IAAI,CAAA,CAAE,SAAS,MAAA,EAAW,GAAA,CAAI,UAAU,KAAA,CAAM,CAAA,CAAE,MAAM,MAAM,CAAA;AAC5D,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,KAAW,CAAA;AAC9B,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AACrE,EAAA,OAAO,GAAA;AACT;AA+BA,SAAS,WAAW,MAAA,EAAgC;AAClD,EAAA,MAAM,QAAA,GAAW,gBAAgB,MAAM,CAAA;AACvC,EAAA,OAAO,OAAO,OAAO,IAAA,KAAS;AAC5B,IAAA,MAAM,OAAO,MAAM,QAAA;AACnB,IAAA,MAAM,kBAAA,GAAqB;AAAA,MACzB,sBAAsB,KAAA,CAAM,EAAA;AAAA,MAC5B,GAAI,MAAM,SAAA,GAAY,EAAE,sBAAsB,KAAA,CAAM,SAAA,KAAc,EAAC;AAAA,MACnE,GAAI,MAAM,KAAA,GAAQ,EAAE,yBAAyB,KAAA,CAAM,KAAA,KAAU,EAAC;AAAA,MAC9D,GAAI,MAAM,UAAA,GAAa,EAAE,wBAAwB,KAAA,CAAM,UAAA,KAAe;AAAC,KACzE;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,GACjB,MAAA,CACE,MAAM,MAAA,CAAO,KAAA,CAAM,WAAA,CAAmD,IAAA,EAAM,KAAA,EAAO;AAAA,MACjF;AAAA,KACD,CAAA,EACD,MAAA,EAAO,GACT,MAAM,MAAA,CACH,QAAA,CAAgD,EAAE,IAAA,EAAM,CAAA,CACxD,GAAA,CAAI,KAAA,EAAO,EAAE,oBAAoB,CAAA;AACxC,IAAA,OAAO,MAAA,CAAO,IAAI,CAAA,IAAM,MAAA;AAAA,EAC1B,CAAA;AACF;AAGO,IAAM,OAAA,GAAN,MAAM,QAAA,CAAQ;AAAA,EAIX,WAAA,CACW,GAAA,EACR,SAAA,EACQ,QAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AACR,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACQ,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAEjB,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAA,CAAM,CAAC,EAAA,EAAI,KAAA,EAAO,KAAA,KAAU,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,KAAA,EAAO,KAAK,CAAC,CAAA;AAAA,EAC1E;AAAA,EALmB,GAAA;AAAA,EACR,SAAA;AAAA,EACQ,QAAA;AAAA;AAAA,EALV,KAAA;AAAA;AAAA,EAWT,aAAa,MAAA,CAAO,MAAA,EAAuB,IAAA,GAAoB,EAAC,EAAqB;AACnF,IAAA,MAAM,cAAA,EAAe;AACrB,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,GAAW,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,QAAA,EAAU,IAAA,CAAK,QAAA,EAAS,GAAI,IAAA,CAAK,QAAA;AACtF,IAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI;AAAA,MACxB,EAAA,EAAI,SAAA;AAAA,MACJ,OAAO,EAAC;AAAA,MACR,GAAI,KAAK,EAAA,GAAK,EAAE,WAAW,IAAA,CAAK,EAAA,KAAO,EAAC;AAAA,MACxC,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,MAChD,GAAI,KAAK,IAAA,GAAO,EAAE,YAAY,IAAA,CAAK,IAAA,KAAS,EAAC;AAAA,MAC7C,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,MAC/B,GAAI,KAAK,aAAA,GAAgB,EAAE,WAAW,IAAA,CAAK,aAAA,KAAkB,EAAC;AAAA,MAC9D,GAAI,IAAA,CAAK,qBAAA,GAAwB,EAAE,eAAA,EAAiB,IAAA,KAAS,EAAC;AAAA,MAC9D,GAAI,IAAA,CAAK,SAAA,GAAY,EAAE,SAAA,EAAW,cAAc,IAAA,CAAK,SAAS,CAAA,EAAE,GAAI;AAAC,KACtE,CAAA;AACD,IAAA,OAAO,IAAI,QAAA,CAAQ,GAAA,EAAK,OAAA,CAAQ,SAAA,EAAW,KAAK,QAAQ,CAAA;AAAA,EAC1D;AAAA;AAAA,EAGA,aAAa,OAAA,CACX,MAAA,EACA,SAAA,EACA,IAAA,GAAoB,EAAC,EACH;AAClB,IAAA,MAAM,cAAA,EAAe;AACrB,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,GAAA,CAAI;AAAA,MACR,EAAA,EAAI,UAAA;AAAA,MACJ,OAAO,EAAC;AAAA,MACR,SAAA;AAAA,MACA,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa;AAAC,KACjD,CAAA;AACD,IAAA,OAAO,IAAI,QAAA,CAAQ,GAAA,EAAK,SAAA,EAAW,KAAK,QAAQ,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,aAAa,IAAA,CAAK,MAAA,EAAuB,IAAA,GAAwB,EAAC,EAA2B;AAC3F,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAM,CAAA,CAAE;AAAA,MACtC,EAAA,EAAI,OAAA;AAAA,MACJ,KAAA,EAAO;AAAA,QACL,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc,EAAC;AAAA,QACtD,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa;AAAC;AACrD,KACD,CAAA;AACD,IAAA,MAAM,GAAA,GAAO,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAC;AAGzC,IAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACrB,GAAG,CAAA;AAAA,MACH,SAAA,EAAW,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAAA,MAC/B,UAAU,CAAA,CAAE,QAAA,GAAW,IAAI,IAAA,CAAK,CAAA,CAAE,QAAQ,CAAA,GAAI;AAAA,KAChD,CAAE,CAAA;AAAA,EACJ;AAAA;AAAA,EAGA,aAAa,MAAA,CAAO,MAAA,EAAuB,IAAA,EAA0C;AACnF,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,KAAK,QAAA,IAAY,EAAE,CAAA,CAAE,MAAA,KAAW,CAAA;AACjE,MAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AACjE,IAAA,MAAM,GAAA,GAAM,WAAW,MAAM,CAAA;AAC7B,IAAA,MAAM,MAAgB,EAAC;AACvB,IAAA,KAAA,MAAW,EAAE,WAAU,IAAK,MAAM,SAAQ,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA,EAAG;AAC5D,MAAA,MAAM,GAAA,CAAI,EAAE,EAAA,EAAI,SAAA,EAAW,OAAO,EAAC,EAAG,WAAW,CAAA;AACjD,MAAA,GAAA,CAAI,KAAK,SAAS,CAAA;AAAA,IACpB;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,IAAA,CAAK,GAAA,EAAa,IAAA,GAAiB,EAAC,EAA2B;AACnE,IAAA,OAAO,IAAA,CAAK,KAAoB,UAAA,EAAY;AAAA,MAC1C,GAAA;AAAA,MACA,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,EAAE,CAAA;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,MAAA,GAAwB;AAC5B,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAc,IAAA,CAAqB,EAAA,EAAY,KAAA,EAAmB,QAAQ,KAAA,EAAmB;AAC3F,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA;AAAA,MACxB;AAAA,QACE,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,GAAI,KAAK,QAAA,GAAW,EAAE,OAAO,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,QAChD,EAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,EAAE,KAAA;AAAM,KACV;AACA,IAAA,OAAO;AAAA,MACL,GAAG,MAAA,CAAO,MAAA;AAAA,MACV,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,SAAS,MAAA,CAAO;AAAA,KAClB;AAAA,EACF;AACF;AAoBA,MAAA,CAAO,cAAA,CAAe,aAAA,CAAc,SAAA,EAAW,SAAA,EAAW;AAAA,EACxD,YAAA,EAAc,IAAA;AAAA,EACd,GAAA,GAA2C;AACzC,IAAA,OAAO;AAAA,MACL,QAAQ,CAAC,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,MAC3C,OAAA,EAAS,CAAC,SAAA,EAAW,IAAA,KAAS,QAAQ,OAAA,CAAQ,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,MACnE,MAAM,CAAC,IAAA,KAAS,OAAA,CAAQ,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,MACvC,QAAQ,CAAC,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,MAAM,IAAI;AAAA,KAC7C;AAAA,EACF;AACF,CAAC,CAAA","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 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};\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 with a unit like '512Mi', '4Gi' or '8G', or a number of MiB, got ${JSON.stringify(value)}`\n );\n const bytes = Number(m[1]) * UNITS[m[2]];\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hatchet-dev/sandbox",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Hatchet Sandbox TypeScript SDK",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"typecheck": "tsc --noEmit",
|
|
62
62
|
"lint": "pnpm run eslint:check && pnpm run prettier:check",
|
|
63
63
|
"lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix",
|
|
64
|
-
"eslint:check": "eslint \"src/**/*.ts\"",
|
|
65
|
-
"eslint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
66
|
-
"prettier:check": "prettier \"src/**/*.ts\" \"*.md\" --list-different",
|
|
67
|
-
"prettier:fix": "prettier \"src/**/*.ts\" \"*.md\" --write",
|
|
64
|
+
"eslint:check": "eslint \"src/**/*.ts\" \"examples/**/*.ts\"",
|
|
65
|
+
"eslint:fix": "eslint \"src/**/*.ts\" \"examples/**/*.ts\" --fix",
|
|
66
|
+
"prettier:check": "prettier \"src/**/*.ts\" \"examples/**/*.ts\" \"*.md\" --list-different",
|
|
67
|
+
"prettier:fix": "prettier \"src/**/*.ts\" \"examples/**/*.ts\" \"*.md\" --write",
|
|
68
68
|
"publish:ci": "pnpm run build && pnpm publish --access public --no-git-checks",
|
|
69
69
|
"publish:ci:alpha": "pnpm run build && pnpm publish --access public --no-git-checks --tag alpha",
|
|
70
70
|
"release:local": "pnpm run build:sdk && pnpm install && pnpm run lint && pnpm run build && pnpm publish --access public --no-git-checks"
|