@rockclaver/sandcastle 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,7 +50,7 @@ interface DaytonaOptions {
50
50
  *
51
51
  * @example
52
52
  * ```ts
53
- * import { daytona } from "@ai-hero/sandcastle/sandboxes/daytona";
53
+ * import { daytona } from "@rockclaver/sandcastle/sandboxes/daytona";
54
54
  *
55
55
  * const provider = daytona({ apiKey: "dyt_my_key" });
56
56
  * ```
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sandboxes/daytona.ts"],"names":["files"],"mappings":"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","file":"daytona.js","sourcesContent":["/**\n * Daytona isolated sandbox provider.\n *\n * Creates ephemeral Daytona sandboxes via `@daytona/sdk`.\n * Requires `@daytona/sdk` as a peer dependency.\n */\n\nimport { readdir, stat } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport {\n createIsolatedSandboxProvider,\n type ExecResult,\n type IsolatedSandboxHandle,\n type IsolatedSandboxProvider,\n} from \"../SandboxProvider.js\";\nimport { BoundedTail, MAX_TAIL_CHARS } from \"../boundedTail.js\";\n\nimport type {\n Daytona as DaytonaClient,\n DaytonaConfig,\n CreateSandboxFromImageParams,\n CreateSandboxFromSnapshotParams,\n} from \"@daytona/sdk\";\n\n/** Options for the Daytona sandbox provider. */\nexport interface DaytonaOptions {\n /**\n * Daytona API key for authentication.\n * Falls back to the `DAYTONA_API_KEY` environment variable if not provided.\n */\n readonly apiKey?: string;\n\n /**\n * Daytona API URL.\n * Falls back to the `DAYTONA_API_URL` environment variable if not provided.\n */\n readonly apiUrl?: string;\n\n /**\n * Target environment for sandboxes.\n * Falls back to the `DAYTONA_TARGET` environment variable if not provided.\n */\n readonly target?: string;\n\n /**\n * Options passed through to the Daytona SDK when creating a sandbox.\n * Supports both image-based and snapshot-based creation.\n */\n readonly create?:\n | CreateSandboxFromImageParams\n | CreateSandboxFromSnapshotParams;\n\n /** Environment variables injected by this provider. Merged at launch time with env resolver and agent provider env. */\n readonly env?: Record<string, string>;\n\n /**\n * Maximum number of characters of streamed `exec` output retained per stream\n * (stdout and stderr) when an `onLine` callback is supplied (default: 64KiB).\n *\n * Output is delivered live to `onLine` regardless; this only bounds the tail\n * returned in `ExecResult`, preventing a long-running agent's output from\n * overflowing V8's max string length and crashing the run.\n */\n readonly maxOutputTailChars?: number;\n}\n\n/**\n * Create a Daytona isolated sandbox provider.\n *\n * Sandboxes are ephemeral — each `create()` call spins up a new Daytona\n * sandbox and `close()` destroys it.\n *\n * @example\n * ```ts\n * import { daytona } from \"@ai-hero/sandcastle/sandboxes/daytona\";\n *\n * const provider = daytona({ apiKey: \"dyt_my_key\" });\n * ```\n */\nexport const daytona = (options?: DaytonaOptions): IsolatedSandboxProvider =>\n createIsolatedSandboxProvider({\n name: \"daytona\",\n env: options?.env,\n create: async (): Promise<IsolatedSandboxHandle> => {\n const maxOutputTailChars = options?.maxOutputTailChars ?? MAX_TAIL_CHARS;\n const { Daytona } =\n (await import(\"@daytona/sdk\")) as typeof import(\"@daytona/sdk\");\n\n const config: DaytonaConfig = {};\n if (options?.apiKey) config.apiKey = options.apiKey;\n if (options?.apiUrl) config.apiUrl = options.apiUrl;\n if (options?.target) config.target = options.target;\n\n const client: DaytonaClient = new Daytona(config);\n const sandbox = await client.create(options?.create as any);\n\n const worktreePath =\n (await sandbox.getWorkDir()) ??\n (await sandbox.getUserHomeDir()) ??\n \"/home/daytona\";\n\n return {\n worktreePath,\n\n exec: async (\n command: string,\n opts?: {\n onLine?: (line: string) => void;\n cwd?: string;\n sudo?: boolean;\n },\n ): Promise<ExecResult> => {\n const effectiveCommand = opts?.sudo ? `sudo ${command}` : command;\n if (opts?.onLine) {\n const onLine = opts.onLine;\n const sessionId = `sandcastle-${crypto.randomUUID()}`;\n await sandbox.process.createSession(sessionId);\n\n try {\n const execResponse = await sandbox.process.executeSessionCommand(\n sessionId,\n {\n command: `cd ${opts?.cwd ?? worktreePath} && ${effectiveCommand}`,\n async: true,\n },\n );\n\n const cmdId = execResponse.cmdId!;\n\n const stdoutTail = new BoundedTail(maxOutputTailChars, \"\\n\");\n const stderrTail = new BoundedTail(maxOutputTailChars, \"\");\n let partial = \"\";\n\n await sandbox.process.getSessionCommandLogs(\n sessionId,\n cmdId,\n (chunk: string) => {\n const text = partial + chunk;\n const lines = text.split(\"\\n\");\n partial = lines.pop() ?? \"\";\n for (const line of lines) {\n stdoutTail.push(line);\n onLine(line);\n }\n },\n (chunk: string) => {\n stderrTail.push(chunk);\n },\n );\n\n if (partial) {\n stdoutTail.push(partial);\n onLine(partial);\n }\n\n const cmdInfo = await sandbox.process.getSessionCommand(\n sessionId,\n cmdId,\n );\n\n return {\n stdout: stdoutTail.toString(),\n stderr: stderrTail.toString(),\n exitCode: cmdInfo.exitCode ?? 0,\n };\n } finally {\n await sandbox.process.deleteSession(sessionId).catch(() => {});\n }\n }\n\n const response = await sandbox.process.executeCommand(\n effectiveCommand,\n opts?.cwd ?? worktreePath,\n );\n return {\n stdout: response.result,\n stderr: \"\",\n exitCode: response.exitCode,\n };\n },\n\n copyIn: async (\n hostPath: string,\n sandboxPath: string,\n ): Promise<void> => {\n const info = await stat(hostPath);\n if (info.isDirectory()) {\n const walk = async (dir: string): Promise<string[]> => {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await walk(full)));\n } else {\n files.push(full);\n }\n }\n return files;\n };\n const files = await walk(hostPath);\n for (const file of files) {\n const rel = relative(hostPath, file);\n await sandbox.fs.uploadFile(file, join(sandboxPath, rel));\n }\n } else {\n await sandbox.fs.uploadFile(hostPath, sandboxPath);\n }\n },\n\n copyFileOut: async (\n sandboxPath: string,\n hostPath: string,\n ): Promise<void> => {\n await sandbox.fs.downloadFile(sandboxPath, hostPath);\n },\n\n close: async (): Promise<void> => {\n await client.delete(sandbox);\n },\n };\n },\n });\n"]}
1
+ {"version":3,"sources":["../../src/sandboxes/daytona.ts"],"names":["files"],"mappings":"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","file":"daytona.js","sourcesContent":["/**\n * Daytona isolated sandbox provider.\n *\n * Creates ephemeral Daytona sandboxes via `@daytona/sdk`.\n * Requires `@daytona/sdk` as a peer dependency.\n */\n\nimport { readdir, stat } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport {\n createIsolatedSandboxProvider,\n type ExecResult,\n type IsolatedSandboxHandle,\n type IsolatedSandboxProvider,\n} from \"../SandboxProvider.js\";\nimport { BoundedTail, MAX_TAIL_CHARS } from \"../boundedTail.js\";\n\nimport type {\n Daytona as DaytonaClient,\n DaytonaConfig,\n CreateSandboxFromImageParams,\n CreateSandboxFromSnapshotParams,\n} from \"@daytona/sdk\";\n\n/** Options for the Daytona sandbox provider. */\nexport interface DaytonaOptions {\n /**\n * Daytona API key for authentication.\n * Falls back to the `DAYTONA_API_KEY` environment variable if not provided.\n */\n readonly apiKey?: string;\n\n /**\n * Daytona API URL.\n * Falls back to the `DAYTONA_API_URL` environment variable if not provided.\n */\n readonly apiUrl?: string;\n\n /**\n * Target environment for sandboxes.\n * Falls back to the `DAYTONA_TARGET` environment variable if not provided.\n */\n readonly target?: string;\n\n /**\n * Options passed through to the Daytona SDK when creating a sandbox.\n * Supports both image-based and snapshot-based creation.\n */\n readonly create?:\n | CreateSandboxFromImageParams\n | CreateSandboxFromSnapshotParams;\n\n /** Environment variables injected by this provider. Merged at launch time with env resolver and agent provider env. */\n readonly env?: Record<string, string>;\n\n /**\n * Maximum number of characters of streamed `exec` output retained per stream\n * (stdout and stderr) when an `onLine` callback is supplied (default: 64KiB).\n *\n * Output is delivered live to `onLine` regardless; this only bounds the tail\n * returned in `ExecResult`, preventing a long-running agent's output from\n * overflowing V8's max string length and crashing the run.\n */\n readonly maxOutputTailChars?: number;\n}\n\n/**\n * Create a Daytona isolated sandbox provider.\n *\n * Sandboxes are ephemeral — each `create()` call spins up a new Daytona\n * sandbox and `close()` destroys it.\n *\n * @example\n * ```ts\n * import { daytona } from \"@rockclaver/sandcastle/sandboxes/daytona\";\n *\n * const provider = daytona({ apiKey: \"dyt_my_key\" });\n * ```\n */\nexport const daytona = (options?: DaytonaOptions): IsolatedSandboxProvider =>\n createIsolatedSandboxProvider({\n name: \"daytona\",\n env: options?.env,\n create: async (): Promise<IsolatedSandboxHandle> => {\n const maxOutputTailChars = options?.maxOutputTailChars ?? MAX_TAIL_CHARS;\n const { Daytona } =\n (await import(\"@daytona/sdk\")) as typeof import(\"@daytona/sdk\");\n\n const config: DaytonaConfig = {};\n if (options?.apiKey) config.apiKey = options.apiKey;\n if (options?.apiUrl) config.apiUrl = options.apiUrl;\n if (options?.target) config.target = options.target;\n\n const client: DaytonaClient = new Daytona(config);\n const sandbox = await client.create(options?.create as any);\n\n const worktreePath =\n (await sandbox.getWorkDir()) ??\n (await sandbox.getUserHomeDir()) ??\n \"/home/daytona\";\n\n return {\n worktreePath,\n\n exec: async (\n command: string,\n opts?: {\n onLine?: (line: string) => void;\n cwd?: string;\n sudo?: boolean;\n },\n ): Promise<ExecResult> => {\n const effectiveCommand = opts?.sudo ? `sudo ${command}` : command;\n if (opts?.onLine) {\n const onLine = opts.onLine;\n const sessionId = `sandcastle-${crypto.randomUUID()}`;\n await sandbox.process.createSession(sessionId);\n\n try {\n const execResponse = await sandbox.process.executeSessionCommand(\n sessionId,\n {\n command: `cd ${opts?.cwd ?? worktreePath} && ${effectiveCommand}`,\n async: true,\n },\n );\n\n const cmdId = execResponse.cmdId!;\n\n const stdoutTail = new BoundedTail(maxOutputTailChars, \"\\n\");\n const stderrTail = new BoundedTail(maxOutputTailChars, \"\");\n let partial = \"\";\n\n await sandbox.process.getSessionCommandLogs(\n sessionId,\n cmdId,\n (chunk: string) => {\n const text = partial + chunk;\n const lines = text.split(\"\\n\");\n partial = lines.pop() ?? \"\";\n for (const line of lines) {\n stdoutTail.push(line);\n onLine(line);\n }\n },\n (chunk: string) => {\n stderrTail.push(chunk);\n },\n );\n\n if (partial) {\n stdoutTail.push(partial);\n onLine(partial);\n }\n\n const cmdInfo = await sandbox.process.getSessionCommand(\n sessionId,\n cmdId,\n );\n\n return {\n stdout: stdoutTail.toString(),\n stderr: stderrTail.toString(),\n exitCode: cmdInfo.exitCode ?? 0,\n };\n } finally {\n await sandbox.process.deleteSession(sessionId).catch(() => {});\n }\n }\n\n const response = await sandbox.process.executeCommand(\n effectiveCommand,\n opts?.cwd ?? worktreePath,\n );\n return {\n stdout: response.result,\n stderr: \"\",\n exitCode: response.exitCode,\n };\n },\n\n copyIn: async (\n hostPath: string,\n sandboxPath: string,\n ): Promise<void> => {\n const info = await stat(hostPath);\n if (info.isDirectory()) {\n const walk = async (dir: string): Promise<string[]> => {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await walk(full)));\n } else {\n files.push(full);\n }\n }\n return files;\n };\n const files = await walk(hostPath);\n for (const file of files) {\n const rel = relative(hostPath, file);\n await sandbox.fs.uploadFile(file, join(sandboxPath, rel));\n }\n } else {\n await sandbox.fs.uploadFile(hostPath, sandboxPath);\n }\n },\n\n copyFileOut: async (\n sandboxPath: string,\n hostPath: string,\n ): Promise<void> => {\n await sandbox.fs.downloadFile(sandboxPath, hostPath);\n },\n\n close: async (): Promise<void> => {\n await client.delete(sandbox);\n },\n };\n },\n });\n"]}
@@ -1,5 +1,5 @@
1
- import { run, agent } from "@ai-hero/sandcastle";
2
- import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
1
+ import { run, agent } from "@rockclaver/sandcastle";
2
+ import { docker } from "@rockclaver/sandcastle/sandboxes/docker";
3
3
 
