Metadata-Version: 2.4
Name: ai-forge-sdk
Version: 0.2.1
Summary: Python SDK for the AI Forge Control Plane API
Project-URL: Homepage, https://github.com/onstak/ai-forge-sdk-python
Project-URL: Documentation, https://github.com/onstak/ai-forge-sdk-python#readme
Project-URL: Repository, https://github.com/onstak/ai-forge-sdk-python
Project-URL: Issues, https://github.com/onstak/ai-forge-sdk-python/issues
Author-email: OnStak <engineering@onstak.com>
License-Expression: MIT
License-File: LICENSE
Keywords: ai-forge,cloud,iaas,kubernetes,mlops,sdk
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: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.7
Requires-Dist: pydantic[email]<3.0,>=2.7
Requires-Dist: typing-extensions>=4.10; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.25; extra == 'docs'
Description-Content-Type: text/markdown

# AI Forge Python SDK

Python SDK for the **AI Forge Control Plane API**.

The SDK provides a typed, developer-friendly wrapper around AI Forge REST APIs for organizations, workspaces, connectors, service catalog, compute, storage, IAM, and long-running operations.

> Package name: `ai-forge-sdk`  
> Import name: `ai_forge`  
> CLI command: `ai-forge`

---

## 1. Prerequisites

Install the following on your development machine:

- Python `3.10` or later
- Git
- `make` optional, but recommended
- A virtual environment tool such as `venv`
- AI Forge API URL and credentials

Check Python version:

```bash
python --version
```

Expected:

```bash
Python 3.10+
```

---

## 2. Clone the Repository

```bash
git clone https://github.com/onstak/ai-forge-sdk-python.git
cd ai-forge-sdk-python
```

If you are using the generated template locally:

```bash
cd ai-forge-python-sdk-template
```

---

## 3. Create and Activate Virtual Environment

### Linux / macOS

```bash
python -m venv .venv
source .venv/bin/activate
```

### Windows PowerShell

```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
```

### Windows CMD

```cmd
python -m venv .venv
.\.venv\Scripts\activate.bat
```

Upgrade pip:

```bash
python -m pip install --upgrade pip
```

---

## 4. Install SDK for Local Development

Install the package in editable mode with development dependencies:

```bash
pip install -e ".[dev]"
```

This installs:

- SDK runtime dependencies
- test tools
- lint tools
- type-checking tools
- build/publish tools

Verify package import:

```bash
python -c "import ai_forge; print(ai_forge.__version__)"
```

Verify CLI:

```bash
ai-forge --version
```

---

## 5. Environment Configuration

Create a local `.env` file from the example file:

```bash
cp .env.example .env
```

Update `.env`:

```env
AI_FORGE_BASE_URL=https://api.ai-forge.example.com
AI_FORGE_API_KEY=replace-with-api-key
AI_FORGE_BEARER_TOKEN=
AI_FORGE_TENANT_ID=replace-with-tenant-id
AI_FORGE_WORKSPACE_ID=replace-with-workspace-id
AI_FORGE_TIMEOUT_SECONDS=30
AI_FORGE_MAX_RETRIES=3
```

### Required Variables

| Variable | Required | Description |
|---|---:|---|
| `AI_FORGE_BASE_URL` | Yes | Base URL of the AI Forge API Gateway |
| `AI_FORGE_API_KEY` | Recommended | API key for SDK authentication |
| `AI_FORGE_BEARER_TOKEN` | Optional | OAuth/OIDC bearer token. Takes priority over API key if set |
| `AI_FORGE_TENANT_ID` | Optional | Tenant scope header |
| `AI_FORGE_WORKSPACE_ID` | Optional | Workspace scope header |
| `AI_FORGE_TIMEOUT_SECONDS` | Optional | HTTP timeout. Default is `30` |
| `AI_FORGE_MAX_RETRIES` | Optional | Retry count for transient errors. Default is `3` |

> Do not commit `.env` to Git.

To load `.env` variables manually in Linux/macOS:

```bash
set -a
source .env
set +a
```

In Windows PowerShell:

```powershell
$env:AI_FORGE_BASE_URL="https://api.ai-forge.example.com"
$env:AI_FORGE_API_KEY="replace-with-api-key"
$env:AI_FORGE_TENANT_ID="replace-with-tenant-id"
$env:AI_FORGE_WORKSPACE_ID="replace-with-workspace-id"
```

