@computesdk/archil 0.4.9 → 0.4.10

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/README.md CHANGED
@@ -58,7 +58,7 @@ await provider.sandbox.destroy(sandbox.sandboxId);
58
58
  | `runCommand` | ✅ | Executes shell commands through Archil's HTTP `exec` endpoint. |
59
59
  | `getInfo` | ✅ | |
60
60
  | `getUrl` | ❌ | Each exec runs in a fresh ephemeral container — no port to expose. |
61
- | `filesystem` | ✅ | Implemented via shell commands (`cat`, `find`, `mkdir`, etc.). |
61
+ | `filesystem` | ✅ | Maps paths into `/mnt/archil` and manages shared-mode checkout/checkin automatically. |
62
62
 
63
63
  ## Limitations
64
64
 
@@ -67,5 +67,8 @@ await provider.sandbox.destroy(sandbox.sandboxId);
67
67
  - Responses are truncated to ~5 MB by the Archil control plane.
68
68
  - `getUrl` is not supported — each exec runs in a fresh ephemeral container,
69
69
  so there is no long-lived process to expose a port on.
70
- - Filesystem operations are implemented as shell commands, so each call
71
- costs one HTTP round trip.
70
+ - Filesystem operations accept normal absolute paths and map them into the
71
+ `/mnt/archil` disk mount internally. Each mutating operation checks out and
72
+ checks in the disk automatically.
73
+ - Raw `runCommand` strings are not rewritten. Commands that access the disk
74
+ directly must use `/mnt/archil` themselves.
package/dist/index.js CHANGED
@@ -24,6 +24,11 @@ __export(index_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
  var import_provider = require("@computesdk/provider");
27
+ var import_node_crypto = require("crypto");
28
+ var import_node_path = require("path");
29
+ var ARCHIL_MOUNT_ROOT = "/mnt/archil";
30
+ var ARCHIL_MAX_EXEC_COMMAND_BYTES = 102400;
31
+ var ARCHIL_MAX_READ_CHUNK_BYTES = 2 * 1024 * 1024;
27
32
  var REGION_COLORS = {
28
33
  "gcp-us-central1": "blue"
29
34
  };
@@ -94,6 +99,73 @@ function resolveCreateDiskId(options) {
94
99
  function shellEscape(value) {
95
100
  return `'${value.replace(/'/g, `'\\''`)}'`;
96
101
  }
102
+ function mapFilesystemPath(path) {
103
+ const normalized = import_node_path.posix.normalize(path.startsWith("/") ? path : `/${path}`);
104
+ if (normalized === "/") {
105
+ return ARCHIL_MOUNT_ROOT;
106
+ }
107
+ if (normalized === ARCHIL_MOUNT_ROOT || normalized.startsWith(`${ARCHIL_MOUNT_ROOT}/`)) {
108
+ return normalized;
109
+ }
110
+ return `${ARCHIL_MOUNT_ROOT}${normalized}`;
111
+ }
112
+ function withDiskWriteLock(command) {
113
+ const mountRoot = shellEscape(ARCHIL_MOUNT_ROOT);
114
+ return [
115
+ `archil checkout --force --yes ${mountRoot}`,
116
+ `{ ${command}; status=$?; archil checkin ${mountRoot}; checkin_status=$?; if [ $status -ne 0 ]; then exit $status; fi; exit $checkin_status; }`
117
+ ].join(" && ");
118
+ }
119
+ function execCommandBytes(command) {
120
+ return Buffer.byteLength(wrapCommand(command), "utf8");
121
+ }
122
+ function buildWriteChunkCommand(parent, tempPath, diskPath, encodedChunk, isFirst, isFinal) {
123
+ const writeCommand = `printf %s ${shellEscape(encodedChunk)} | base64 -d ${isFirst ? ">" : ">>"} ${shellEscape(tempPath)}`;
124
+ return [
125
+ ...isFirst ? [`mkdir -p ${shellEscape(parent)}`] : [],
126
+ writeCommand,
127
+ ...isFinal ? [finalizeStagedFileCommand(tempPath, diskPath)] : []
128
+ ].join(" && ");
129
+ }
130
+ function finalizeStagedFileCommand(tempPath, diskPath) {
131
+ const quotedDestination = shellEscape(diskPath);
132
+ return [
133
+ `if [ -d ${quotedDestination} ]; then`,
134
+ `printf '%s\\n' ${shellEscape(`Refusing to overwrite directory ${diskPath}`)} >&2;`,
135
+ "exit 1;",
136
+ "fi;",
137
+ `mv ${shellEscape(tempPath)} ${quotedDestination}`
138
+ ].join(" ");
139
+ }
140
+ function maxWriteChunkSize(parent, tempPath, diskPath) {
141
+ let low = 0;
142
+ let high = ARCHIL_MAX_EXEC_COMMAND_BYTES;
143
+ while (low < high) {
144
+ const candidate = Math.ceil((low + high) / 2);
145
+ const command = withDiskWriteLock(
146
+ buildWriteChunkCommand(
147
+ parent,
148
+ tempPath,
149
+ diskPath,
150
+ "A".repeat(candidate),
151
+ true,
152
+ true
153
+ )
154
+ );
155
+ if (execCommandBytes(command) <= ARCHIL_MAX_EXEC_COMMAND_BYTES) {
156
+ low = candidate;
157
+ } else {
158
+ high = candidate - 1;
159
+ }
160
+ }
161
+ const chunkSize = low - low % 4;
162
+ if (chunkSize < 4) {
163
+ throw new Error(
164
+ `Archil filesystem path is too long to write within the ${ARCHIL_MAX_EXEC_COMMAND_BYTES}-byte exec command limit.`
165
+ );
166
+ }
167
+ return chunkSize;
168
+ }
97
169
  function wrapCommand(command, options) {
98
170
  let wrapped = command;
99
171
  const envEntries = Object.entries(options?.env ?? {});
@@ -198,36 +270,132 @@ var _provider = (0, import_provider.defineProvider)({
198
270
  },
199
271
  filesystem: {
200
272
  readFile: async (sandbox, path, runCommand) => {
201
- const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);
202
- if (result.exitCode !== 0) {
203
- throw new Error(`Failed to read ${path}: ${result.stderr}`);
273
+ const diskPath = mapFilesystemPath(path);
274
+ const sizeResult = await runCommand(
275
+ sandbox,
276
+ `wc -c < ${shellEscape(diskPath)}`
277
+ );
278
+ if (sizeResult.exitCode !== 0) {
279
+ throw new Error(`Failed to read ${path}: ${sizeResult.stderr}`);
280
+ }
281
+ const sizeText = sizeResult.stdout.trim();
282
+ if (!/^\d+$/.test(sizeText)) {
283
+ throw new Error(
284
+ `Failed to read ${path}: Archil returned an invalid file size.`
285
+ );
286
+ }
287
+ const size = Number(sizeText);
288
+ if (!Number.isSafeInteger(size)) {
289
+ throw new Error(
290
+ `Failed to read ${path}: file size exceeds JavaScript's safe integer range.`
291
+ );
292
+ }
293
+ if (size === 0) return "";
294
+ const chunks = [];
295
+ for (let offset = 0; offset < size; offset += ARCHIL_MAX_READ_CHUNK_BYTES) {
296
+ const expectedBytes = Math.min(
297
+ ARCHIL_MAX_READ_CHUNK_BYTES,
298
+ size - offset
299
+ );
300
+ const result = await runCommand(
301
+ sandbox,
302
+ `dd if=${shellEscape(diskPath)} bs=1 skip=${offset} count=${expectedBytes} 2>/dev/null | base64`
303
+ );
304
+ if (result.exitCode !== 0) {
305
+ throw new Error(`Failed to read ${path}: ${result.stderr}`);
306
+ }
307
+ const encoded = result.stdout.replace(/\s/g, "");
308
+ if (encoded.length === 0 || encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {
309
+ throw new Error(
310
+ `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`
311
+ );
312
+ }
313
+ const chunk = Buffer.from(encoded, "base64");
314
+ if (chunk.length !== expectedBytes) {
315
+ throw new Error(
316
+ `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`
317
+ );
318
+ }
319
+ chunks.push(chunk);
204
320
  }
205
- return result.stdout;
321
+ return Buffer.concat(chunks).toString("utf8");
206
322
  },
207
323
  writeFile: async (sandbox, path, content, runCommand) => {
208
- const parent = path.substring(0, path.lastIndexOf("/"));
209
- if (parent) {
210
- await runCommand(sandbox, `mkdir -p ${shellEscape(parent)}`);
211
- }
324
+ const diskPath = mapFilesystemPath(path);
325
+ const parent = import_node_path.posix.dirname(diskPath);
212
326
  const encoded = Buffer.from(content, "utf8").toString("base64");
213
- const result = await runCommand(
214
- sandbox,
215
- `printf %s ${shellEscape(encoded)} | base64 -d > ${shellEscape(path)}`
216
- );
217
- if (result.exitCode !== 0) {
218
- throw new Error(`Failed to write ${path}: ${result.stderr}`);
327
+ const tempPath = `${diskPath}.computesdk-write-${(0, import_node_crypto.randomUUID)()}`;
328
+ let started = false;
329
+ try {
330
+ if (encoded.length === 0) {
331
+ started = true;
332
+ const result = await runCommand(
333
+ sandbox,
334
+ withDiskWriteLock(
335
+ [
336
+ `mkdir -p ${shellEscape(parent)}`,
337
+ `: > ${shellEscape(tempPath)}`,
338
+ finalizeStagedFileCommand(tempPath, diskPath)
339
+ ].join(" && ")
340
+ )
341
+ );
342
+ if (result.exitCode !== 0) {
343
+ throw new Error(result.stderr);
344
+ }
345
+ return;
346
+ }
347
+ const chunkSize = maxWriteChunkSize(parent, tempPath, diskPath);
348
+ for (let offset = 0; offset < encoded.length; offset += chunkSize) {
349
+ const isFirst = offset === 0;
350
+ const isFinal = offset + chunkSize >= encoded.length;
351
+ started = true;
352
+ const result = await runCommand(
353
+ sandbox,
354
+ withDiskWriteLock(
355
+ buildWriteChunkCommand(
356
+ parent,
357
+ tempPath,
358
+ diskPath,
359
+ encoded.slice(offset, offset + chunkSize),
360
+ isFirst,
361
+ isFinal
362
+ )
363
+ )
364
+ );
365
+ if (result.exitCode !== 0) {
366
+ throw new Error(result.stderr);
367
+ }
368
+ }
369
+ } catch (error) {
370
+ if (started) {
371
+ try {
372
+ await runCommand(
373
+ sandbox,
374
+ withDiskWriteLock(`rm -f ${shellEscape(tempPath)}`)
375
+ );
376
+ } catch {
377
+ }
378
+ }
379
+ throw new Error(
380
+ `Failed to write ${path}: ${error instanceof Error ? error.message : String(error)}`
381
+ );
219
382
  }
220
383
  },
221
384
  mkdir: async (sandbox, path, runCommand) => {
222
- const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);
385
+ const diskPath = mapFilesystemPath(path);
386
+ const result = await runCommand(
387
+ sandbox,
388
+ withDiskWriteLock(`mkdir -p ${shellEscape(diskPath)}`)
389
+ );
223
390
  if (result.exitCode !== 0) {
224
391
  throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
225
392
  }
226
393
  },
227
394
  readdir: async (sandbox, path, runCommand) => {
395
+ const diskPath = mapFilesystemPath(path);
228
396
  const result = await runCommand(
229
397
  sandbox,
230
- `find ${shellEscape(path)} -mindepth 1 -maxdepth 1 -printf '%y\\t%s\\t%T@\\t%f\\n'`
398
+ `find ${shellEscape(diskPath)} -mindepth 1 -maxdepth 1 -printf '%y\\t%s\\t%T@\\t%f\\n'`
231
399
  );
232
400
  if (result.exitCode !== 0) {
233
401
  throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
@@ -247,11 +415,19 @@ var _provider = (0, import_provider.defineProvider)({
247
415
  return entries;
248
416
  },
249
417
  exists: async (sandbox, path, runCommand) => {
250
- const result = await runCommand(sandbox, `test -e ${shellEscape(path)}`);
418
+ const diskPath = mapFilesystemPath(path);
419
+ const result = await runCommand(sandbox, `test -e ${shellEscape(diskPath)}`);
251
420
  return result.exitCode === 0;
252
421
  },
253
422
  remove: async (sandbox, path, runCommand) => {
254
- const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);
423
+ const diskPath = mapFilesystemPath(path);
424
+ if (diskPath === ARCHIL_MOUNT_ROOT) {
425
+ throw new Error("Refusing to remove the Archil disk mount root.");
426
+ }
427
+ const result = await runCommand(
428
+ sandbox,
429
+ withDiskWriteLock(`rm -rf ${shellEscape(diskPath)}`)
430
+ );
255
431
  if (result.exitCode !== 0) {
256
432
  throw new Error(`Failed to remove ${path}: ${result.stderr}`);
257
433
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Archil Provider\n *\n * Executes commands against an Archil disk via the Archil control-plane HTTP\n * API. Archil is exec-only — each command runs in an Archil-managed container\n * with the configured disk mounted, then returns stdout, stderr, and exit code.\n * There is no sandbox lifecycle to manage; \"create\" resolves a handle to an\n * existing disk id.\n */\n\nimport { defineProvider } from '@computesdk/provider';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n// Per-region color overrides. Default is \"green\" for any region not listed here.\nconst REGION_COLORS: Record<string, string> = {\n 'gcp-us-central1': 'blue',\n};\n\nfunction regionToBaseUrl(region: string): string {\n const dash = region.indexOf('-');\n if (dash <= 0 || dash === region.length - 1) {\n throw new Error(\n `Invalid Archil region \"${region}\". Expected \"{cloud}-{suffix}\", e.g. \"aws-us-east-1\".`,\n );\n }\n const cloud = region.slice(0, dash);\n const suffix = region.slice(dash + 1);\n const color = REGION_COLORS[region] ?? 'green';\n return `https://control.${color}.${suffix}.${cloud}.prod.archil.com`;\n}\n\nexport interface ArchilConfig {\n /** Archil API key. Falls back to ARCHIL_API_KEY env var. */\n apiKey?: string;\n /** Archil region (e.g. \"aws-us-east-1\"). Falls back to ARCHIL_REGION env var. */\n region?: string;\n /** Override the control-plane base URL (useful for testing). */\n baseUrl?: string;\n}\n\ninterface DiskResponse {\n id: string;\n name: string;\n organization: string;\n status: string;\n provider: string;\n region: string;\n createdAt: string;\n}\n\ntype DiskHandle = Pick<DiskResponse, 'id'>;\n\ninterface ExecTiming {\n totalMs: number;\n queueMs: number;\n executeMs: number;\n}\n\ninterface ExecResponse {\n exitCode: number;\n stdout: string;\n stderr: string;\n timing: ExecTiming;\n}\n\ninterface ResolvedConfig {\n apiKey: string;\n baseUrl: string;\n}\n\ninterface ArchilSandbox {\n disk: DiskHandle | DiskResponse;\n resolved: ResolvedConfig;\n createdAt: Date;\n}\n\ninterface ArchilCreateOptions extends CreateSandboxOptions {\n diskId?: string;\n}\n\nfunction resolveConfig(config: ArchilConfig): ResolvedConfig {\n const apiKey = config.apiKey ?? process.env.ARCHIL_API_KEY;\n const region = config.region ?? process.env.ARCHIL_REGION;\n\n if (!apiKey) {\n throw new Error(\n 'Missing API key for Archil.\\n\\n' +\n 'Pass it: archil({ apiKey: \"...\" })\\n' +\n 'Or set ARCHIL_API_KEY in your environment.',\n );\n }\n\n let baseUrl = config.baseUrl;\n if (!baseUrl) {\n if (!region) {\n throw new Error(\n 'Missing region for Archil.\\n\\n' +\n 'Pass it: archil({ region: \"...\" })\\n' +\n 'Or set ARCHIL_REGION in your environment.\\n' +\n 'Examples: \"aws-us-east-1\", \"aws-eu-west-1\", \"gcp-us-central1\".',\n );\n }\n baseUrl = regionToBaseUrl(region);\n }\n\n return { apiKey, baseUrl };\n}\n\nfunction authHeader(apiKey: string): string {\n return `key-${apiKey.replace(/^key-/, '')}`;\n}\n\nasync function callApi<T>(\n resolved: ResolvedConfig,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n const response = await fetch(`${resolved.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: authHeader(resolved.apiKey),\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n type Envelope = { success?: boolean; data?: T; error?: string };\n let payload: Envelope | null = null;\n try {\n payload = (await response.json()) as Envelope;\n } catch {\n payload = null;\n }\n\n if (!response.ok || !payload || payload.success === false) {\n const message =\n (payload && payload.error) ||\n `Archil API ${method} ${path} failed with status ${response.status}`;\n throw new Error(message);\n }\n\n return payload.data as T;\n}\n\nfunction resolveCreateDiskId(options?: ArchilCreateOptions): string {\n const diskId = options?.diskId;\n\n if (!diskId) {\n throw new Error(\n 'Archil create() requires an existing disk id on the top-level options.\\n\\n' +\n 'Example:\\n' +\n ' provider.sandbox.create({ diskId: \"disk_abc123\" })',\n );\n }\n\n return diskId;\n}\n\nfunction shellEscape(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction wrapCommand(command: string, options?: RunCommandOptions): string {\n let wrapped = command;\n\n const envEntries = Object.entries(options?.env ?? {});\n if (!envEntries.some(([key]) => key === 'HOME')) {\n envEntries.unshift(['HOME', process.env.HOME || '/tmp']);\n }\n const envPrefix = envEntries\n .map(([k, v]) => `${k}=${shellEscape(String(v))}`)\n .join(' ');\n wrapped = `${envPrefix} ${wrapped}`;\n\n if (options?.cwd) {\n wrapped = `cd ${shellEscape(options.cwd)} && ${wrapped}`;\n }\n\n if (options?.background) {\n wrapped = `nohup sh -c ${shellEscape(wrapped)} > /dev/null 2>&1 &`;\n }\n\n return wrapped;\n}\n\nasync function execOnDisk(sandbox: ArchilSandbox, command: string): Promise<ExecResponse> {\n return callApi<ExecResponse>(\n sandbox.resolved,\n 'POST',\n `/api/disks/${encodeURIComponent(sandbox.disk.id)}/exec`,\n { command },\n );\n}\n\nconst _provider = defineProvider<ArchilSandbox, ArchilConfig>({\n name: 'archil',\n methods: {\n sandbox: {\n create: async (config: ArchilConfig, options?: ArchilCreateOptions) => {\n const resolved = resolveConfig(config);\n const diskId = resolveCreateDiskId(options);\n return {\n sandbox: { disk: { id: diskId }, resolved, createdAt: new Date() },\n sandboxId: diskId,\n };\n },\n\n getById: async (config: ArchilConfig, sandboxId: string) => {\n const resolved = resolveConfig(config);\n try {\n const disk = await callApi<DiskResponse>(\n resolved,\n 'GET',\n `/api/disks/${encodeURIComponent(sandboxId)}`,\n );\n return {\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: ArchilConfig) => {\n const resolved = resolveConfig(config);\n const disks = await callApi<DiskResponse[]>(resolved, 'GET', '/api/disks');\n return disks.map((disk) => ({\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n }));\n },\n\n destroy: async (_config: ArchilConfig, _sandboxId: string) => {\n // No-op: Archil disks have an independent lifecycle.\n },\n\n runCommand: async (\n sandbox: ArchilSandbox,\n command: string,\n options?: RunCommandOptions,\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const result = await execOnDisk(sandbox, wrapCommand(command, options));\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 1,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (sandbox: ArchilSandbox): Promise<SandboxInfo> => {\n const diskInfo = 'status' in sandbox.disk ? sandbox.disk : undefined;\n return {\n id: sandbox.disk.id,\n provider: 'archil',\n status: !diskInfo || diskInfo.status === 'ready' ? 'running' : 'stopped',\n createdAt: diskInfo ? new Date(diskInfo.createdAt) : sandbox.createdAt,\n timeout: 0,\n metadata: diskInfo\n ? {\n name: diskInfo.name,\n organization: diskInfo.organization,\n region: diskInfo.region,\n provider: diskInfo.provider,\n }\n : {},\n };\n },\n\n getUrl: async (\n _sandbox: ArchilSandbox,\n options: { port: number; protocol?: string },\n ): Promise<string> => {\n throw new Error(\n `Archil exec runs each command in a fresh ephemeral container that exits when the command returns, ` +\n `so there is no long-lived process to expose port ${options.port} on. ` +\n `getUrl is not supported.`,\n );\n },\n\n filesystem: {\n readFile: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${result.stderr}`);\n }\n return result.stdout;\n },\n\n writeFile: async (sandbox, path, content, runCommand) => {\n const parent = path.substring(0, path.lastIndexOf('/'));\n if (parent) {\n await runCommand(sandbox, `mkdir -p ${shellEscape(parent)}`);\n }\n // base64-pipe to avoid heredoc/quoting hazards on arbitrary content.\n const encoded = Buffer.from(content, 'utf8').toString('base64');\n const result = await runCommand(\n sandbox,\n `printf %s ${shellEscape(encoded)} | base64 -d > ${shellEscape(path)}`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to write ${path}: ${result.stderr}`);\n }\n },\n\n mkdir: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox, path, runCommand) => {\n // Tab-separated: type<TAB>size<TAB>mtime-iso<TAB>name. Robust to spaces in names.\n const result = await runCommand(\n sandbox,\n `find ${shellEscape(path)} -mindepth 1 -maxdepth 1 -printf '%y\\\\t%s\\\\t%T@\\\\t%f\\\\n'`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n const entries: FileEntry[] = [];\n for (const line of result.stdout.split('\\n')) {\n if (!line) continue;\n const [typeChar, sizeStr, mtimeStr, ...nameParts] = line.split('\\t');\n const name = nameParts.join('\\t');\n entries.push({\n name,\n type: typeChar === 'd' ? 'directory' : 'file',\n size: parseInt(sizeStr, 10) || 0,\n modified: new Date(parseFloat(mtimeStr) * 1000),\n });\n }\n return entries;\n },\n\n exists: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `test -e ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n getInstance: (sandbox: ArchilSandbox): ArchilSandbox => sandbox,\n },\n },\n});\n\nexport const archil = (config: ArchilConfig = {}) => _provider(config);\n\nexport type { ArchilSandbox };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Archil Provider\n *\n * Executes commands against an Archil disk via the Archil control-plane HTTP\n * API. Archil is exec-only — each command runs in an Archil-managed container\n * with the configured disk mounted, then returns stdout, stderr, and exit code.\n * There is no sandbox lifecycle to manage; \"create\" resolves a handle to an\n * existing disk id.\n */\n\nimport { defineProvider } from '@computesdk/provider';\nimport { randomUUID } from 'node:crypto';\nimport { posix } from 'node:path';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\nconst ARCHIL_MOUNT_ROOT = '/mnt/archil';\nconst ARCHIL_MAX_EXEC_COMMAND_BYTES = 102_400;\n// Base64 expands the file data and adds line wrapping. Keep the raw chunk\n// comfortably below Archil's roughly 4 MiB response cap.\nconst ARCHIL_MAX_READ_CHUNK_BYTES = 2 * 1024 * 1024;\n\n// Per-region color overrides. Default is \"green\" for any region not listed here.\nconst REGION_COLORS: Record<string, string> = {\n 'gcp-us-central1': 'blue',\n};\n\nfunction regionToBaseUrl(region: string): string {\n const dash = region.indexOf('-');\n if (dash <= 0 || dash === region.length - 1) {\n throw new Error(\n `Invalid Archil region \"${region}\". Expected \"{cloud}-{suffix}\", e.g. \"aws-us-east-1\".`,\n );\n }\n const cloud = region.slice(0, dash);\n const suffix = region.slice(dash + 1);\n const color = REGION_COLORS[region] ?? 'green';\n return `https://control.${color}.${suffix}.${cloud}.prod.archil.com`;\n}\n\nexport interface ArchilConfig {\n /** Archil API key. Falls back to ARCHIL_API_KEY env var. */\n apiKey?: string;\n /** Archil region (e.g. \"aws-us-east-1\"). Falls back to ARCHIL_REGION env var. */\n region?: string;\n /** Override the control-plane base URL (useful for testing). */\n baseUrl?: string;\n}\n\ninterface DiskResponse {\n id: string;\n name: string;\n organization: string;\n status: string;\n provider: string;\n region: string;\n createdAt: string;\n}\n\ntype DiskHandle = Pick<DiskResponse, 'id'>;\n\ninterface ExecTiming {\n totalMs: number;\n queueMs: number;\n executeMs: number;\n}\n\ninterface ExecResponse {\n exitCode: number;\n stdout: string;\n stderr: string;\n timing: ExecTiming;\n}\n\ninterface ResolvedConfig {\n apiKey: string;\n baseUrl: string;\n}\n\ninterface ArchilSandbox {\n disk: DiskHandle | DiskResponse;\n resolved: ResolvedConfig;\n createdAt: Date;\n}\n\ninterface ArchilCreateOptions extends CreateSandboxOptions {\n diskId?: string;\n}\n\nfunction resolveConfig(config: ArchilConfig): ResolvedConfig {\n const apiKey = config.apiKey ?? process.env.ARCHIL_API_KEY;\n const region = config.region ?? process.env.ARCHIL_REGION;\n\n if (!apiKey) {\n throw new Error(\n 'Missing API key for Archil.\\n\\n' +\n 'Pass it: archil({ apiKey: \"...\" })\\n' +\n 'Or set ARCHIL_API_KEY in your environment.',\n );\n }\n\n let baseUrl = config.baseUrl;\n if (!baseUrl) {\n if (!region) {\n throw new Error(\n 'Missing region for Archil.\\n\\n' +\n 'Pass it: archil({ region: \"...\" })\\n' +\n 'Or set ARCHIL_REGION in your environment.\\n' +\n 'Examples: \"aws-us-east-1\", \"aws-eu-west-1\", \"gcp-us-central1\".',\n );\n }\n baseUrl = regionToBaseUrl(region);\n }\n\n return { apiKey, baseUrl };\n}\n\nfunction authHeader(apiKey: string): string {\n return `key-${apiKey.replace(/^key-/, '')}`;\n}\n\nasync function callApi<T>(\n resolved: ResolvedConfig,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n const response = await fetch(`${resolved.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: authHeader(resolved.apiKey),\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n type Envelope = { success?: boolean; data?: T; error?: string };\n let payload: Envelope | null = null;\n try {\n payload = (await response.json()) as Envelope;\n } catch {\n payload = null;\n }\n\n if (!response.ok || !payload || payload.success === false) {\n const message =\n (payload && payload.error) ||\n `Archil API ${method} ${path} failed with status ${response.status}`;\n throw new Error(message);\n }\n\n return payload.data as T;\n}\n\nfunction resolveCreateDiskId(options?: ArchilCreateOptions): string {\n const diskId = options?.diskId;\n\n if (!diskId) {\n throw new Error(\n 'Archil create() requires an existing disk id on the top-level options.\\n\\n' +\n 'Example:\\n' +\n ' provider.sandbox.create({ diskId: \"disk_abc123\" })',\n );\n }\n\n return diskId;\n}\n\nfunction shellEscape(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction mapFilesystemPath(path: string): string {\n const normalized = posix.normalize(path.startsWith('/') ? path : `/${path}`);\n\n if (normalized === '/') {\n return ARCHIL_MOUNT_ROOT;\n }\n\n if (\n normalized === ARCHIL_MOUNT_ROOT ||\n normalized.startsWith(`${ARCHIL_MOUNT_ROOT}/`)\n ) {\n return normalized;\n }\n\n return `${ARCHIL_MOUNT_ROOT}${normalized}`;\n}\n\nfunction withDiskWriteLock(command: string): string {\n const mountRoot = shellEscape(ARCHIL_MOUNT_ROOT);\n return [\n `archil checkout --force --yes ${mountRoot}`,\n `{ ${command}; status=$?; archil checkin ${mountRoot}; checkin_status=$?; ` +\n `if [ $status -ne 0 ]; then exit $status; fi; exit $checkin_status; }`,\n ].join(' && ');\n}\n\nfunction execCommandBytes(command: string): number {\n return Buffer.byteLength(wrapCommand(command), 'utf8');\n}\n\nfunction buildWriteChunkCommand(\n parent: string,\n tempPath: string,\n diskPath: string,\n encodedChunk: string,\n isFirst: boolean,\n isFinal: boolean,\n): string {\n const writeCommand =\n `printf %s ${shellEscape(encodedChunk)} | base64 -d ` +\n `${isFirst ? '>' : '>>'} ${shellEscape(tempPath)}`;\n return [\n ...(isFirst ? [`mkdir -p ${shellEscape(parent)}`] : []),\n writeCommand,\n ...(isFinal\n ? [finalizeStagedFileCommand(tempPath, diskPath)]\n : []),\n ].join(' && ');\n}\n\nfunction finalizeStagedFileCommand(tempPath: string, diskPath: string): string {\n const quotedDestination = shellEscape(diskPath);\n return [\n `if [ -d ${quotedDestination} ]; then`,\n `printf '%s\\\\n' ${shellEscape(`Refusing to overwrite directory ${diskPath}`)} >&2;`,\n 'exit 1;',\n 'fi;',\n `mv ${shellEscape(tempPath)} ${quotedDestination}`,\n ].join(' ');\n}\n\nfunction maxWriteChunkSize(\n parent: string,\n tempPath: string,\n diskPath: string,\n): number {\n let low = 0;\n let high = ARCHIL_MAX_EXEC_COMMAND_BYTES;\n\n while (low < high) {\n const candidate = Math.ceil((low + high) / 2);\n const command = withDiskWriteLock(\n buildWriteChunkCommand(\n parent,\n tempPath,\n diskPath,\n 'A'.repeat(candidate),\n true,\n true,\n ),\n );\n\n if (execCommandBytes(command) <= ARCHIL_MAX_EXEC_COMMAND_BYTES) {\n low = candidate;\n } else {\n high = candidate - 1;\n }\n }\n\n const chunkSize = low - (low % 4);\n if (chunkSize < 4) {\n throw new Error(\n `Archil filesystem path is too long to write within the ${ARCHIL_MAX_EXEC_COMMAND_BYTES}-byte exec command limit.`,\n );\n }\n return chunkSize;\n}\n\nfunction wrapCommand(command: string, options?: RunCommandOptions): string {\n let wrapped = command;\n\n const envEntries = Object.entries(options?.env ?? {});\n if (!envEntries.some(([key]) => key === 'HOME')) {\n envEntries.unshift(['HOME', process.env.HOME || '/tmp']);\n }\n const envPrefix = envEntries\n .map(([k, v]) => `${k}=${shellEscape(String(v))}`)\n .join(' ');\n wrapped = `${envPrefix} ${wrapped}`;\n\n if (options?.cwd) {\n wrapped = `cd ${shellEscape(options.cwd)} && ${wrapped}`;\n }\n\n if (options?.background) {\n wrapped = `nohup sh -c ${shellEscape(wrapped)} > /dev/null 2>&1 &`;\n }\n\n return wrapped;\n}\n\nasync function execOnDisk(sandbox: ArchilSandbox, command: string): Promise<ExecResponse> {\n return callApi<ExecResponse>(\n sandbox.resolved,\n 'POST',\n `/api/disks/${encodeURIComponent(sandbox.disk.id)}/exec`,\n { command },\n );\n}\n\nconst _provider = defineProvider<ArchilSandbox, ArchilConfig>({\n name: 'archil',\n methods: {\n sandbox: {\n create: async (config: ArchilConfig, options?: ArchilCreateOptions) => {\n const resolved = resolveConfig(config);\n const diskId = resolveCreateDiskId(options);\n return {\n sandbox: { disk: { id: diskId }, resolved, createdAt: new Date() },\n sandboxId: diskId,\n };\n },\n\n getById: async (config: ArchilConfig, sandboxId: string) => {\n const resolved = resolveConfig(config);\n try {\n const disk = await callApi<DiskResponse>(\n resolved,\n 'GET',\n `/api/disks/${encodeURIComponent(sandboxId)}`,\n );\n return {\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: ArchilConfig) => {\n const resolved = resolveConfig(config);\n const disks = await callApi<DiskResponse[]>(resolved, 'GET', '/api/disks');\n return disks.map((disk) => ({\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n }));\n },\n\n destroy: async (_config: ArchilConfig, _sandboxId: string) => {\n // No-op: Archil disks have an independent lifecycle.\n },\n\n runCommand: async (\n sandbox: ArchilSandbox,\n command: string,\n options?: RunCommandOptions,\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const result = await execOnDisk(sandbox, wrapCommand(command, options));\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 1,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (sandbox: ArchilSandbox): Promise<SandboxInfo> => {\n const diskInfo = 'status' in sandbox.disk ? sandbox.disk : undefined;\n return {\n id: sandbox.disk.id,\n provider: 'archil',\n status: !diskInfo || diskInfo.status === 'ready' ? 'running' : 'stopped',\n createdAt: diskInfo ? new Date(diskInfo.createdAt) : sandbox.createdAt,\n timeout: 0,\n metadata: diskInfo\n ? {\n name: diskInfo.name,\n organization: diskInfo.organization,\n region: diskInfo.region,\n provider: diskInfo.provider,\n }\n : {},\n };\n },\n\n getUrl: async (\n _sandbox: ArchilSandbox,\n options: { port: number; protocol?: string },\n ): Promise<string> => {\n throw new Error(\n `Archil exec runs each command in a fresh ephemeral container that exits when the command returns, ` +\n `so there is no long-lived process to expose port ${options.port} on. ` +\n `getUrl is not supported.`,\n );\n },\n\n filesystem: {\n readFile: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const sizeResult = await runCommand(\n sandbox,\n `wc -c < ${shellEscape(diskPath)}`,\n );\n if (sizeResult.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${sizeResult.stderr}`);\n }\n\n const sizeText = sizeResult.stdout.trim();\n if (!/^\\d+$/.test(sizeText)) {\n throw new Error(\n `Failed to read ${path}: Archil returned an invalid file size.`,\n );\n }\n\n const size = Number(sizeText);\n if (!Number.isSafeInteger(size)) {\n throw new Error(\n `Failed to read ${path}: file size exceeds JavaScript's safe integer range.`,\n );\n }\n if (size === 0) return '';\n\n const chunks: Buffer[] = [];\n for (\n let offset = 0;\n offset < size;\n offset += ARCHIL_MAX_READ_CHUNK_BYTES\n ) {\n const expectedBytes = Math.min(\n ARCHIL_MAX_READ_CHUNK_BYTES,\n size - offset,\n );\n const result = await runCommand(\n sandbox,\n `dd if=${shellEscape(diskPath)} bs=1 skip=${offset} count=${expectedBytes} 2>/dev/null | base64`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${result.stderr}`);\n }\n\n const encoded = result.stdout.replace(/\\s/g, '');\n if (\n encoded.length === 0 ||\n encoded.length % 4 !== 0 ||\n !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)\n ) {\n throw new Error(\n `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`,\n );\n }\n\n const chunk = Buffer.from(encoded, 'base64');\n if (chunk.length !== expectedBytes) {\n throw new Error(\n `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`,\n );\n }\n chunks.push(chunk);\n }\n\n return Buffer.concat(chunks).toString('utf8');\n },\n\n writeFile: async (sandbox, path, content, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const parent = posix.dirname(diskPath);\n const encoded = Buffer.from(content, 'utf8').toString('base64');\n const tempPath = `${diskPath}.computesdk-write-${randomUUID()}`;\n let started = false;\n\n try {\n if (encoded.length === 0) {\n started = true;\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(\n [\n `mkdir -p ${shellEscape(parent)}`,\n `: > ${shellEscape(tempPath)}`,\n finalizeStagedFileCommand(tempPath, diskPath),\n ].join(' && '),\n ),\n );\n if (result.exitCode !== 0) {\n throw new Error(result.stderr);\n }\n return;\n }\n\n const chunkSize = maxWriteChunkSize(parent, tempPath, diskPath);\n for (let offset = 0; offset < encoded.length; offset += chunkSize) {\n const isFirst = offset === 0;\n const isFinal = offset + chunkSize >= encoded.length;\n started = true;\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(\n buildWriteChunkCommand(\n parent,\n tempPath,\n diskPath,\n encoded.slice(offset, offset + chunkSize),\n isFirst,\n isFinal,\n ),\n ),\n );\n if (result.exitCode !== 0) {\n throw new Error(result.stderr);\n }\n }\n } catch (error) {\n if (started) {\n try {\n await runCommand(\n sandbox,\n withDiskWriteLock(`rm -f ${shellEscape(tempPath)}`),\n );\n } catch {\n // Preserve the original write error if cleanup fails.\n }\n }\n throw new Error(\n `Failed to write ${path}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n },\n\n mkdir: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(`mkdir -p ${shellEscape(diskPath)}`),\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n // Tab-separated: type<TAB>size<TAB>mtime-iso<TAB>name. Robust to spaces in names.\n const result = await runCommand(\n sandbox,\n `find ${shellEscape(diskPath)} -mindepth 1 -maxdepth 1 -printf '%y\\\\t%s\\\\t%T@\\\\t%f\\\\n'`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n const entries: FileEntry[] = [];\n for (const line of result.stdout.split('\\n')) {\n if (!line) continue;\n const [typeChar, sizeStr, mtimeStr, ...nameParts] = line.split('\\t');\n const name = nameParts.join('\\t');\n entries.push({\n name,\n type: typeChar === 'd' ? 'directory' : 'file',\n size: parseInt(sizeStr, 10) || 0,\n modified: new Date(parseFloat(mtimeStr) * 1000),\n });\n }\n return entries;\n },\n\n exists: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const result = await runCommand(sandbox, `test -e ${shellEscape(diskPath)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n if (diskPath === ARCHIL_MOUNT_ROOT) {\n throw new Error('Refusing to remove the Archil disk mount root.');\n }\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(`rm -rf ${shellEscape(diskPath)}`),\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n getInstance: (sandbox: ArchilSandbox): ArchilSandbox => sandbox,\n },\n },\n});\n\nexport const archil = (config: ArchilConfig = {}) => _provider(config);\n\nexport type { ArchilSandbox };\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,10 @@
1
1
  // src/index.ts
2
2
  import { defineProvider } from "@computesdk/provider";
3
+ import { randomUUID } from "crypto";
4
+ import { posix } from "path";
5
+ var ARCHIL_MOUNT_ROOT = "/mnt/archil";
6
+ var ARCHIL_MAX_EXEC_COMMAND_BYTES = 102400;
7
+ var ARCHIL_MAX_READ_CHUNK_BYTES = 2 * 1024 * 1024;
3
8
  var REGION_COLORS = {
4
9
  "gcp-us-central1": "blue"
5
10
  };
@@ -70,6 +75,73 @@ function resolveCreateDiskId(options) {
70
75
  function shellEscape(value) {
71
76
  return `'${value.replace(/'/g, `'\\''`)}'`;
72
77
  }
78
+ function mapFilesystemPath(path) {
79
+ const normalized = posix.normalize(path.startsWith("/") ? path : `/${path}`);
80
+ if (normalized === "/") {
81
+ return ARCHIL_MOUNT_ROOT;
82
+ }
83
+ if (normalized === ARCHIL_MOUNT_ROOT || normalized.startsWith(`${ARCHIL_MOUNT_ROOT}/`)) {
84
+ return normalized;
85
+ }
86
+ return `${ARCHIL_MOUNT_ROOT}${normalized}`;
87
+ }
88
+ function withDiskWriteLock(command) {
89
+ const mountRoot = shellEscape(ARCHIL_MOUNT_ROOT);
90
+ return [
91
+ `archil checkout --force --yes ${mountRoot}`,
92
+ `{ ${command}; status=$?; archil checkin ${mountRoot}; checkin_status=$?; if [ $status -ne 0 ]; then exit $status; fi; exit $checkin_status; }`
93
+ ].join(" && ");
94
+ }
95
+ function execCommandBytes(command) {
96
+ return Buffer.byteLength(wrapCommand(command), "utf8");
97
+ }
98
+ function buildWriteChunkCommand(parent, tempPath, diskPath, encodedChunk, isFirst, isFinal) {
99
+ const writeCommand = `printf %s ${shellEscape(encodedChunk)} | base64 -d ${isFirst ? ">" : ">>"} ${shellEscape(tempPath)}`;
100
+ return [
101
+ ...isFirst ? [`mkdir -p ${shellEscape(parent)}`] : [],
102
+ writeCommand,
103
+ ...isFinal ? [finalizeStagedFileCommand(tempPath, diskPath)] : []
104
+ ].join(" && ");
105
+ }
106
+ function finalizeStagedFileCommand(tempPath, diskPath) {
107
+ const quotedDestination = shellEscape(diskPath);
108
+ return [
109
+ `if [ -d ${quotedDestination} ]; then`,
110
+ `printf '%s\\n' ${shellEscape(`Refusing to overwrite directory ${diskPath}`)} >&2;`,
111
+ "exit 1;",
112
+ "fi;",
113
+ `mv ${shellEscape(tempPath)} ${quotedDestination}`
114
+ ].join(" ");
115
+ }
116
+ function maxWriteChunkSize(parent, tempPath, diskPath) {
117
+ let low = 0;
118
+ let high = ARCHIL_MAX_EXEC_COMMAND_BYTES;
119
+ while (low < high) {
120
+ const candidate = Math.ceil((low + high) / 2);
121
+ const command = withDiskWriteLock(
122
+ buildWriteChunkCommand(
123
+ parent,
124
+ tempPath,
125
+ diskPath,
126
+ "A".repeat(candidate),
127
+ true,
128
+ true
129
+ )
130
+ );
131
+ if (execCommandBytes(command) <= ARCHIL_MAX_EXEC_COMMAND_BYTES) {
132
+ low = candidate;
133
+ } else {
134
+ high = candidate - 1;
135
+ }
136
+ }
137
+ const chunkSize = low - low % 4;
138
+ if (chunkSize < 4) {
139
+ throw new Error(
140
+ `Archil filesystem path is too long to write within the ${ARCHIL_MAX_EXEC_COMMAND_BYTES}-byte exec command limit.`
141
+ );
142
+ }
143
+ return chunkSize;
144
+ }
73
145
  function wrapCommand(command, options) {
74
146
  let wrapped = command;
75
147
  const envEntries = Object.entries(options?.env ?? {});
@@ -174,36 +246,132 @@ var _provider = defineProvider({
174
246
  },
175
247
  filesystem: {
176
248
  readFile: async (sandbox, path, runCommand) => {
177
- const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);
178
- if (result.exitCode !== 0) {
179
- throw new Error(`Failed to read ${path}: ${result.stderr}`);
249
+ const diskPath = mapFilesystemPath(path);
250
+ const sizeResult = await runCommand(
251
+ sandbox,
252
+ `wc -c < ${shellEscape(diskPath)}`
253
+ );
254
+ if (sizeResult.exitCode !== 0) {
255
+ throw new Error(`Failed to read ${path}: ${sizeResult.stderr}`);
256
+ }
257
+ const sizeText = sizeResult.stdout.trim();
258
+ if (!/^\d+$/.test(sizeText)) {
259
+ throw new Error(
260
+ `Failed to read ${path}: Archil returned an invalid file size.`
261
+ );
262
+ }
263
+ const size = Number(sizeText);
264
+ if (!Number.isSafeInteger(size)) {
265
+ throw new Error(
266
+ `Failed to read ${path}: file size exceeds JavaScript's safe integer range.`
267
+ );
268
+ }
269
+ if (size === 0) return "";
270
+ const chunks = [];
271
+ for (let offset = 0; offset < size; offset += ARCHIL_MAX_READ_CHUNK_BYTES) {
272
+ const expectedBytes = Math.min(
273
+ ARCHIL_MAX_READ_CHUNK_BYTES,
274
+ size - offset
275
+ );
276
+ const result = await runCommand(
277
+ sandbox,
278
+ `dd if=${shellEscape(diskPath)} bs=1 skip=${offset} count=${expectedBytes} 2>/dev/null | base64`
279
+ );
280
+ if (result.exitCode !== 0) {
281
+ throw new Error(`Failed to read ${path}: ${result.stderr}`);
282
+ }
283
+ const encoded = result.stdout.replace(/\s/g, "");
284
+ if (encoded.length === 0 || encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {
285
+ throw new Error(
286
+ `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`
287
+ );
288
+ }
289
+ const chunk = Buffer.from(encoded, "base64");
290
+ if (chunk.length !== expectedBytes) {
291
+ throw new Error(
292
+ `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`
293
+ );
294
+ }
295
+ chunks.push(chunk);
180
296
  }
181
- return result.stdout;
297
+ return Buffer.concat(chunks).toString("utf8");
182
298
  },
183
299
  writeFile: async (sandbox, path, content, runCommand) => {
184
- const parent = path.substring(0, path.lastIndexOf("/"));
185
- if (parent) {
186
- await runCommand(sandbox, `mkdir -p ${shellEscape(parent)}`);
187
- }
300
+ const diskPath = mapFilesystemPath(path);
301
+ const parent = posix.dirname(diskPath);
188
302
  const encoded = Buffer.from(content, "utf8").toString("base64");
189
- const result = await runCommand(
190
- sandbox,
191
- `printf %s ${shellEscape(encoded)} | base64 -d > ${shellEscape(path)}`
192
- );
193
- if (result.exitCode !== 0) {
194
- throw new Error(`Failed to write ${path}: ${result.stderr}`);
303
+ const tempPath = `${diskPath}.computesdk-write-${randomUUID()}`;
304
+ let started = false;
305
+ try {
306
+ if (encoded.length === 0) {
307
+ started = true;
308
+ const result = await runCommand(
309
+ sandbox,
310
+ withDiskWriteLock(
311
+ [
312
+ `mkdir -p ${shellEscape(parent)}`,
313
+ `: > ${shellEscape(tempPath)}`,
314
+ finalizeStagedFileCommand(tempPath, diskPath)
315
+ ].join(" && ")
316
+ )
317
+ );
318
+ if (result.exitCode !== 0) {
319
+ throw new Error(result.stderr);
320
+ }
321
+ return;
322
+ }
323
+ const chunkSize = maxWriteChunkSize(parent, tempPath, diskPath);
324
+ for (let offset = 0; offset < encoded.length; offset += chunkSize) {
325
+ const isFirst = offset === 0;
326
+ const isFinal = offset + chunkSize >= encoded.length;
327
+ started = true;
328
+ const result = await runCommand(
329
+ sandbox,
330
+ withDiskWriteLock(
331
+ buildWriteChunkCommand(
332
+ parent,
333
+ tempPath,
334
+ diskPath,
335
+ encoded.slice(offset, offset + chunkSize),
336
+ isFirst,
337
+ isFinal
338
+ )
339
+ )
340
+ );
341
+ if (result.exitCode !== 0) {
342
+ throw new Error(result.stderr);
343
+ }
344
+ }
345
+ } catch (error) {
346
+ if (started) {
347
+ try {
348
+ await runCommand(
349
+ sandbox,
350
+ withDiskWriteLock(`rm -f ${shellEscape(tempPath)}`)
351
+ );
352
+ } catch {
353
+ }
354
+ }
355
+ throw new Error(
356
+ `Failed to write ${path}: ${error instanceof Error ? error.message : String(error)}`
357
+ );
195
358
  }
196
359
  },
197
360
  mkdir: async (sandbox, path, runCommand) => {
198
- const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);
361
+ const diskPath = mapFilesystemPath(path);
362
+ const result = await runCommand(
363
+ sandbox,
364
+ withDiskWriteLock(`mkdir -p ${shellEscape(diskPath)}`)
365
+ );
199
366
  if (result.exitCode !== 0) {
200
367
  throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
201
368
  }
202
369
  },
203
370
  readdir: async (sandbox, path, runCommand) => {
371
+ const diskPath = mapFilesystemPath(path);
204
372
  const result = await runCommand(
205
373
  sandbox,
206
- `find ${shellEscape(path)} -mindepth 1 -maxdepth 1 -printf '%y\\t%s\\t%T@\\t%f\\n'`
374
+ `find ${shellEscape(diskPath)} -mindepth 1 -maxdepth 1 -printf '%y\\t%s\\t%T@\\t%f\\n'`
207
375
  );
208
376
  if (result.exitCode !== 0) {
209
377
  throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
@@ -223,11 +391,19 @@ var _provider = defineProvider({
223
391
  return entries;
224
392
  },
225
393
  exists: async (sandbox, path, runCommand) => {
226
- const result = await runCommand(sandbox, `test -e ${shellEscape(path)}`);
394
+ const diskPath = mapFilesystemPath(path);
395
+ const result = await runCommand(sandbox, `test -e ${shellEscape(diskPath)}`);
227
396
  return result.exitCode === 0;
228
397
  },
229
398
  remove: async (sandbox, path, runCommand) => {
230
- const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);
399
+ const diskPath = mapFilesystemPath(path);
400
+ if (diskPath === ARCHIL_MOUNT_ROOT) {
401
+ throw new Error("Refusing to remove the Archil disk mount root.");
402
+ }
403
+ const result = await runCommand(
404
+ sandbox,
405
+ withDiskWriteLock(`rm -rf ${shellEscape(diskPath)}`)
406
+ );
231
407
  if (result.exitCode !== 0) {
232
408
  throw new Error(`Failed to remove ${path}: ${result.stderr}`);
233
409
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Archil Provider\n *\n * Executes commands against an Archil disk via the Archil control-plane HTTP\n * API. Archil is exec-only — each command runs in an Archil-managed container\n * with the configured disk mounted, then returns stdout, stderr, and exit code.\n * There is no sandbox lifecycle to manage; \"create\" resolves a handle to an\n * existing disk id.\n */\n\nimport { defineProvider } from '@computesdk/provider';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n// Per-region color overrides. Default is \"green\" for any region not listed here.\nconst REGION_COLORS: Record<string, string> = {\n 'gcp-us-central1': 'blue',\n};\n\nfunction regionToBaseUrl(region: string): string {\n const dash = region.indexOf('-');\n if (dash <= 0 || dash === region.length - 1) {\n throw new Error(\n `Invalid Archil region \"${region}\". Expected \"{cloud}-{suffix}\", e.g. \"aws-us-east-1\".`,\n );\n }\n const cloud = region.slice(0, dash);\n const suffix = region.slice(dash + 1);\n const color = REGION_COLORS[region] ?? 'green';\n return `https://control.${color}.${suffix}.${cloud}.prod.archil.com`;\n}\n\nexport interface ArchilConfig {\n /** Archil API key. Falls back to ARCHIL_API_KEY env var. */\n apiKey?: string;\n /** Archil region (e.g. \"aws-us-east-1\"). Falls back to ARCHIL_REGION env var. */\n region?: string;\n /** Override the control-plane base URL (useful for testing). */\n baseUrl?: string;\n}\n\ninterface DiskResponse {\n id: string;\n name: string;\n organization: string;\n status: string;\n provider: string;\n region: string;\n createdAt: string;\n}\n\ntype DiskHandle = Pick<DiskResponse, 'id'>;\n\ninterface ExecTiming {\n totalMs: number;\n queueMs: number;\n executeMs: number;\n}\n\ninterface ExecResponse {\n exitCode: number;\n stdout: string;\n stderr: string;\n timing: ExecTiming;\n}\n\ninterface ResolvedConfig {\n apiKey: string;\n baseUrl: string;\n}\n\ninterface ArchilSandbox {\n disk: DiskHandle | DiskResponse;\n resolved: ResolvedConfig;\n createdAt: Date;\n}\n\ninterface ArchilCreateOptions extends CreateSandboxOptions {\n diskId?: string;\n}\n\nfunction resolveConfig(config: ArchilConfig): ResolvedConfig {\n const apiKey = config.apiKey ?? process.env.ARCHIL_API_KEY;\n const region = config.region ?? process.env.ARCHIL_REGION;\n\n if (!apiKey) {\n throw new Error(\n 'Missing API key for Archil.\\n\\n' +\n 'Pass it: archil({ apiKey: \"...\" })\\n' +\n 'Or set ARCHIL_API_KEY in your environment.',\n );\n }\n\n let baseUrl = config.baseUrl;\n if (!baseUrl) {\n if (!region) {\n throw new Error(\n 'Missing region for Archil.\\n\\n' +\n 'Pass it: archil({ region: \"...\" })\\n' +\n 'Or set ARCHIL_REGION in your environment.\\n' +\n 'Examples: \"aws-us-east-1\", \"aws-eu-west-1\", \"gcp-us-central1\".',\n );\n }\n baseUrl = regionToBaseUrl(region);\n }\n\n return { apiKey, baseUrl };\n}\n\nfunction authHeader(apiKey: string): string {\n return `key-${apiKey.replace(/^key-/, '')}`;\n}\n\nasync function callApi<T>(\n resolved: ResolvedConfig,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n const response = await fetch(`${resolved.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: authHeader(resolved.apiKey),\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n type Envelope = { success?: boolean; data?: T; error?: string };\n let payload: Envelope | null = null;\n try {\n payload = (await response.json()) as Envelope;\n } catch {\n payload = null;\n }\n\n if (!response.ok || !payload || payload.success === false) {\n const message =\n (payload && payload.error) ||\n `Archil API ${method} ${path} failed with status ${response.status}`;\n throw new Error(message);\n }\n\n return payload.data as T;\n}\n\nfunction resolveCreateDiskId(options?: ArchilCreateOptions): string {\n const diskId = options?.diskId;\n\n if (!diskId) {\n throw new Error(\n 'Archil create() requires an existing disk id on the top-level options.\\n\\n' +\n 'Example:\\n' +\n ' provider.sandbox.create({ diskId: \"disk_abc123\" })',\n );\n }\n\n return diskId;\n}\n\nfunction shellEscape(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction wrapCommand(command: string, options?: RunCommandOptions): string {\n let wrapped = command;\n\n const envEntries = Object.entries(options?.env ?? {});\n if (!envEntries.some(([key]) => key === 'HOME')) {\n envEntries.unshift(['HOME', process.env.HOME || '/tmp']);\n }\n const envPrefix = envEntries\n .map(([k, v]) => `${k}=${shellEscape(String(v))}`)\n .join(' ');\n wrapped = `${envPrefix} ${wrapped}`;\n\n if (options?.cwd) {\n wrapped = `cd ${shellEscape(options.cwd)} && ${wrapped}`;\n }\n\n if (options?.background) {\n wrapped = `nohup sh -c ${shellEscape(wrapped)} > /dev/null 2>&1 &`;\n }\n\n return wrapped;\n}\n\nasync function execOnDisk(sandbox: ArchilSandbox, command: string): Promise<ExecResponse> {\n return callApi<ExecResponse>(\n sandbox.resolved,\n 'POST',\n `/api/disks/${encodeURIComponent(sandbox.disk.id)}/exec`,\n { command },\n );\n}\n\nconst _provider = defineProvider<ArchilSandbox, ArchilConfig>({\n name: 'archil',\n methods: {\n sandbox: {\n create: async (config: ArchilConfig, options?: ArchilCreateOptions) => {\n const resolved = resolveConfig(config);\n const diskId = resolveCreateDiskId(options);\n return {\n sandbox: { disk: { id: diskId }, resolved, createdAt: new Date() },\n sandboxId: diskId,\n };\n },\n\n getById: async (config: ArchilConfig, sandboxId: string) => {\n const resolved = resolveConfig(config);\n try {\n const disk = await callApi<DiskResponse>(\n resolved,\n 'GET',\n `/api/disks/${encodeURIComponent(sandboxId)}`,\n );\n return {\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: ArchilConfig) => {\n const resolved = resolveConfig(config);\n const disks = await callApi<DiskResponse[]>(resolved, 'GET', '/api/disks');\n return disks.map((disk) => ({\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n }));\n },\n\n destroy: async (_config: ArchilConfig, _sandboxId: string) => {\n // No-op: Archil disks have an independent lifecycle.\n },\n\n runCommand: async (\n sandbox: ArchilSandbox,\n command: string,\n options?: RunCommandOptions,\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const result = await execOnDisk(sandbox, wrapCommand(command, options));\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 1,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (sandbox: ArchilSandbox): Promise<SandboxInfo> => {\n const diskInfo = 'status' in sandbox.disk ? sandbox.disk : undefined;\n return {\n id: sandbox.disk.id,\n provider: 'archil',\n status: !diskInfo || diskInfo.status === 'ready' ? 'running' : 'stopped',\n createdAt: diskInfo ? new Date(diskInfo.createdAt) : sandbox.createdAt,\n timeout: 0,\n metadata: diskInfo\n ? {\n name: diskInfo.name,\n organization: diskInfo.organization,\n region: diskInfo.region,\n provider: diskInfo.provider,\n }\n : {},\n };\n },\n\n getUrl: async (\n _sandbox: ArchilSandbox,\n options: { port: number; protocol?: string },\n ): Promise<string> => {\n throw new Error(\n `Archil exec runs each command in a fresh ephemeral container that exits when the command returns, ` +\n `so there is no long-lived process to expose port ${options.port} on. ` +\n `getUrl is not supported.`,\n );\n },\n\n filesystem: {\n readFile: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${result.stderr}`);\n }\n return result.stdout;\n },\n\n writeFile: async (sandbox, path, content, runCommand) => {\n const parent = path.substring(0, path.lastIndexOf('/'));\n if (parent) {\n await runCommand(sandbox, `mkdir -p ${shellEscape(parent)}`);\n }\n // base64-pipe to avoid heredoc/quoting hazards on arbitrary content.\n const encoded = Buffer.from(content, 'utf8').toString('base64');\n const result = await runCommand(\n sandbox,\n `printf %s ${shellEscape(encoded)} | base64 -d > ${shellEscape(path)}`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to write ${path}: ${result.stderr}`);\n }\n },\n\n mkdir: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox, path, runCommand) => {\n // Tab-separated: type<TAB>size<TAB>mtime-iso<TAB>name. Robust to spaces in names.\n const result = await runCommand(\n sandbox,\n `find ${shellEscape(path)} -mindepth 1 -maxdepth 1 -printf '%y\\\\t%s\\\\t%T@\\\\t%f\\\\n'`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n const entries: FileEntry[] = [];\n for (const line of result.stdout.split('\\n')) {\n if (!line) continue;\n const [typeChar, sizeStr, mtimeStr, ...nameParts] = line.split('\\t');\n const name = nameParts.join('\\t');\n entries.push({\n name,\n type: typeChar === 'd' ? 'directory' : 'file',\n size: parseInt(sizeStr, 10) || 0,\n modified: new Date(parseFloat(mtimeStr) * 1000),\n });\n }\n return entries;\n },\n\n exists: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `test -e ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox, path, runCommand) => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n getInstance: (sandbox: ArchilSandbox): ArchilSandbox => sandbox,\n },\n },\n});\n\nexport const archil = (config: ArchilConfig = {}) => _provider(config);\n\nexport type { ArchilSandbox };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Archil Provider\n *\n * Executes commands against an Archil disk via the Archil control-plane HTTP\n * API. Archil is exec-only — each command runs in an Archil-managed container\n * with the configured disk mounted, then returns stdout, stderr, and exit code.\n * There is no sandbox lifecycle to manage; \"create\" resolves a handle to an\n * existing disk id.\n */\n\nimport { defineProvider } from '@computesdk/provider';\nimport { randomUUID } from 'node:crypto';\nimport { posix } from 'node:path';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\nconst ARCHIL_MOUNT_ROOT = '/mnt/archil';\nconst ARCHIL_MAX_EXEC_COMMAND_BYTES = 102_400;\n// Base64 expands the file data and adds line wrapping. Keep the raw chunk\n// comfortably below Archil's roughly 4 MiB response cap.\nconst ARCHIL_MAX_READ_CHUNK_BYTES = 2 * 1024 * 1024;\n\n// Per-region color overrides. Default is \"green\" for any region not listed here.\nconst REGION_COLORS: Record<string, string> = {\n 'gcp-us-central1': 'blue',\n};\n\nfunction regionToBaseUrl(region: string): string {\n const dash = region.indexOf('-');\n if (dash <= 0 || dash === region.length - 1) {\n throw new Error(\n `Invalid Archil region \"${region}\". Expected \"{cloud}-{suffix}\", e.g. \"aws-us-east-1\".`,\n );\n }\n const cloud = region.slice(0, dash);\n const suffix = region.slice(dash + 1);\n const color = REGION_COLORS[region] ?? 'green';\n return `https://control.${color}.${suffix}.${cloud}.prod.archil.com`;\n}\n\nexport interface ArchilConfig {\n /** Archil API key. Falls back to ARCHIL_API_KEY env var. */\n apiKey?: string;\n /** Archil region (e.g. \"aws-us-east-1\"). Falls back to ARCHIL_REGION env var. */\n region?: string;\n /** Override the control-plane base URL (useful for testing). */\n baseUrl?: string;\n}\n\ninterface DiskResponse {\n id: string;\n name: string;\n organization: string;\n status: string;\n provider: string;\n region: string;\n createdAt: string;\n}\n\ntype DiskHandle = Pick<DiskResponse, 'id'>;\n\ninterface ExecTiming {\n totalMs: number;\n queueMs: number;\n executeMs: number;\n}\n\ninterface ExecResponse {\n exitCode: number;\n stdout: string;\n stderr: string;\n timing: ExecTiming;\n}\n\ninterface ResolvedConfig {\n apiKey: string;\n baseUrl: string;\n}\n\ninterface ArchilSandbox {\n disk: DiskHandle | DiskResponse;\n resolved: ResolvedConfig;\n createdAt: Date;\n}\n\ninterface ArchilCreateOptions extends CreateSandboxOptions {\n diskId?: string;\n}\n\nfunction resolveConfig(config: ArchilConfig): ResolvedConfig {\n const apiKey = config.apiKey ?? process.env.ARCHIL_API_KEY;\n const region = config.region ?? process.env.ARCHIL_REGION;\n\n if (!apiKey) {\n throw new Error(\n 'Missing API key for Archil.\\n\\n' +\n 'Pass it: archil({ apiKey: \"...\" })\\n' +\n 'Or set ARCHIL_API_KEY in your environment.',\n );\n }\n\n let baseUrl = config.baseUrl;\n if (!baseUrl) {\n if (!region) {\n throw new Error(\n 'Missing region for Archil.\\n\\n' +\n 'Pass it: archil({ region: \"...\" })\\n' +\n 'Or set ARCHIL_REGION in your environment.\\n' +\n 'Examples: \"aws-us-east-1\", \"aws-eu-west-1\", \"gcp-us-central1\".',\n );\n }\n baseUrl = regionToBaseUrl(region);\n }\n\n return { apiKey, baseUrl };\n}\n\nfunction authHeader(apiKey: string): string {\n return `key-${apiKey.replace(/^key-/, '')}`;\n}\n\nasync function callApi<T>(\n resolved: ResolvedConfig,\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n): Promise<T> {\n const response = await fetch(`${resolved.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: authHeader(resolved.apiKey),\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n type Envelope = { success?: boolean; data?: T; error?: string };\n let payload: Envelope | null = null;\n try {\n payload = (await response.json()) as Envelope;\n } catch {\n payload = null;\n }\n\n if (!response.ok || !payload || payload.success === false) {\n const message =\n (payload && payload.error) ||\n `Archil API ${method} ${path} failed with status ${response.status}`;\n throw new Error(message);\n }\n\n return payload.data as T;\n}\n\nfunction resolveCreateDiskId(options?: ArchilCreateOptions): string {\n const diskId = options?.diskId;\n\n if (!diskId) {\n throw new Error(\n 'Archil create() requires an existing disk id on the top-level options.\\n\\n' +\n 'Example:\\n' +\n ' provider.sandbox.create({ diskId: \"disk_abc123\" })',\n );\n }\n\n return diskId;\n}\n\nfunction shellEscape(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction mapFilesystemPath(path: string): string {\n const normalized = posix.normalize(path.startsWith('/') ? path : `/${path}`);\n\n if (normalized === '/') {\n return ARCHIL_MOUNT_ROOT;\n }\n\n if (\n normalized === ARCHIL_MOUNT_ROOT ||\n normalized.startsWith(`${ARCHIL_MOUNT_ROOT}/`)\n ) {\n return normalized;\n }\n\n return `${ARCHIL_MOUNT_ROOT}${normalized}`;\n}\n\nfunction withDiskWriteLock(command: string): string {\n const mountRoot = shellEscape(ARCHIL_MOUNT_ROOT);\n return [\n `archil checkout --force --yes ${mountRoot}`,\n `{ ${command}; status=$?; archil checkin ${mountRoot}; checkin_status=$?; ` +\n `if [ $status -ne 0 ]; then exit $status; fi; exit $checkin_status; }`,\n ].join(' && ');\n}\n\nfunction execCommandBytes(command: string): number {\n return Buffer.byteLength(wrapCommand(command), 'utf8');\n}\n\nfunction buildWriteChunkCommand(\n parent: string,\n tempPath: string,\n diskPath: string,\n encodedChunk: string,\n isFirst: boolean,\n isFinal: boolean,\n): string {\n const writeCommand =\n `printf %s ${shellEscape(encodedChunk)} | base64 -d ` +\n `${isFirst ? '>' : '>>'} ${shellEscape(tempPath)}`;\n return [\n ...(isFirst ? [`mkdir -p ${shellEscape(parent)}`] : []),\n writeCommand,\n ...(isFinal\n ? [finalizeStagedFileCommand(tempPath, diskPath)]\n : []),\n ].join(' && ');\n}\n\nfunction finalizeStagedFileCommand(tempPath: string, diskPath: string): string {\n const quotedDestination = shellEscape(diskPath);\n return [\n `if [ -d ${quotedDestination} ]; then`,\n `printf '%s\\\\n' ${shellEscape(`Refusing to overwrite directory ${diskPath}`)} >&2;`,\n 'exit 1;',\n 'fi;',\n `mv ${shellEscape(tempPath)} ${quotedDestination}`,\n ].join(' ');\n}\n\nfunction maxWriteChunkSize(\n parent: string,\n tempPath: string,\n diskPath: string,\n): number {\n let low = 0;\n let high = ARCHIL_MAX_EXEC_COMMAND_BYTES;\n\n while (low < high) {\n const candidate = Math.ceil((low + high) / 2);\n const command = withDiskWriteLock(\n buildWriteChunkCommand(\n parent,\n tempPath,\n diskPath,\n 'A'.repeat(candidate),\n true,\n true,\n ),\n );\n\n if (execCommandBytes(command) <= ARCHIL_MAX_EXEC_COMMAND_BYTES) {\n low = candidate;\n } else {\n high = candidate - 1;\n }\n }\n\n const chunkSize = low - (low % 4);\n if (chunkSize < 4) {\n throw new Error(\n `Archil filesystem path is too long to write within the ${ARCHIL_MAX_EXEC_COMMAND_BYTES}-byte exec command limit.`,\n );\n }\n return chunkSize;\n}\n\nfunction wrapCommand(command: string, options?: RunCommandOptions): string {\n let wrapped = command;\n\n const envEntries = Object.entries(options?.env ?? {});\n if (!envEntries.some(([key]) => key === 'HOME')) {\n envEntries.unshift(['HOME', process.env.HOME || '/tmp']);\n }\n const envPrefix = envEntries\n .map(([k, v]) => `${k}=${shellEscape(String(v))}`)\n .join(' ');\n wrapped = `${envPrefix} ${wrapped}`;\n\n if (options?.cwd) {\n wrapped = `cd ${shellEscape(options.cwd)} && ${wrapped}`;\n }\n\n if (options?.background) {\n wrapped = `nohup sh -c ${shellEscape(wrapped)} > /dev/null 2>&1 &`;\n }\n\n return wrapped;\n}\n\nasync function execOnDisk(sandbox: ArchilSandbox, command: string): Promise<ExecResponse> {\n return callApi<ExecResponse>(\n sandbox.resolved,\n 'POST',\n `/api/disks/${encodeURIComponent(sandbox.disk.id)}/exec`,\n { command },\n );\n}\n\nconst _provider = defineProvider<ArchilSandbox, ArchilConfig>({\n name: 'archil',\n methods: {\n sandbox: {\n create: async (config: ArchilConfig, options?: ArchilCreateOptions) => {\n const resolved = resolveConfig(config);\n const diskId = resolveCreateDiskId(options);\n return {\n sandbox: { disk: { id: diskId }, resolved, createdAt: new Date() },\n sandboxId: diskId,\n };\n },\n\n getById: async (config: ArchilConfig, sandboxId: string) => {\n const resolved = resolveConfig(config);\n try {\n const disk = await callApi<DiskResponse>(\n resolved,\n 'GET',\n `/api/disks/${encodeURIComponent(sandboxId)}`,\n );\n return {\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: ArchilConfig) => {\n const resolved = resolveConfig(config);\n const disks = await callApi<DiskResponse[]>(resolved, 'GET', '/api/disks');\n return disks.map((disk) => ({\n sandbox: { disk, resolved, createdAt: new Date() },\n sandboxId: disk.id,\n }));\n },\n\n destroy: async (_config: ArchilConfig, _sandboxId: string) => {\n // No-op: Archil disks have an independent lifecycle.\n },\n\n runCommand: async (\n sandbox: ArchilSandbox,\n command: string,\n options?: RunCommandOptions,\n ): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const result = await execOnDisk(sandbox, wrapCommand(command, options));\n return {\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 1,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n getInfo: async (sandbox: ArchilSandbox): Promise<SandboxInfo> => {\n const diskInfo = 'status' in sandbox.disk ? sandbox.disk : undefined;\n return {\n id: sandbox.disk.id,\n provider: 'archil',\n status: !diskInfo || diskInfo.status === 'ready' ? 'running' : 'stopped',\n createdAt: diskInfo ? new Date(diskInfo.createdAt) : sandbox.createdAt,\n timeout: 0,\n metadata: diskInfo\n ? {\n name: diskInfo.name,\n organization: diskInfo.organization,\n region: diskInfo.region,\n provider: diskInfo.provider,\n }\n : {},\n };\n },\n\n getUrl: async (\n _sandbox: ArchilSandbox,\n options: { port: number; protocol?: string },\n ): Promise<string> => {\n throw new Error(\n `Archil exec runs each command in a fresh ephemeral container that exits when the command returns, ` +\n `so there is no long-lived process to expose port ${options.port} on. ` +\n `getUrl is not supported.`,\n );\n },\n\n filesystem: {\n readFile: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const sizeResult = await runCommand(\n sandbox,\n `wc -c < ${shellEscape(diskPath)}`,\n );\n if (sizeResult.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${sizeResult.stderr}`);\n }\n\n const sizeText = sizeResult.stdout.trim();\n if (!/^\\d+$/.test(sizeText)) {\n throw new Error(\n `Failed to read ${path}: Archil returned an invalid file size.`,\n );\n }\n\n const size = Number(sizeText);\n if (!Number.isSafeInteger(size)) {\n throw new Error(\n `Failed to read ${path}: file size exceeds JavaScript's safe integer range.`,\n );\n }\n if (size === 0) return '';\n\n const chunks: Buffer[] = [];\n for (\n let offset = 0;\n offset < size;\n offset += ARCHIL_MAX_READ_CHUNK_BYTES\n ) {\n const expectedBytes = Math.min(\n ARCHIL_MAX_READ_CHUNK_BYTES,\n size - offset,\n );\n const result = await runCommand(\n sandbox,\n `dd if=${shellEscape(diskPath)} bs=1 skip=${offset} count=${expectedBytes} 2>/dev/null | base64`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read ${path}: ${result.stderr}`);\n }\n\n const encoded = result.stdout.replace(/\\s/g, '');\n if (\n encoded.length === 0 ||\n encoded.length % 4 !== 0 ||\n !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)\n ) {\n throw new Error(\n `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`,\n );\n }\n\n const chunk = Buffer.from(encoded, 'base64');\n if (chunk.length !== expectedBytes) {\n throw new Error(\n `Failed to read ${path}: Archil returned an incomplete file chunk at byte ${offset}.`,\n );\n }\n chunks.push(chunk);\n }\n\n return Buffer.concat(chunks).toString('utf8');\n },\n\n writeFile: async (sandbox, path, content, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const parent = posix.dirname(diskPath);\n const encoded = Buffer.from(content, 'utf8').toString('base64');\n const tempPath = `${diskPath}.computesdk-write-${randomUUID()}`;\n let started = false;\n\n try {\n if (encoded.length === 0) {\n started = true;\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(\n [\n `mkdir -p ${shellEscape(parent)}`,\n `: > ${shellEscape(tempPath)}`,\n finalizeStagedFileCommand(tempPath, diskPath),\n ].join(' && '),\n ),\n );\n if (result.exitCode !== 0) {\n throw new Error(result.stderr);\n }\n return;\n }\n\n const chunkSize = maxWriteChunkSize(parent, tempPath, diskPath);\n for (let offset = 0; offset < encoded.length; offset += chunkSize) {\n const isFirst = offset === 0;\n const isFinal = offset + chunkSize >= encoded.length;\n started = true;\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(\n buildWriteChunkCommand(\n parent,\n tempPath,\n diskPath,\n encoded.slice(offset, offset + chunkSize),\n isFirst,\n isFinal,\n ),\n ),\n );\n if (result.exitCode !== 0) {\n throw new Error(result.stderr);\n }\n }\n } catch (error) {\n if (started) {\n try {\n await runCommand(\n sandbox,\n withDiskWriteLock(`rm -f ${shellEscape(tempPath)}`),\n );\n } catch {\n // Preserve the original write error if cleanup fails.\n }\n }\n throw new Error(\n `Failed to write ${path}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n },\n\n mkdir: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(`mkdir -p ${shellEscape(diskPath)}`),\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n // Tab-separated: type<TAB>size<TAB>mtime-iso<TAB>name. Robust to spaces in names.\n const result = await runCommand(\n sandbox,\n `find ${shellEscape(diskPath)} -mindepth 1 -maxdepth 1 -printf '%y\\\\t%s\\\\t%T@\\\\t%f\\\\n'`,\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n const entries: FileEntry[] = [];\n for (const line of result.stdout.split('\\n')) {\n if (!line) continue;\n const [typeChar, sizeStr, mtimeStr, ...nameParts] = line.split('\\t');\n const name = nameParts.join('\\t');\n entries.push({\n name,\n type: typeChar === 'd' ? 'directory' : 'file',\n size: parseInt(sizeStr, 10) || 0,\n modified: new Date(parseFloat(mtimeStr) * 1000),\n });\n }\n return entries;\n },\n\n exists: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n const result = await runCommand(sandbox, `test -e ${shellEscape(diskPath)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox, path, runCommand) => {\n const diskPath = mapFilesystemPath(path);\n if (diskPath === ARCHIL_MOUNT_ROOT) {\n throw new Error('Refusing to remove the Archil disk mount root.');\n }\n const result = await runCommand(\n sandbox,\n withDiskWriteLock(`rm -rf ${shellEscape(diskPath)}`),\n );\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n getInstance: (sandbox: ArchilSandbox): ArchilSandbox => sandbox,\n },\n },\n});\n\nexport const archil = (config: ArchilConfig = {}) => _provider(config);\n\nexport type { ArchilSandbox };\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/archil",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "Archil provider for ComputeSDK - exec commands against an Archil disk",
5
5
  "author": "ComputeSDK",
6
6
  "license": "MIT",
@@ -18,8 +18,8 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
- "@computesdk/provider": "2.1.5",
22
- "computesdk": "4.1.4"
21
+ "computesdk": "4.1.4",
22
+ "@computesdk/provider": "2.1.5"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^20.0.0",