Metadata-Version: 2.5
Name: singularity-grid
Version: 0.9.1
Summary: Python SDK for the SGL Network confidential compute grid (end-to-end encrypted + streaming)
Project-URL: Homepage, https://singularitylayer.xyz
Project-URL: Repository, https://github.com/Singularity-Layer/sgl-network-sdk
Project-URL: Documentation, https://docs.singularitylayer.xyz/sdk
Author-email: Singularity Layer <dev@singularitylayer.xyz>
License-Expression: MIT
License-File: LICENSE
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.9
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 :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: base58>=2.1
Requires-Dist: cryptography>=42.0
Requires-Dist: httpx>=0.24
Requires-Dist: pydantic>=2.0
Requires-Dist: pynacl>=1.5
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Description-Content-Type: text/markdown

# singularity-grid

Python SDK for the SGL Network confidential compute grid. Submit inference jobs to TEE-verified nodes, check grid capacity, and use the OpenAI-compatible chat completions endpoint -- all from a single package.

## Installation

```bash
pip install singularity-grid
```

To use the OpenAI compatibility helper:

```bash
pip install singularity-grid[openai]
```

## Quick start

### 1. OpenAI-compatible usage (simplest)

The SGL Network orchestrator exposes an OpenAI-compatible `/v1/chat/completions` endpoint. You can use the standard `openai` package with no wrapper:

```python
from openai import OpenAI

client = OpenAI(
    base_url="https://grid.x402compute.cc/v1",
    api_key="scg_your_api_key",
)

response = client.chat.completions.create(
    model="gemma-4-26b",
    messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)
```

### 2. Helper function

If you prefer not to copy the URL, use the built-in helper:

```python
from singularity_grid import create_openai_client

client = create_openai_client(api_key="scg_your_api_key")

response = client.chat.completions.create(
    model="gemma-4-26b",
    messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)
```

### 3. GridClient (full grid features)

For grid-specific features like job submission, TEE attestation, capacity checks, and pricing:

```python
from singularity_grid import GridClient

# Public endpoints -- no auth required
grid = GridClient()
capacity = grid.capacity()
models = grid.models()
pricing = grid.pricing()

print(f"Active nodes: {capacity.active_nodes}/{capacity.total_nodes}")
for m in models:
    print(f"  {m.id} -- {m.sgl_node_count} nodes")

# Authenticated endpoints
grid = GridClient(api_key="scg_your_api_key")

job = grid.submit_job(
    model="gemma-4-26b",
    input_payload={
        "messages": [{"role": "user", "content": "Analyze this data"}]
    },
    submitter_wallet="0xYourWallet",
    submitter_chain="base",
)

print(f"Job {job.job_id}: {job.status}")

# Retrieve result and attestation
result = grid.get_job(job.job_id)
attestation = grid.get_attestation(job.job_id)
print(f"TEE verified: {attestation.verified}")
```

## API reference

### GridClient

| Method | Auth | Description |
|---|---|---|
| `capacity()` | No | Grid-wide capacity summary |
| `models()` | No | Available models with pricing and TEE info |
| `pricing()` | No | Pricing table for all models |
| `submit_job(model, input_payload, ...)` | Yes | Submit a compute job |
| `get_job(job_id)` | Yes | Get job status and result |
| `get_attestation(job_id)` | Yes | Get TEE attestation proof |

### Exceptions

| Exception | When |
|---|---|
| `SGLError` | Base class for all SDK errors |
| `SGLAPIError` | Non-2xx response from the API |
| `SGLAuthError` | 401 or 403 response |
| `SGLNotFoundError` | 404 response |
| `SGLConnectionError` | Orchestrator unreachable or timeout |

### Configuration

| Parameter | Default | Description |
|---|---|---|
| `api_key` | `None` | Bearer token for authenticated endpoints |
| `base_url` | orchestrator URL | Override the orchestrator URL |
| `timeout` | `60.0` | Request timeout in seconds |

## License

MIT

## Processors

Processors are served by `processors.x402compute.cc`, not the grid, so they have their own client.

```python
from singularity_grid import ProcessorsClient

p = ProcessorsClient(api_key=os.environ["SGL_API_KEY"])

p.catalogue()                          # public, no credential
p.list()                               # yours          (processors:read)
p.deploy(manifest, code)               # returns the invoke token ONCE
p.update("my-processor", code=code)
p.set_listing("my-processor", True)
p.run("my-processor", {"name": "world"}, invoke_token)
```

> **`processors:write` is full control** of processors owned by that key's wallet — delete and
> secrets included, the same as a Cloudflare API token. Mint `processors:read` if you want a
> credential that cannot change anything. Note that compute keys do not expire, there is no audit
> log, and **delete is permanent**: the code is wiped and the slug is burned forever.

`run()` takes the **invoke token** from `deploy()`, not the API key — the run route is the only one
with both a money path and an anonymous buyer lane, so it does not read a key as an ownership
claim. Buyers use `run_with_payment()` with an x402 header instead.

### Upgrading from 0.8.x

The six processor methods on `GridClient` (`deploy_processor`, `invoke_processor`,
`list_processors`, `get_processor`, `delete_processor`, `get_processor_logs`) are **removed**, along
with the `Processor*` models. They pointed at `/grid/processors`, which has never existed — every
call returned 404 — and their models described an older design that was never shipped. Use
`ProcessorsClient`. Nothing else changed: chat, embeddings, jobs, models, capacity, pricing,
reserve and the vault are untouched.