---

## 6. Basic SDK Usage

```python
from ai_forge import AIForgeClient

with AIForgeClient.from_env() as client:
    workspaces = client.workspaces.list()

    for workspace in workspaces.items:
        print(workspace.id, workspace.name, workspace.status)
```

Run:

```bash
python examples/list_workspaces.py
```

---

## 7. Create a Client Manually

Use this when you do not want to rely on environment variables:

```python
from ai_forge import AIForgeClient, AIForgeConfig

config = AIForgeConfig(
    base_url="https://api.ai-forge.example.com",
    api_key="replace-with-api-key",
    tenant_id="tenant-uuid",
    workspace_id="workspace-uuid",
    timeout_seconds=30,
    max_retries=3,
)

with AIForgeClient(config) as client:
    catalog_items = client.service_catalog.list()
    print(catalog_items.items)
```

---

## 8. CLI Usage

Show version:

```bash
ai-forge --version
```

List workspaces:

```bash
ai-forge workspaces
```

List service catalog items:

```bash
ai-forge catalog
```

The CLI reads configuration from the same environment variables used by `AIForgeClient.from_env()`.

---

## 9. Resource Examples

### 9.1 List Workspaces

```python
from ai_forge import AIForgeClient

with AIForgeClient.from_env() as client:
    page = client.workspaces.list(limit=50)

    for workspace in page.items:
        print(workspace.id, workspace.name)
```

### 9.2 Create a Workspace

```python
from ai_forge import AIForgeClient
from ai_forge.models import CreateWorkspaceRequest

request = CreateWorkspaceRequest(
    name="demo-workspace",
    organizationId="organization-uuid",
)

with AIForgeClient.from_env() as client:
    workspace = client.workspaces.create(
        request,
        idempotency_key="create-workspace-demo-001",
    )
    print(workspace.id)
```

### 9.3 List Connectors

```python
from ai_forge import AIForgeClient

workspace_id = "workspace-uuid"

with AIForgeClient.from_env() as client:
    connectors = client.connectors.list(workspace_id)

    for connector in connectors.items:
        print(connector.id, connector.name, connector.connector_type, connector.status)
```

### 9.4 Create a Connector

```python
from ai_forge import AIForgeClient
from ai_forge.models import CreateConnectorRequest

workspace_id = "workspace-uuid"

request = CreateConnectorRequest(
    name="openshift-prod",
    connectorType="openshift",
    endpoint="https://api.openshift.example.com:6443",
    credentialsRef="vault://tenants/demo/workspaces/main/connectors/openshift-prod",
    config={
        "watchNamespaces": ["default", "apps"],
        "enableMetrics": True,
    },
)

with AIForgeClient.from_env() as client:
    operation = client.connectors.create(
        workspace_id,
        request,
        idempotency_key="create-connector-openshift-prod-001",
    )
    print(operation.id, operation.status)
```

### 9.5 Create a VM

```python
from ai_forge import AIForgeClient

workspace_id = "workspace-uuid"

with AIForgeClient.from_env() as client:
    operation = client.compute.create_vm(
        workspace_id,
        name="demo-vm-01",
        instance_type="standard-2c-8g",
        image="ubuntu-22.04",
        disk_gb=80,
        idempotency_key="create-demo-vm-01",
    )

    print(operation.id, operation.status)
```

### 9.6 Wait for a Long-Running Operation

```python
from ai_forge import AIForgeClient

operation_id = "operation-uuid"

with AIForgeClient.from_env() as client:
    result = client.operations.wait(
        operation_id,
        timeout_seconds=600,
        poll_interval_seconds=5,
    )

    print(result.status)
```

### 9.7 Create an Object Storage Bucket

```python
from ai_forge import AIForgeClient

workspace_id = "workspace-uuid"

with AIForgeClient.from_env() as client:
    operation = client.storage.create_bucket(
        workspace_id,
        name="ml-datasets",
        region="us-east-1",
        versioning_enabled=True,
        encrypted=True,
        idempotency_key="create-bucket-ml-datasets-001",
    )

    print(operation.id, operation.status)
```

---

## 10. Run Tests

Run all tests:

```bash
pytest
```

