@capsule-run/sdk 0.6.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -173,7 +173,7 @@ Every task returns a structured JSON envelope containing both the result and exe
173
173
  | `ram` | Memory limit | `string` | unlimited | `"512MB"`, `"2GB"` |
174
174
  | `timeout` | Maximum execution time | `string` or `number` | unlimited | `"30s"`, `"5m"` |
175
175
  | `maxRetries` | Retry attempts on failure | `number` | `0` | `3` |
176
- | `allowedFiles` | Folders accessible in the sandbox | `string[]` | `[]` | `["./data", "./output"]` |
176
+ | `allowedFiles` | Folders accessible in the sandbox (with optional access mode) | `(string \| AllowedFile)[]` | `[]` | `["./data"]`, `[{ path: "./data", mode: "ro" }]` |
177
177
  | `allowedHosts` | Domains accessible in the sandbox | `string[]` | `["*"]` | `["api.openai.com", "*.anthropic.com"]` |
178
178
  | `envVariables` | Environment variables accessible in the sandbox | `string[]` | `[]` | `["API_KEY"]` |
179
179
 
@@ -206,25 +206,31 @@ Task-level options always override these defaults.
206
206
 
207
207
  Tasks can read and write files within directories specified in `allowedFiles`. Any attempt to access files outside these directories is not possible.
208
208
 
209
+ > `allowedFiles` supports directory paths only, not individual files.
210
+
211
+ Each entry can be a plain path (read-write by default) or an `AllowedFile` object with an explicit `mode`: `"read-only"` (or `"ro"`) or `"read-write"` (or `"rw"`).
212
+
209
213
  Common Node.js built-ins are available. Use the standard `fs` module:
210
214
 
211
215
  ```typescript
212
216
  import { task } from "@capsule-run/sdk";
213
217
  import fs from "fs/promises";
214
218
 
215
- export const restrictedWriter = task({
216
- name: "restricted_writer",
217
- allowedFiles: ["./output"]
219
+ export const main = task({
220
+ name: "main",
221
+ allowedFiles: [
222
+ { path: "./data", mode: "read-only" },
223
+ { path: "./output", mode: "read-write" },
224
+ ]
218
225
  }, async () => {
219
- await fs.writeFile("./output/result.txt", "result");
220
- });
221
-
222
- export const main = task({ name: "main", allowedFiles: ["./data"] }, async () => {
223
- await restrictedWriter();
224
- return await fs.readFile("./data/input.txt", "utf8");
226
+ const content = await fs.readFile("./data/input.txt", "utf8");
227
+ await fs.writeFile("./output/result.txt", content);
228
+ return content;
225
229
  });
226
230
  ```
227
231
 
232
+ Plain strings are still accepted: `allowedFiles: ["./output"]` defaults to read-write.
233
+
228
234
  ### Network Access
229
235
 
230
236
  Tasks can make HTTP requests to domains specified in `allowedHosts`. By default, all outbound requests are allowed (`[\"*\"]`). Restrict access by providing a whitelist of domains.
package/dist/task.d.ts CHANGED
@@ -4,6 +4,12 @@
4
4
  * Provides the `task` wrapper function for defining Capsule tasks
5
5
  * in an idiomatic TypeScript way.
6
6
  */
7
+ export interface AllowedFile {
8
+ /** Path to the directory, e.g., "./data" */
9
+ path: string;
10
+ /** Access mode: "read-only" / "ro" or "read-write" / "rw" (default) */
11
+ mode?: "read-only" | "read-write" | "ro" | "rw";
12
+ }
7
13
  export interface TaskOptions {
8
14
  /** Task name (required) */
9
15
  name: string;
@@ -19,8 +25,8 @@ export interface TaskOptions {
19
25
  timeout?: string | number;
20
26
  /** Maximum number of retries */
21
27
  maxRetries?: number;
22
- /** Files/folders accessible in the sandbox, e.g., ["./data"] */
23
- allowedFiles?: string[];
28
+ /** Files/folders accessible in the sandbox, e.g., ["./data"] or [{ path: "./data", mode: "ro" }] */
29
+ allowedFiles?: (string | AllowedFile)[];
24
30
  /** Allowed hosts for HTTP requests */
25
31
  allowedHosts?: string[];
26
32
  /** Environment variables available from your .env file for the task */
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,WAAW;IAC1B,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7C,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,UAAU,UAAU,CAAC,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtD,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,UAAU,aAAa;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AAID,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAC/C,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GACtB,UAAU,CAAC,CAAC,CAAC,CAAC;AA+ClB,wBAAgB,IAAI,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,EAC/C,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,GAC9B,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,cAAc,CAAC,OAAO,CAAC,CA+D7C"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,IAAI,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,WAAW;IAC1B,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7C,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oGAAoG;IACpG,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;IACxC,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,UAAU,UAAU,CAAC,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtD,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,UAAU,aAAa;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AAID,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAC/C,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GACtB,UAAU,CAAC,CAAC,CAAC,CAAC;AAiElB,wBAAgB,IAAI,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,EAC/C,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,GAC9B,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,cAAc,CAAC,OAAO,CAAC,CA+D7C"}
package/dist/task.js CHANGED
@@ -50,6 +50,22 @@ function normalizeTimeout(timeout) {
50
50
  }
51
51
  return timeout;
52
52
  }
