Metadata-Version: 2.4
Name: miosa-modal-shim
Version: 0.1.0
Summary: Drop-in replacement for the Modal Python SDK, backed by MIOSA compute
Project-URL: Homepage, https://miosa.ai
Project-URL: Documentation, https://docs.miosa.ai/sdk/python
Project-URL: Repository, https://github.com/miosa-ai/miosa
Author-email: MIOSA <dev@miosa.ai>
License-Expression: MIT
Keywords: compatibility,compute,gpu,miosa,modal,serverless,shim
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: miosa-sandbox>=0.1.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# miosa-modal-shim

Drop-in replacement for the [Modal](https://modal.com) Python SDK that routes
all compute to [MIOSA](https://miosa.ai) instead. Existing Modal scripts run
on MIOSA **with zero code changes**.

## Installation

```bash
# Replace modal with the MIOSA shim
pip uninstall modal
pip install miosa-modal-shim
```

The package installs a `modal` Python module that shadows the real Modal SDK.
All `import modal` statements resolve to this shim.

## Configuration

Set your MIOSA API key:

```bash
export MIOSA_API_KEY="mki_..."
```

The shim also reads `MODAL_TOKEN_ID` as a fallback, so existing CI
configurations that set Modal credentials continue to work after you swap
the key value.

## Usage

Your existing Modal code works unchanged:

```python
import modal

app = modal.App("my-app")

@app.function(gpu="any", image=modal.Image.debian_slim().pip_install("torch"))
def train(data):
    import torch
    return torch.tensor(data).sum().item()

# Runs on a MIOSA sandbox with a GPU
result = train.remote(data=[1, 2, 3])
print(result)  # 6.0
```

### Execution modes

| Method | Where it runs |
|--------|---------------|
| `fn.local(...)` | Current process, no sandbox |
| `fn(...)` | Same as `local` |
| `fn.remote(...)` | MIOSA sandbox (ephemeral VM) |
| `fn.map(iter1, iter2)` | Parallel MIOSA sandboxes (up to 10 concurrent) |

### Image builder

```python
image = (
    modal.Image.debian_slim(python_version="3.11")
    .apt_install("git", "ffmpeg")
    .pip_install("torch", "transformers")
    .run_commands("echo 'setup done'")
)
```

### Secrets

```python
# From explicit dict
secret = modal.Secret.from_dict({"HF_TOKEN": "hf_..."})

# From environment (reads MYAPP_* env vars)
secret = modal.Secret.from_name("myapp")

@app.function(secrets=[secret])
def inference():
    ...
```

### Volumes

```python
vol = modal.Volume.from_name("training-data", create_if_missing=True)

@app.function(volumes={"/data": vol})
def process():
    ...
```

Volumes provide API compatibility. Persistent cross-sandbox storage is on the
roadmap.

## What is supported

| Feature | Status |
|---------|--------|
| `modal.App` / `modal.Stub` | Fully supported |
| `@app.function()` | Fully supported |
| `@app.cls()` | Construction only |
| `modal.Image` (debian_slim, from_registry, pip/apt/run_commands) | Fully supported |
| `modal.Volume` | API-compatible stub |
| `modal.Secret` (from_name, from_dict) | Fully supported |
| `function.remote()` | Fully supported |
| `function.local()` | Fully supported |
| `function.map()` | Fully supported |
| GPU selection (T4, L4, A10G, A100, H100, L40S) | Fully supported |

## Not yet supported

- `modal.web_endpoint` / `modal.asgi_app` / `modal.wsgi_app`
- `modal.Cron`
- `modal.Dict` / `modal.Queue`
- Class method-level `.remote()` dispatch

## License

MIT