Run tests with coverage:

```bash
pytest --cov=ai_forge --cov-report=term-missing
```

Run one test file:

```bash
pytest tests/test_client.py
```

Run one test case:

```bash
pytest tests/test_client.py::test_client_lists_workspaces
```

Using Makefile:

```bash
make test
```

---

## 11. Lint, Format, and Type Check

Format code:

```bash
ruff format src tests
```

Auto-fix lint issues:

```bash
ruff check --fix src tests
```

Check lint only:

```bash
ruff check src tests
```

Run type checking:

```bash
mypy src
```

Using Makefile:

```bash
make format
make lint
```

---

## 12. Pre-commit Hooks

Install pre-commit hooks:

```bash
pre-commit install
```

Run hooks manually:

```bash
pre-commit run --all-files
```

---

## 13. Build the Package

Clean old build artifacts:

```bash
rm -rf dist build *.egg-info src/*.egg-info
```

Build source distribution and wheel:

```bash
python -m build
```

Validate package metadata:

```bash
python -m twine check dist/*
```

Using Makefile:

```bash
make build
```

Expected output:

```text
dist/ai_forge_sdk-<version>.tar.gz
dist/ai_forge_sdk-<version>-py3-none-any.whl
```

---

## 14. Test the Built Wheel Locally

Create a clean temporary environment:

```bash
python -m venv /tmp/ai-forge-sdk-test
source /tmp/ai-forge-sdk-test/bin/activate
python -m pip install --upgrade pip
```

Install the built wheel:

```bash
pip install dist/*.whl
```

Verify import:

```bash
python -c "from ai_forge import AIForgeClient; print(AIForgeClient)"
```

Verify CLI:

```bash
ai-forge --version
```

Deactivate:

```bash
deactivate
```

---

## 15. Generate Documentation Locally

Install documentation dependencies:

```bash
pip install -e ".[docs]"
```

Serve docs locally:

```bash
mkdocs serve
```

Open:

```text
http://127.0.0.1:8000
```

Build static docs:

```bash
mkdocs build
```

---

## 16. Publish to TestPyPI

Build first:

```bash
make build
```

Upload to TestPyPI:

```bash
python -m twine upload --repository testpypi dist/*
```

Using Makefile:

```bash
make publish-test
```

Install from TestPyPI in a clean environment:

```bash
python -m venv /tmp/ai-forge-testpypi
source /tmp/ai-forge-testpypi/bin/activate
python -m pip install --upgrade pip
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple ai-forge-sdk
```

Verify:

```bash
python -c "import ai_forge; print(ai_forge.__version__)"
```

---

## 17. Publish to PyPI

Only publish to PyPI after validating the package on TestPyPI.

```bash
make build
python -m twine upload dist/*
```

Using Makefile:

```bash
make publish
```

Install from PyPI:

```bash
pip install ai-forge-sdk
```

---

## 18. Versioning

The package version is stored in:

```text
src/ai_forge/__about__.py
```

Example:

```python
__version__ = "0.1.0"
```

Recommended versioning strategy:

```text
0.1.0   Initial alpha SDK
0.2.0   New resources or non-breaking features
0.2.1   Bug fixes
1.0.0   Stable public SDK contract
```

Update version before every release:

```bash
sed -i 's/__version__ = "0.1.0"/__version__ = "0.2.0"/' src/ai_forge/__about__.py
```

On macOS:

```bash
sed -i '' 's/__version__ = "0.1.0"/__version__ = "0.2.0"/' src/ai_forge/__about__.py
```

---

## 19. GitHub Actions

The template includes GitHub Actions workflows:

```text
.github/workflows/ci.yml
.github/workflows/publish.yml
```

### CI Workflow

Runs automatically on pull requests and pushes.

Typical checks:

- Install package
- Lint
- Type check
- Run tests

### Publish Workflow

Publishes the package when a release tag is created.

Recommended tag format:

```bash
git tag v0.1.0
git push origin v0.1.0
```

### Required GitHub Secret

Add this repository secret in GitHub:

```text
PYPI_API_TOKEN
```

Use a PyPI API token, not your PyPI password.

---

## 20. Project Structure

