un-inception/clients/README.md
russell@unturf.com 6d91e987ce feat: Full SDK implementations for 8 languages (sync + async)
Complete SDK implementations with full API surface:
- Python: sync/async with all 43 functions
- Go: sync/async with full API
- Java: sync/async with full API
- JavaScript: sync/async with full API
- PHP: sync/async with full API
- Ruby: sync/async with full API
- Rust: sync/async with full API

Added:
- clients/README.md - SDK overview
- clients/CLI_SPEC.md - CLI specification

Removed:
- un_deno.ts (moved to clients/typescript/)
2026-01-15 18:35:43 -05:00

318 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Unsandbox SDK Clients
Multi-language SDK implementations for the Unsandbox API.
**Each SDK is BOTH a library AND a CLI tool** - see [CLI_SPEC.md](CLI_SPEC.md) for the full CLI specification.
```bash
# Library usage
python -c "from un import execute_code; print(execute_code('python', 'print(1)'))"
# CLI usage (identical across all 42+ languages)
python un.py script.py
python un.py -s bash 'echo hello'
python un.py session --tmux
python un.py service --list
```
## Directory Structure
```
clients/
├── python/
│ ├── sync/src/un.py # Synchronous (requests)
│ └── async/src/un_async.py # Asynchronous (aiohttp)
├── javascript/
│ ├── sync/src/un.js # Synchronous (https)
│ └── async/src/un_async.js # Asynchronous (fetch)
├── go/
│ ├── sync/src/un.go # Synchronous (net/http)
│ └── async/src/un_async.go # Asynchronous (goroutines)
├── java/
│ ├── sync/src/Un.java # Synchronous (HttpURLConnection)
│ └── async/src/UnsandboxAsync.java # Asynchronous (CompletableFuture)
├── ruby/
│ ├── sync/src/un.rb # Synchronous (net/http)
│ └── async/src/un_async.rb # Asynchronous (Future)
├── rust/
│ ├── sync/src/lib.rs # Synchronous (reqwest blocking)
│ └── async/src/lib.rs # Asynchronous (reqwest + tokio)
├── php/
│ ├── sync/src/un.php # Synchronous (cURL)
│ └── async/src/UnsandboxAsync.php # Asynchronous (Guzzle promises)
└── c/
└── src/unsandbox.c # Reference implementation
```
## API Functions (43 total)
All SDKs implement the complete Unsandbox API:
### Execute & Jobs (6 functions)
| Function | Description | Endpoint |
|----------|-------------|----------|
| `execute_code` | Execute code synchronously | POST /execute |
| `execute_async` | Execute code, return job ID | POST /execute (async mode) |
| `get_job` | Get job status | GET /jobs/{id} |
| `wait_for_job` | Poll until completion | GET /jobs/{id} (polling) |
| `cancel_job` | Cancel running job | DELETE /jobs/{id} |
| `list_jobs` | List all jobs | GET /jobs |
### Sessions (9 functions)
| Function | Description | Endpoint |
|----------|-------------|----------|
| `list_sessions` | List all sessions | GET /sessions |
| `get_session` | Get session details | GET /sessions/{id} |
| `create_session` | Create interactive session | POST /sessions |
| `delete_session` | Terminate session | DELETE /sessions/{id} |
| `freeze_session` | Pause session | POST /sessions/{id}/freeze |
| `unfreeze_session` | Resume session | POST /sessions/{id}/unfreeze |
| `boost_session` | Add vCPUs | POST /sessions/{id}/boost |
| `unboost_session` | Remove boost | POST /sessions/{id}/unboost |
| `shell_session` | Execute shell command | POST /sessions/{id}/shell |
### Services (16 functions)
| Function | Description | Endpoint |
|----------|-------------|----------|
| `list_services` | List all services | GET /services |
| `create_service` | Create persistent service | POST /services |
| `get_service` | Get service details | GET /services/{id} |
| `update_service` | Update/resize service | PATCH /services/{id} |
| `delete_service` | Destroy service | DELETE /services/{id} |
| `freeze_service` | Pause service | POST /services/{id}/freeze |
| `unfreeze_service` | Resume service | POST /services/{id}/unfreeze |
| `lock_service` | Prevent deletion | POST /services/{id}/lock |
| `unlock_service` | Allow deletion | POST /services/{id}/unlock |
| `get_service_logs` | Get bootstrap logs | GET /services/{id}/logs |
| `get_service_env` | Get env vault status | GET /services/{id}/env |
| `set_service_env` | Set environment vars | PUT /services/{id}/env |
| `delete_service_env` | Delete env vars | DELETE /services/{id}/env |
| `export_service_env` | Export decrypted env | POST /services/{id}/env/export |
| `redeploy_service` | Re-run bootstrap | POST /services/{id}/redeploy |
| `execute_in_service` | Run command in service | POST /services/{id}/execute |
### Snapshots (8 functions)
| Function | Description | Endpoint |
|----------|-------------|----------|
| `list_snapshots` | List all snapshots | GET /snapshots |
| `get_snapshot` | Get snapshot details | GET /snapshots/{id} |
| `delete_snapshot` | Delete snapshot | DELETE /snapshots/{id} |
| `session_snapshot` | Snapshot a session | POST /sessions/{id}/snapshot |
| `service_snapshot` | Snapshot a service | POST /services/{id}/snapshot |
| `restore_snapshot` | Restore from snapshot | POST /snapshots/{id}/restore |
| `lock_snapshot` | Prevent deletion | POST /snapshots/{id}/lock |
| `unlock_snapshot` | Allow deletion | POST /snapshots/{id}/unlock |
| `clone_snapshot` | Clone snapshot | POST /snapshots/{id}/clone |
### Utilities (4 functions)
| Function | Description | Endpoint |
|----------|-------------|----------|
| `get_languages` | Get supported languages | GET /languages (cached 1hr) |
| `detect_language` | Detect from filename | Local (no API call) |
| `validate_keys` | Validate API credentials | POST /keys/validate |
| `image` | Generate AI images | POST /image |
## Authentication
### 4-Tier Credential Resolution
All SDKs resolve credentials in this priority order:
1. **Function arguments** (highest priority)
```python
result = execute_code("python", code, public_key="pk-xxx", secret_key="sk-xxx")
```
2. **Environment variables**
```bash
export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx"
export UNSANDBOX_SECRET_KEY="unsb-sk-xxxx"
```
3. **Home directory config**
```
~/.unsandbox/accounts.csv
Format: public_key,secret_key (one per line)
```
4. **Local directory config**
```
./accounts.csv
Format: public_key,secret_key (one per line)
```
### HMAC-SHA256 Request Signing
Every API request includes:
```
Authorization: Bearer <public_key>
X-Timestamp: <unix_seconds>
X-Signature: HMAC-SHA256(secret_key, "timestamp:METHOD:path:body")
```
Example signature message:
```
1704067200:POST:/execute:{"language":"python","code":"print(1)"}
```
## Caching
### Languages Cache
All SDKs cache the `/languages` response:
- **Location**: `~/.unsandbox/languages.json`
- **TTL**: 1 hour (3600 seconds)
- **Behavior**: Check cache freshness before API call
## Line Count Comparison
### Why un.c is 6,354 lines vs Python's 1,714 lines
The reference C implementation includes infrastructure that high-level languages get from standard libraries:
| Component | un.c (lines) | Python | Notes |
|-----------|--------------|--------|-------|
| **API Functions** | ~2,500 | ~1,500 | Similar complexity |
| **CLI main()** | 1,306 | 0 | SDK is library-only |
| **CLI help/usage** | 154 | 0 | No CLI in SDK |
| **HTTP client** | 574 | 0 | `requests` library |
| **JSON parsing** | ~200 | 0 | `json` module |
| **HMAC crypto** | ~100 | 0 | `hmac` module |
| **Memory management** | ~300 | 0 | Garbage collected |
| **String utilities** | ~200 | 0 | Built-in |
| **Total** | **6,354** | **1,714** | 3.7x difference |
### What Python Gets "For Free"
```python
import requests # Replaces ~574 lines of curl code
import json # Replaces ~200 lines of JSON parsing
import hmac # Replaces ~100 lines of crypto
import hashlib # Replaces SHA-256 implementation
```
### Feature Parity
Despite the line count difference, all SDKs implement:
- ✅ All 43 API functions
- ✅ 4-tier credential resolution
- ✅ HMAC-SHA256 request signing
- ✅ 1-hour languages caching
- ✅ Exponential backoff polling
- ✅ Proper error handling
The C implementation additionally includes:
- Full CLI with argument parsing
- Interactive shell support (WebSocket)
- Output formatting and display
- File input handling
## SDK Size Summary
| Language | Sync | Async | Total | Notes |
|----------|------|-------|-------|-------|
| Python | 1,714 | 1,701 | 3,415 | requests/aiohttp |
| JavaScript | 1,131 | 1,209 | 2,340 | https/fetch |
| Go | 1,080 | 1,642 | 2,722 | net/http + goroutines |
| Java | 1,856 | 1,849 | 3,705 | HttpURLConnection |
| Ruby | 1,264 | 1,543 | 2,807 | net/http + Future |
| Rust | 1,856 | 1,949 | 3,805 | reqwest + tokio |
| PHP | 1,403 | 1,346 | 2,749 | cURL + Guzzle |
| **Total** | | | **21,543** | |
Reference: `un.c` = 6,354 lines (includes CLI)
## Usage Examples
### Python (Sync)
```python
from un import execute_code, list_services, image
# Execute code
result = execute_code("python", 'print("Hello, World!")')
print(result["stdout"])
# List services
services = list_services()
for svc in services:
print(f"{svc['name']}: {svc['status']}")
# Generate AI image
img = image("A sunset over mountains")
print(img["images"][0])
```
### Python (Async)
```python
import asyncio
from un_async import execute_code, list_services
async def main():
result = await execute_code("python", 'print("Hello!")')
print(result["stdout"])
asyncio.run(main())
```
### JavaScript (Sync)
```javascript
const un = require('./un');
const result = un.executeCode("javascript", 'console.log("Hello!")');
console.log(result.stdout);
```
### Go
```go
import "un"
func main() {
creds, _ := un.ResolveCredentials("", "")
result, _ := un.ExecuteCode(creds, "python", `print("Hello")`)
fmt.Println(result.Stdout)
}
```
### Rust
```rust
use un::{execute_code, resolve_credentials};
fn main() -> Result<()> {
let creds = resolve_credentials(None, None)?;
let result = execute_code("python", r#"print("Hello")"#, &creds)?;
println!("{}", result.output);
Ok(())
}
```
## Error Handling
All SDKs define these error types:
| Error | Description |
|-------|-------------|
| `CredentialsError` | No credentials found or invalid |
| `APIError` | API returned error response |
| `TimeoutError` | Job polling exceeded timeout |
| `NetworkError` | Connection failed |
## Contributing
When adding new API endpoints:
1. Update all 14 SDK files (7 languages × 2 variants)
2. Follow existing patterns for authentication and error handling
3. Add proper documentation (docstrings/comments)
4. Test with the SDK test framework
## License
PUBLIC DOMAIN - No license, no warranty.
Part of the permacomputer project: https://permacomputer.com