Metadata-Version: 2.4
Name: afa-client
Version: 0.2.0
Summary: Python client for the AFA API -- autonomous code evolution with 9 quantitative gates
Project-URL: Homepage, https://afa.undercurrentholdings.com
Project-URL: Documentation, https://afa.undercurrentholdings.com
Project-URL: Portal, https://portal.veiltide.com
Author-email: Undercurrent Holdings <engineering@veiltide.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: ai,automation,code-analysis,code-quality,enhancement,gates
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software 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 :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx[http2]>=0.27
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# AFA Client SDK

Python client for the [AFA](https://afa.undercurrentholdings.com) REST API: autonomous code evolution with 9 quantitative gates.

```bash
pip install afa-client
```

## Quick start

```python
from afa_client import AFA

client = AFA(api_key="uk_afa_...")

# Analyze code
result = client.analyze(code="def hello(name):\n    print('Hello ' + name)")
for r in result.results:
    print(r["scores"])
    for finding in r["findings"]:
        print(f"  [{finding['severity']}] {finding['message']}")

# Generate and gate-check an enhancement
enhanced = client.enhance(
    code="def hello(name):\n    print('Hello ' + name)",
    dry_run=True,
)
print(enhanced.status)  # "pass" if all 9 gates passed
```

## Async

```python
from afa_client import AsyncAFA

async with AsyncAFA(api_key="uk_afa_...") as client:
    result = await client.analyze(code="def foo(): pass")
```

## Authentication

Pass your API key directly or set it as an environment variable:

```bash
export AFA_API_KEY="uk_afa_..."
```

Get your key at [portal.veiltide.com](https://portal.veiltide.com).

## Methods

| Method | Description |
|--------|-------------|
| `analyze(code, language, depth)` | Analyze code with 4 AI agents |
| `enhance(code, language, dry_run)` | Generate enhancement + run 9 gates |
| `gate_check(metrics)` | Evaluate raw metrics against gates |
| `health()` | API health check (no auth) |
| `history(last)` | Query audit trail |
| `metrics()` | Prometheus metrics |
| `get_profile()` | Customer profile + tier |
| `get_usage(month)` | Monthly usage report |
| `list_keys()` | List API keys |
| `create_key(name)` | Create new API key |
| `revoke_key(key_id)` | Revoke an API key |

## Error handling

```python
from afa_client import AFA, RateLimitError, AuthenticationError

client = AFA()
try:
    result = client.analyze(code="def foo(): pass")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except AuthenticationError:
    print("Invalid API key")
```

## Configuration

| Parameter | Env var | Default |
|-----------|---------|---------|
| `api_key` | `AFA_API_KEY` | Required |
| `base_url` | `AFA_BASE_URL` | `https://api.afa.undercurrentholdings.com` |
| `timeout` | -- | 30s |
| `max_retries` | -- | 2 |

## Security

- TLS enforced on all non-localhost connections
- API key transmitted only in `Authorization: Bearer` header
- Key masking in all error messages and repr output
- Automatic retry with exponential backoff + jitter
- Idempotency keys on mutating requests
- HTTP/2 enabled by default

## License

Apache 2.0
