Metadata-Version: 2.4
Name: omicslab
Version: 1.5.0
Summary: Python SDK and CLI for the OmicsLab Platform
Project-URL: Homepage, https://platform.omicslab.io
Project-URL: Repository, https://github.com/vieomics/omicslab-platform
Author: OmicsLab Platform Team
License-Expression: GPL-3.0
Keywords: bioinformatics,cli,hpc,omics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.12
Requires-Dist: aiohttp>=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: jinja2>=3
Requires-Dist: psutil>=6
Requires-Dist: pydantic>=2
Requires-Dist: python-dotenv>=1
Requires-Dist: questionary>=2.1
Requires-Dist: rich>=13
Requires-Dist: typer>=0.15
Requires-Dist: websocket-client>=1.8
Requires-Dist: websockets>=13
Description-Content-Type: text/markdown

# OmicsLab SDK

Python SDK and CLI for the **OmicsLab Platform**.

- **CLI**: `omicslab` (alias `omx`)
- **Python SDK**: `omicslab.Client`

Full documentation at **[docs.omicslab.io](https://docs.omicslab.io)**.

```bash
pip install omicslab
```

## Quick Start

```bash
# 1. Authenticate
omicslab auth login --token omx_abc123...

# 2. Set context
omicslab use

# 3. Navigate storage
omicslab ls && omicslab upload ./data.csv

# 4. Launch a job
omicslab jobs launch --workspace <ws_id> --analysis <id> --compute <id>
```

## Storage Commands

### Upload

Upload files or directories to workspace storage. Directories are uploaded concurrently with automatic batch presigned URL resolution.

```bash
# Single file (key defaults to filename)
omicslab upload ./data.csv

# With explicit remote key
omicslab upload ./data.csv results/run1/data.csv

# Upload to an s3:// path (auto-resolves workspace)
omicslab upload ./data.csv s3://my-bucket/data/results/

# Upload directory recursively (auto-detected, explicit --recursive/-r also accepted)
omicslab upload -r ./outputs/ results/

# Upload directory with custom thread count
omicslab upload -r ./outputs/ results/ --threads 8

# Upload with confirmation skip
omicslab upload -y ./data.csv s3://my-bucket/data/
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--recursive`, `-r` | Upload directory recursively (auto-detected; errors if used with a file) |
| `--threads` | Concurrent upload threads (default: 4) |
| `--workspace-id`, `-w` | Workspace ID (inferred from s3:// path if provided) |
| `--yes`, `-y` | Skip confirmation prompt for s3:// path resolution |

**Directory upload** walks the source tree, batches presigned URL requests (up to 500 files per batch via the backend `/data/upload-batch/` endpoint), and uploads all files concurrently.

### Download

Download files or directories from workspace storage. Recursive downloads preserve subdirectory structure and use parallel threads.

```bash
# Single file (defaults to filename in current directory)
omicslab download results/run1/data.csv

# Single file with explicit destination
omicslab download results/run1/data.csv ./local_copy.csv

# Download from s3:// path (auto-resolves workspace)
omicslab download s3://my-bucket/data/results/report.html

# Recursive directory download (preserves subdirectory structure)
omicslab download -r s3://my-bucket/data/results/ ./local_results/

# Recursive download with custom thread count
omicslab download -r s3://my-bucket/data/results/ ./local_results/ --threads 8

# Recursive download with confirmation skip
omicslab download -y -r s3://my-bucket/data/results/ ./local_results/
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--recursive`, `-r` | Download all files under an s3:// directory prefix |
| `--threads` | Concurrent download threads (default: 4) |
| `--workspace-id`, `-w` | Workspace ID (inferred from s3:// path if provided) |
| `--yes`, `-y` | Skip confirmation prompt for s3:// path resolution |

**Recursive download** lists all objects under the prefix, then downloads them in parallel while preserving the original subdirectory structure under the destination directory.

## Environment Variables

| Variable | Purpose |
|---|---|
| `OMICSLAB_TOKEN` | API token (overrides config file) |
| `OMICSLAB_BASE_URL` | API base URL (default: `https://platform.omicslab.io/api`) |

## Jobs API

Analysis and studio jobs share one backend namespace:
`/workspaces/{workspace_id}/jobs/...` — `job_type` ("analysis" | "studio")
is part of the launch payload / list filter, not a separate URL space.
`client.jobs` exposes generic methods (`launch`, `list_jobs`, `get_job`,
`get_job_manifest`, `terminate_job`, `delete_job`, `connect_job`,
`disconnect_job`, `check_job_ready`, ...) plus the domain aliases
(`launch_analysis`, `launch_studio`, `list_analysis`, `list_studio`, ...)
for convenience. Job resources (`time`/`cpu`/`memory`/`disk`) and the
launch config live in the per-job manifest on S3, retrievable via
`get_job_manifest` / `get_job_audit_params` / `get_job_audit_config`.

```python
from omicslab import Client

client = Client(token="omx_...", base_url="https://platform.omicslab.io/api")

# Launch an analysis job
job = client.jobs.launch_analysis(
    workspace_id="ws-...",
    analysis_id="ana-...",
    compute_id="comp-...",
    tag="v1.0.0",
    params={"input": "s3://bucket/data/sample.csv"},
)
job_id = job["id"]

# Resolved launch manifest (config + resources + audit payload)
manifest = client.jobs.get_job_manifest("ws-...", job_id)

# Studio sessions: connect is available once the job is RUNNING
studio = client.jobs.launch_studio(
    workspace_id="ws-...",
    params={"runtime": {"image": "rocker/rstudio"}, "services": [...]},
    compute_id="cloud-comp-...",
)
access = client.jobs.connect_job("ws-...", studio["id"])  # {"access_url": ...}
```

## Testing

The e2e suites (SDK, frontend, backend) run against a shared test infra started
with `make start-test-e2e-infra` (test-db, redis, S3 at `:4566`, SLURM).
The SDK wheel is built and uploaded to the S3 `omicslab` bucket as
`s3://omicslab/data/tools/<version>.whl` plus the stable
`s3://omicslab/data/tools/omicslab-latest.whl` alias so runner/cloud jobs can
install it.

On the self-hosted CI runner the S3 volume is **kept between runs**; only
non-`omicslab` buckets are cleaned at startup. The frontend E2E job therefore
skips rebuilding/re-uploading the wheel (`SKIP_SDK_UPLOAD=1`) whenever
`sdk/**` and the root `Makefile` are unchanged — the wheel from the last
SDK-touching run is reused. To force a rebuild + upload locally:

```bash
make SKIP_SDK_UPLOAD=0 S3_ENDPOINT_URL=http://localhost:4566 S3_REGION=us-east-1 upload-bootstrap-env
```

## Runner & CLI hardening (2026-09)

- Runner reaps terminal jobs so the heartbeat returns to idle (no more stuck BUSY).
- SLURM sbatch wrapper sets --job-name matching daemon-restart discovery.
- `omicslab auth whoami` calls the correct check_access_token path.
- `runner exec` no longer deletes the user-provided --params-file.