```text
.
├── pyproject.toml
├── README.md
├── LICENSE
├── Makefile
├── .env.example
├── src/
│   └── ai_forge/
│       ├── __init__.py
│       ├── __about__.py
│       ├── auth.py
│       ├── client.py
│       ├── config.py
│       ├── exceptions.py
│       ├── pagination.py
│       ├── transport.py
│       ├── cli.py
│       ├── models/
│       └── resources/
├── tests/
├── examples/
├── docs/
└── .github/workflows/
```

### Important Files

| File | Purpose |
|---|---|
| `pyproject.toml` | Python package metadata, dependencies, build config |
| `src/ai_forge/client.py` | Main SDK client |
| `src/ai_forge/config.py` | Runtime config and environment loading |
| `src/ai_forge/transport.py` | HTTP transport, retries, headers, error handling |
| `src/ai_forge/auth.py` | API key / bearer token auth providers |
| `src/ai_forge/resources/` | API resource clients |
| `src/ai_forge/models/` | Pydantic request/response models |
| `tests/` | Unit tests |
| `examples/` | Usage examples |
| `docs/` | MkDocs documentation |

---

## 21. Development Workflow

Recommended daily workflow:

```bash
source .venv/bin/activate
pip install -e ".[dev]"
make format
make lint
make test
```

Before opening a pull request:

```bash
make format
make lint
make test
make build
```

Before releasing:

```bash
rm -rf dist build *.egg-info src/*.egg-info
make lint
make test
make build
python -m twine check dist/*
```

---

## 22. Error Handling

```python
from ai_forge import AIForgeClient
from ai_forge.exceptions import AIForgeAPIError, AIForgeAuthenticationError, AIForgeRateLimitError

try:
    with AIForgeClient.from_env() as client:
        workspaces = client.workspaces.list()
except AIForgeAuthenticationError:
    print("Invalid or expired AI Forge credentials")
except AIForgeRateLimitError:
    print("Rate limit exceeded. Retry later")
except AIForgeAPIError as exc:
    print(exc.message)
    print(exc.error_code)
    print(exc.details)
```

---

## 23. Pagination Pattern

```python
from ai_forge import AIForgeClient

with AIForgeClient.from_env() as client:
    cursor = None

    while True:
        page = client.workspaces.list(cursor=cursor, limit=100)

        for workspace in page.items:
            print(workspace.id, workspace.name)

        if not page.next_cursor:
            break

        cursor = page.next_cursor
```

---

## 24. Idempotency Pattern

Use idempotency keys for create/update operations that may be retried safely:

```python
operation = client.compute.create_vm(
    workspace_id="workspace-uuid",
    name="demo-vm-01",
    instance_type="standard-2c-8g",
    image="ubuntu-22.04",
    disk_gb=80,
    idempotency_key="create-demo-vm-01",
)
```

---

## 25. Troubleshooting

### `Required environment variable is missing: AI_FORGE_BASE_URL`

Set the base URL:

```bash
export AI_FORGE_BASE_URL="https://api.ai-forge.example.com"
```

### `401 Unauthorized`

Check that one of these is valid:

```bash
export AI_FORGE_API_KEY="your-api-key"
# or
export AI_FORGE_BEARER_TOKEN="your-oauth-token"
```

### `403 Forbidden`

The token is valid, but the user/service account does not have permission for the target tenant, workspace, or resource.

### `429 Too Many Requests`

The AI Forge API Gateway rate limit was reached. Increase backoff, reduce concurrency, or request a quota increase.

### `ModuleNotFoundError: No module named 'ai_forge'`

Install the SDK locally:

```bash
pip install -e ".[dev]"
```

### `mypy` fails after adding new models

Make sure all fields are typed and Pydantic aliases are declared correctly:

```python
from pydantic import Field

workspace_id: str = Field(alias="workspaceId")
```

---

## 26. Release Checklist

Before every release:

- [ ] Update `src/ai_forge/__about__.py`
- [ ] Update `CHANGELOG.md` if available
- [ ] Run `make format`
- [ ] Run `make lint`
- [ ] Run `make test`
- [ ] Run `make build`
- [ ] Install wheel in a clean virtual environment
- [ ] Publish to TestPyPI
- [ ] Install from TestPyPI
- [ ] Publish to PyPI
- [ ] Create GitHub release tag

---

## 27. License

MIT License. See `LICENSE`.
