Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,56 @@ env:
CARGO_TERM_COLOR: always

jobs:
ci:
name: Test, Format, Lint
image-resize:
name: image-resize
runs-on: ubuntu-latest
defaults:
run:
working-directory: image-resize
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- uses: Swatinem/rust-cache@v2
with:
workspaces: image-resize -> target
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features

- name: Check formatting
run: cargo fmt --all -- --check

- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
sandbox-docker:
name: sandbox-docker
runs-on: ubuntu-latest
defaults:
run:
working-directory: sandbox-docker
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: sandbox-docker -> target
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features

- name: Run tests
run: cargo test --all-features
sandbox-firecracker:
name: sandbox-firecracker
runs-on: ubuntu-latest
defaults:
run:
working-directory: sandbox-firecracker
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: sandbox-firecracker -> target
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features
142 changes: 104 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,71 +1,137 @@
# Motia Workers
# III Workers

Worker modules for the [III engine](https://github.com/motia).
Worker modules for the [III engine](https://github.com/iii-hq/iii).

## Modules
Each worker is a standalone Rust binary that connects to the engine via WebSocket, registers functions and triggers, and uses the engine's built-in state. No custom SDKs — consume workers through iii-sdk (`iii.trigger()`).

## Workers

### image-resize

A Rust-based image resize worker that connects to the III engine via WebSocket and processes images through stream channels.
Image resize worker using stream channels.

**Supported formats:** JPEG, PNG, WebP (including cross-format conversion)

**Resize strategies:**

| Strategy | Behavior |
|---|---|
| `scale-to-fit` | Scales the image to fit within the target dimensions, preserving aspect ratio (default) |
| `crop-to-fit` | Scales and center-crops to fill the exact target dimensions |
| `scale-to-fit` | Scales to fit within target dimensions, preserving aspect ratio (default) |
| `crop-to-fit` | Scales and center-crops to fill exact target dimensions |

```bash
cd image-resize && cargo build --release
./target/release/image-resize --url ws://127.0.0.1:49134
```

---

**Features:**
- EXIF orientation auto-correction
- Configurable quality per format (JPEG, WebP)
- Per-request parameter overrides (dimensions, quality, strategy, output format)
- Module manifest output (`--manifest`)
### sandbox-docker

#### Prerequisites
Docker container sandbox. Creates isolated containers, executes commands, runs code, reads/writes files.

- Rust 1.70+
- A running III engine instance
**Functions registered:**

#### Build
| Function ID | Description |
|---|---|
| `sandbox::create` | Create a Docker container with security hardening |
| `sandbox::get` | Get sandbox details by ID |
| `sandbox::list` | List all sandboxes |
| `sandbox::kill` | Stop and remove a sandbox |
| `exec::run` | Execute a shell command inside a sandbox |
| `exec::code` | Write and run a code snippet (Python, JavaScript, Bash) |
| `fs::read` | Read a file from a sandbox |
| `fs::write` | Write a file to a sandbox |
| `fs::list` | List directory contents |

**Security:** `pids_limit=256`, `cap_drop=[NET_RAW, SYS_ADMIN, MKNOD]`, `no-new-privileges`, `network=none` by default.

```bash
cd image-resize
cargo build --release
cd sandbox-docker && cargo build --release
./target/release/sandbox-docker --url ws://127.0.0.1:49134
```

#### Usage
**Usage from iii-sdk:**

```bash
# Run with defaults (connects to ws://127.0.0.1:49134)
./target/release/image-resize
```typescript
const sbx = await iii.trigger({ functionId: 'sandbox::create', payload: { image: 'python:3.12-slim' } });
const result = await iii.trigger({ functionId: 'exec::run', payload: { id: sbx.id, command: 'echo hello' } });
const code = await iii.trigger({ functionId: 'exec::code', payload: { id: sbx.id, code: 'print(42)', language: 'python' } });
await iii.trigger({ functionId: 'sandbox::kill', payload: { id: sbx.id } });
```

**Configuration (`config.yaml`):**

```yaml
default_image: python:3.12-slim
default_timeout: 3600
default_memory: 512
max_sandboxes: 50
workspace_dir: /workspace
```

---

# Custom config and engine URL
./target/release/image-resize --config ./config.yaml --url ws://host:port
### sandbox-firecracker

# Print module manifest
./target/release/image-resize --manifest
KVM CoW fork sandbox for sub-millisecond VM spawning. Hardware-enforced isolation via Intel VT-x / AMD-V. **Linux-only.**

**How it works:** Loads a pre-built VM template (CPU state + memory dump) into a `memfd` at startup. Each `sandbox::create` call forks via `mmap(MAP_PRIVATE)` — Copy-on-Write memory mapping. Spawn time: ~0.8ms. Memory overhead: ~265KB per sandbox.

**Functions registered:**

| Function ID | Description |
|---|---|
| `sandbox::create` | Fork a new KVM VM from template (~0.8ms) |
| `sandbox::get` | Get sandbox details by ID |
| `sandbox::list` | List all sandboxes |
| `sandbox::kill` | Kill VM (munmap + close KVM fds) |
| `exec::run` | Execute command via serial I/O |
| `exec::code` | Run code snippet via serial I/O (Python, JavaScript, Bash) |

**Communication:** Serial I/O (16550 UART at COM1). No networking, no filesystem — code in, output out.

```bash
cd sandbox-firecracker && cargo build --release
./target/release/sandbox-firecracker --url ws://127.0.0.1:49134 --config config.yaml
```

#### Configuration
**Usage from iii-sdk:**

Create a `config.yaml` file:
```typescript
const vm = await iii.trigger({ functionId: 'sandbox::create', payload: { language: 'python' } });
const result = await iii.trigger({ functionId: 'exec::code', payload: { id: vm.id, code: 'print(42)' } });
await iii.trigger({ functionId: 'sandbox::kill', payload: { id: vm.id } });
```

**Configuration (`config.yaml`):**

```yaml
width: 200 # default target width
height: 200 # default target height
strategy: scale-to-fit # or crop-to-fit
quality:
jpeg: 85
webp: 80
vmstate_path: ./template/vmstate
memfile_path: ./template/mem
mem_size_mb: 256
default_timeout: 30
max_sandboxes: 1000
```

All fields are optional and fall back to the defaults shown above.
**Prerequisites:** Linux with KVM enabled, pre-built Firecracker VM template (vmstate + memory dump).

---

#### Tests
## Building

Each worker is a standalone Rust crate:

```bash
cd image-resize
cd <worker-name>
cargo build --release
cargo test
```

## CLI flags

All workers support:

| Flag | Default | Description |
|---|---|---|
| `--url` | `ws://127.0.0.1:49134` | III engine WebSocket URL |
| `--config` | `./config.yaml` | Path to config file |
| `--manifest` | — | Print module manifest JSON and exit |
2 changes: 1 addition & 1 deletion image-resize/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mod tests {
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert!(parsed.is_object(), "Manifest must be valid JSON object");
assert_eq!(parsed["name"], "image-resize");
assert_eq!(parsed["version"], "0.1.0");
assert_eq!(parsed["version"], env!("CARGO_PKG_VERSION"));
}

#[test]
Expand Down
36 changes: 36 additions & 0 deletions registry/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,42 @@
}
},
"version": "0.1.2"
},
"sandbox-docker": {
"description": "Docker container sandbox worker — create, exec, filesystem ops",
"repo": "iii-hq/workers",
"tag_prefix": "sandbox-docker",
"supported_targets": ["aarch64-apple-darwin", "x86_64-unknown-linux-gnu"],
"has_checksum": true,
"default_config": {
"class": "workers::sandbox_docker::SandboxDockerWorker",
"config": {
"default_image": "python:3.12-slim",
"default_timeout": 3600,
"default_memory": 512,
"max_sandboxes": 50,
"workspace_dir": "/workspace"
}
},
"version": "0.1.0"
},
"sandbox-firecracker": {
"description": "KVM CoW fork sandbox worker — sub-ms spawn, hardware isolation (Linux-only)",
"repo": "iii-hq/workers",
"tag_prefix": "sandbox-firecracker",
"supported_targets": ["x86_64-unknown-linux-gnu"],
"has_checksum": true,
"default_config": {
"class": "workers::sandbox_firecracker::SandboxFirecrackerWorker",
"config": {
"vmstate_path": "./template/vmstate",
"memfile_path": "./template/mem",
"mem_size_mb": 256,
"default_timeout": 30,
"max_sandboxes": 1000
}
},
"version": "0.1.0"
}
}
}
Loading
Loading