4
4
  // Blank template: customize this to build your own orchestration.
5
5
  // Run this with: npx tsx .sandcastle/main.mts
@@ -16,8 +16,8 @@
16
16
  // Or add to package.json:
17
17
  // "scripts": { "sandcastle": "npx tsx .sandcastle/main.mts" }
18
18
 
19
- import * as sandcastle from "@ai-hero/sandcastle";
20
- import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
19
+ import * as sandcastle from "@rockclaver/sandcastle";
20
+ import { docker } from "@rockclaver/sandcastle/sandboxes/docker";
21
21
  import { z } from "zod";
22
22
 
23
23
  // The planner emits its plan as JSON inside <plan> tags; Output.object extracts
@@ -21,8 +21,8 @@
21
21
  // Or add to package.json:
22
22
  // "scripts": { "sandcastle": "npx tsx .sandcastle/main.mts" }
23
23
 
24
- import * as sandcastle from "@ai-hero/sandcastle";
25
- import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
24
+ import * as sandcastle from "@rockclaver/sandcastle";
25
+ import { docker } from "@rockclaver/sandcastle/sandboxes/docker";
26
26
  import { z } from "zod";
27
27
 
28
28
  // The planner emits its plan as JSON inside <plan> tags; Output.object extracts
@@ -21,8 +21,8 @@
21
21
  // Or add to package.json:
