@capsule-run/cli 0.2.1 → 0.3.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 +135 -0
- package/bin/capsule.js +51 -0
- package/package.json +18 -9
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# capsule
|
|
2
|
+
|
|
3
|
+
**A secure, durable runtime for agentic workflows**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Capsule is a runtime for coordinating AI agent tasks in isolated environments. It is designed to handle long-running workflows, large-scale processing, autonomous decision-making securely, or even multi-agent systems.
|
|
8
|
+
|
|
9
|
+
Each task runs inside its own WebAssembly sandbox, providing:
|
|
10
|
+
|
|
11
|
+
- **Isolated execution**: Each task runs isolated from your host system
|
|
12
|
+
- **Resource limits**: Set CPU, memory, and timeout limits per task
|
|
13
|
+
- **Automatic retries**: Handle failures without manual intervention
|
|
14
|
+
- **Lifecycle tracking**: Monitor which tasks are running, completed, or failed
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @capsule-run/cli
|
|
20
|
+
npm install @capsule-run/sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
Create `hello.ts`:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { task } from "@capsule-run/sdk";
|
|
29
|
+
|
|
30
|
+
export const main = task({
|
|
31
|
+
name: "main",
|
|
32
|
+
compute: "LOW",
|
|
33
|
+
ram: "64MB"
|
|
34
|
+
}, (): string => {
|
|
35
|
+
return "Hello from Capsule!";
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Run it:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
capsule run hello.ts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
Simply use a wrapper function to define your tasks:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { task } from "@capsule-run/sdk";
|
|
51
|
+
|
|
52
|
+
export const analyzeData = task({
|
|
53
|
+
name: "analyze_data",
|
|
54
|
+
compute: "MEDIUM",
|
|
55
|
+
ram: "512MB",
|
|
56
|
+
timeout: "30s",
|
|
57
|
+
maxRetries: 1
|
|
58
|
+
}, (dataset: number[]): object => {
|
|
59
|
+
// Your code runs safely in a Wasm sandbox
|
|
60
|
+
return { processed: dataset.length, status: "complete" };
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// The "main" task is required as the entrypoint
|
|
64
|
+
export const main = task({
|
|
65
|
+
name: "main",
|
|
66
|
+
compute: "HIGH"
|
|
67
|
+
}, () => {
|
|
68
|
+
return analyzeData([1, 2, 3, 4, 5]);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When you run `capsule run main.ts`, your code is compiled into a WebAssembly module and executed in a dedicated sandbox.
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
### Task Configuration Options
|
|
77
|
+
|
|
78
|
+
| Parameter | Description | Type | Default | Example |
|
|
79
|
+
|-----------|-------------|------|---------|---------|
|
|
80
|
+
| `name` | Task identifier | `string` | *required* | `"process_data"` |
|
|
81
|
+
| `compute` | CPU level: `"LOW"`, `"MEDIUM"`, `"HIGH"` | `string` | `"MEDIUM"` | `"HIGH"` |
|
|
82
|
+
| `ram` | Memory limit | `string` | unlimited | `"512MB"`, `"2GB"` |
|
|
83
|
+
| `timeout` | Maximum execution time | `string` or `number` | unlimited | `"30s"`, `"5m"`, `30000` (ms) |
|
|
84
|
+
| `maxRetries` | Retry attempts on failure | `number` | `0` | `3` |
|
|
85
|
+
| `allowedFiles` | Folders accessible in the sandbox | `string[]` | `[]` | `["./data", "./output"]` |
|
|
86
|
+
|
|
87
|
+
### Compute Levels
|
|
88
|
+
|
|
89
|
+
- **LOW**: Minimal allocation for lightweight tasks
|
|
90
|
+
- **MEDIUM**: Balanced resources for typical workloads
|
|
91
|
+
- **HIGH**: Maximum fuel for compute-intensive operations
|
|
92
|
+
- **CUSTOM**: Specify exact fuel value (e.g., `compute="1000000"`)
|
|
93
|
+
|
|
94
|
+
### File Access
|
|
95
|
+
|
|
96
|
+
The **entry point task** (main) has access to the entire project directory. Sub-tasks have **no filesystem access by default** and must declare `allowedFiles` to access specific paths.
|
|
97
|
+
|
|
98
|
+
Node.js built-ins like `fs` are not available in the WebAssembly sandbox. Instead, use the `files` API provided by the SDK:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { task, files } from "@capsule-run/sdk";
|
|
102
|
+
|
|
103
|
+
export const restrictedWriter = task({
|
|
104
|
+
name: "restricted_writer",
|
|
105
|
+
allowedFiles: ["./output"]
|
|
106
|
+
}, async () => {
|
|
107
|
+
await files.writeText("./output/result.txt", "result");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export const main = task({ name: "main" }, async () => {
|
|
111
|
+
restrictedWriter();
|
|
112
|
+
return await files.readText("./data/input.txt");
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Available methods:
|
|
117
|
+
- `files.readText(path)` — Read file as string
|
|
118
|
+
- `files.readBytes(path)` — Read file as `Uint8Array`
|
|
119
|
+
- `files.writeText(path, content)` — Write string to file
|
|
120
|
+
- `files.writeBytes(path, data)` — Write bytes to file
|
|
121
|
+
- `files.list(path)` — List directory contents
|
|
122
|
+
- `files.exists(path)` — Check if file exists
|
|
123
|
+
|
|
124
|
+
## Compatibility
|
|
125
|
+
|
|
126
|
+
✅ **Supported:**
|
|
127
|
+
- npm packages and ES modules work
|
|
128
|
+
|
|
129
|
+
⚠️ **Not yet supported:**
|
|
130
|
+
- Node.js built-ins (`fs`, `path`, `os`) are not available in the sandbox
|
|
131
|
+
|
|
132
|
+
## Links
|
|
133
|
+
|
|
134
|
+
- [GitHub](https://github.com/mavdol/capsule)
|
|
135
|
+
- [Issues](https://github.com/mavdol/capsule/issues)
|
package/bin/capsule.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const PLATFORMS = {
|
|
8
|
+
"darwin-arm64": "@capsule-run/cli-darwin-arm64",
|
|
9
|
+
"darwin-x64": "@capsule-run/cli-darwin-x64",
|
|
10
|
+
"linux-x64": "@capsule-run/cli-linux-x64",
|
|
11
|
+
"win32-x64": "@capsule-run/cli-win32-x64",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function getPlatformPackage() {
|
|
15
|
+
const key = `${process.platform}-${process.arch}`;
|
|
16
|
+
return PLATFORMS[key];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function findBinary() {
|
|
20
|
+
const pkg = getPlatformPackage();
|
|
21
|
+
if (!pkg) {
|
|
22
|
+
console.error(`Unsupported platform: ${process.platform}-${process.arch}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const pkgPath = require.resolve(`${pkg}/package.json`);
|
|
28
|
+
const pkgDir = path.dirname(pkgPath);
|
|
29
|
+
const binary = process.platform === "win32" ? "capsule.exe" : "capsule";
|
|
30
|
+
const binaryPath = path.join(pkgDir, binary);
|
|
31
|
+
|
|
32
|
+
if (fs.existsSync(binaryPath)) {
|
|
33
|
+
return binaryPath;
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Package not found
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.error(`Could not find capsule binary for ${process.platform}-${process.arch}`);
|
|
40
|
+
console.error(`Please ensure @capsule-run/cli is installed correctly.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const result = spawnSync(findBinary(), process.argv.slice(2), { stdio: "inherit" });
|
|
45
|
+
|
|
46
|
+
if (result.error) {
|
|
47
|
+
console.error(result.error.message);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
process.exit(result.status ?? 1);
|
package/package.json
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capsule-run/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Secure WASM runtime to isolate and manage AI agent tasks",
|
|
5
|
+
"bin": {
|
|
6
|
+
"capsule": "./bin/capsule.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/"
|
|
10
|
+
],
|
|
5
11
|
"keywords": [
|
|
6
12
|
"webassembly",
|
|
7
|
-
"cli",
|
|
8
13
|
"sandbox",
|
|
9
|
-
"
|
|
14
|
+
"agents",
|
|
10
15
|
"isolation",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
16
|
+
"llm",
|
|
17
|
+
"ai"
|
|
13
18
|
],
|
|
14
19
|
"license": "Apache-2.0",
|
|
15
20
|
"repository": {
|
|
16
21
|
"type": "git",
|
|
17
22
|
"url": "https://github.com/mavdol/capsule.git"
|
|
18
23
|
},
|
|
24
|
+
"homepage": "https://github.com/mavdol/capsule",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
19
28
|
"engines": {
|
|
20
29
|
"node": ">=18"
|
|
21
30
|
},
|
|
22
31
|
"optionalDependencies": {
|
|
23
|
-
"@capsule-run/cli-darwin-arm64": "0.
|
|
24
|
-
"@capsule-run/cli-darwin-x64": "0.
|
|
25
|
-
"@capsule-run/cli-linux-x64": "0.
|
|
26
|
-
"@capsule-run/cli-win32-x64": "0.
|
|
32
|
+
"@capsule-run/cli-darwin-arm64": "0.3.0",
|
|
33
|
+
"@capsule-run/cli-darwin-x64": "0.3.0",
|
|
34
|
+
"@capsule-run/cli-linux-x64": "0.3.0",
|
|
35
|
+
"@capsule-run/cli-win32-x64": "0.3.0"
|
|
27
36
|
}
|
|
28
37
|
}
|