53
+ function normalizeAllowedFile(entry) {
54
+ if (typeof entry === "string")
55
+ return entry;
56
+ switch (entry.mode) {
57
+ case undefined:
58
+ case "rw":
59
+ case "read-write":
60
+ return entry.path;
61
+ case "ro":
62
+ case "read-only":
63
+ return `${entry.path}:ro`;
64
+ default:
65
+ throw new Error(`Invalid allowed_files mode '${entry.mode}' for path '${entry.path}'. ` +
66
+ `Use 'read-only' or 'read-write'.`);
67
+ }
68
+ }
53
69
  export function task(options, fn) {
54
70
  const taskName = options.name;
55
71
  let compute = options.compute?.toString().toUpperCase() ?? "MEDIUM";
@@ -60,7 +76,7 @@ export function task(options, fn) {
60
76
  ram: options.ram,
61
77
  timeout: normalizeTimeout(options.timeout),
62
78
  maxRetries: options.maxRetries,
63
- allowedFiles: options.allowedFiles,
79
+ allowedFiles: options.allowedFiles?.map(normalizeAllowedFile),
64
80
  allowedHosts,
65
81
  envVariables: options.envVariables,
66
82
  };
package/dist/task.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAmB,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AA6CpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,OAAyB;IACjD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,GAAG,OAAO,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,OAAoB,EACpB,EAA+B;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9B,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,IAAI,QAAQ,CAAC;IACpE,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjD,MAAM,UAAU,GAAe;QAC7B,IAAI,EAAE,QAAQ;QACd,OAAO;QACP,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1C,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,YAAY;QACZ,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAG,IAAW,EAA2B,EAAE;QAC1D,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YAE3B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC7B,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,KAAK;oBACb,KAAK,EAAE,IAAI;oBACX,SAAS,EAAE;wBACT,SAAS,EAAE,QAAQ;wBACnB,WAAW,EAAE,CAAC;wBACd,OAAO,EAAE,CAAC;wBACV,aAAa,EAAE,CAAC;qBACjB;iBACF,CAAC,CAA4B,CAAC;YACjC,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM;gBACN,KAAK,EAAE,IAAI;gBACX,SAAS,EAAE;oBACT,SAAS,EAAE,QAAQ;oBACnB,WAAW,EAAE,CAAC;oBACd,OAAO,EAAE,CAAC;oBACV,aAAa,EAAE,CAAC;iBACjB;aACyB,CAAC;QAC/B,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAExD,IAAI,CAAC;YACH,MAAM,MAAM,GAAiC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpE,OAAO,MAAiC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,WAAW,EAAE,CAAC;gBAC7B,OAAO,UAAgD,CAAC;YAC1D,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC;IAEF,YAAY,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;IAEvC,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capsule-run/sdk",
3
- "version": "0.6.5",
3
+ "version": "0.7.0",
4
4
  "description": "Capsule JavaScript SDK - run AI agent tasks in secure WASM sandboxes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/task.ts CHANGED
@@ -8,6 +8,13 @@
8
8
  import { registerTask, type TaskConfig } from "./app.js";
9
9
  import { isWasmMode, callHost } from "./hostApi.js";
10
10
 
11
+ export interface AllowedFile {
12
+ /** Path to the directory, e.g., "./data" */
13
+ path: string;
14
+ /** Access mode: "read-only" / "ro" or "read-write" / "rw" (default) */
15
+ mode?: "read-only" | "read-write" | "ro" | "rw";
16
+ }
17
+
11
18
  export interface TaskOptions {
12
19
  /** Task name (required) */
13
20
  name: string;
@@ -23,8 +30,8 @@ export interface TaskOptions {
23
30
  timeout?: string | number;
24
31
  /** Maximum number of retries */
25
32
  maxRetries?: number;
26
- /** Files/folders accessible in the sandbox, e.g., ["./data"] */
27
- allowedFiles?: string[];
33
+ /** Files/folders accessible in the sandbox, e.g., ["./data"] or [{ path: "./data", mode: "ro" }] */
34
+ allowedFiles?: (string | AllowedFile)[];
28
35
  /** Allowed hosts for HTTP requests */
29
36
  allowedHosts?: string[];
30
37
  /** Environment variables available from your .env file for the task */
@@ -96,6 +103,24 @@ function normalizeTimeout(timeout?: string | number): string | undefined {
96
103
  return timeout;
97
104
  }
98
105
 
106
+ function normalizeAllowedFile(entry: string | AllowedFile): string {
107
+ if (typeof entry === "string") return entry;
108
+ switch (entry.mode) {
109
+ case undefined:
110
+ case "rw":
111
+ case "read-write":
112
+ return entry.path;
113
+ case "ro":
114
+ case "read-only":
115
+ return `${entry.path}:ro`;
116
+ default:
117
+ throw new Error(
118
+ `Invalid allowed_files mode '${(entry as any).mode}' for path '${entry.path}'. ` +
119
+ `Use 'read-only' or 'read-write'.`
120
+ );
121
+ }
122
+ }
123
+
99
124
  export function task<TArgs extends any[], TReturn>(
100
125
  options: TaskOptions,
101
126
  fn: (...args: TArgs) => TReturn
@@ -110,7 +135,7 @@ export function task<TArgs extends any[], TReturn>(
110
135
  ram: options.ram,
111
136
  timeout: normalizeTimeout(options.timeout),
112
137
  maxRetries: options.maxRetries,
113
- allowedFiles: options.allowedFiles,
138
+ allowedFiles: options.allowedFiles?.map(normalizeAllowedFile),
114
139
  allowedHosts,
115
140
  envVariables: options.envVariables,
116
141
  };