22
22
  // "scripts": { "sandcastle": "npx tsx .sandcastle/main.mts" }
23
23
 
24
- import * as sandcastle from "@ai-hero/sandcastle";
25
- import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
24
+ import * as sandcastle from "@rockclaver/sandcastle";
25
+ import { docker } from "@rockclaver/sandcastle/sandboxes/docker";
26
26
 
27
27
  // ---------------------------------------------------------------------------
28
28
  // Configuration
@@ -1,5 +1,5 @@
1
- import { run, agent } from "@ai-hero/sandcastle";
2
- import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
1
+ import { run, agent } from "@rockclaver/sandcastle";
2
+ import { docker } from "@rockclaver/sandcastle/sandboxes/docker";
3
3
 
4
4
  // Simple loop: an agent that picks open issues one by one and closes them.
5
5
  // Run this with: npx tsx .sandcastle/main.mts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rockclaver/sandcastle",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "CLI for orchestrating AI agents in isolated sandbox environments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,7 +60,7 @@
60
60
  "packageManager": "npm@10.9.2",
61
61
  "repository": {
62
62
  "type": "git",
63
- "url": "https://github.com/mattpocock/sandcastle"
63
+ "url": "git+https://github.com/rockclaver/sandcastle.git"
64
64
  },
65
65
  "license": "MIT",
66
66
  "devDependencies": {