Metadata-Version: 2.4
Name: forktex-intelligence
Version: 1.5.0
Summary: Unified SDK for the ForkTex Intelligence API — one common interface for chat, vision, embeddings, extract, audio, video and any future modality
License-Expression: AGPL-3.0-only
License-File: LICENSE
License-File: NOTICE
Author: FORKTEX
Author-email: info@forktex.com
Requires-Python: >=3.12,<4.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: httpx (>=0.27.0,<1.0.0)
Requires-Dist: httpx-sse (>=0.4.0,<1.0.0)
Requires-Dist: pydantic (>=2.11.10,<3.0.0)
Project-URL: Bug Tracker, https://github.com/forktex/intelligence/issues
Project-URL: Homepage, https://intelligence.forktex.com
Project-URL: Repository, https://github.com/forktex/intelligence
Description-Content-Type: text/markdown

# forktex-intelligence

[![PyPI](https://img.shields.io/pypi/v/forktex-intelligence.svg)](https://pypi.org/project/forktex-intelligence/)
[![Python](https://img.shields.io/pypi/pyversions/forktex-intelligence.svg)](https://pypi.org/project/forktex-intelligence/)
[![License](https://img.shields.io/pypi/l/forktex-intelligence.svg)](https://github.com/forktex/intelligence/blob/master/sdk-py/LICENSE)

Standalone Python SDK for the [ForkTex Intelligence](https://intelligence.forktex.com) API.

`forktex-intelligence` is the Python SDK for the ForkTex Intelligence platform: a single common interface — `intel.invoke(model, inputs)` — for every stateless AI op (chat with vision, embeddings, reranking, file extraction, audio, video) plus the stateful Knowledge pillar (`Space` / `KnowledgeEntry` entity wrappers). Each call returns a typed `Outputs` carrying text / vectors / chunks / cost / usage; the SDK validates inputs against the model descriptor before any HTTP round-trip.

## Install

```bash
pip install forktex-intelligence
```

**Requires Python 3.12+.** Tested on 3.12, 3.13, 3.14.

## Quick Start

### Unified `invoke` — one call for every modality

```python
from forktex_intelligence import Intelligence, Inputs

async with Intelligence(api_key="ftx-...") as intel:
    # 1) Pick a model from the catalog (rich descriptor: inputs / outputs /
    #    capabilities / cost / context / architecture / runs_locally).
    model = await intel.find_model(destination="chat", capability="vision")

    # 2) Same interface for every modality.
    out = await intel.invoke(
        model,
        Inputs.user("Describe this image", images=["https://example.com/cat.jpg"]),
    )
    print(out.text)
    print(out.usage, out.cost, out.currency)
```

### Embed / extract / audio / video — same shape

```python
async with Intelligence(api_key="ftx-...") as intel:
    embed_model = await intel.find_model(destination="embed")
    out = await intel.invoke(embed_model, Inputs(text=["hello", "world"]))
    print(out.vectors)              # list[list[float]]

    extract_model = await intel.find_model(destination="extract")
    with open("paper.pdf", "rb") as f:
        out = await intel.invoke(
            extract_model,
            Inputs(file_bytes=f.read(), filename="paper.pdf",
                   content_type="application/pdf"),
        )
    print(out.text, len(out.chunks or []))
```

### Streaming

```python
async with Intelligence(api_key="ftx-...") as intel:
    model = await intel.find_model(destination="chat", capability="stream")
    async for delta in intel.stream(model, Inputs.user("Long answer")):
        if delta.kind == "text":
            print(delta.text, end="", flush=True)
        elif delta.kind == "done":
            break
```

Streaming a non-streamable model raises `ValueError` client-side — no HTTP round-trip wasted. Sending images to a non-vision model raises before HTTP too.

### Cost estimation (no HTTP)

```python
from forktex_intelligence import estimate_cost

est = estimate_cost(model, Inputs.user("hello"), expected_output_tokens=200)
print(est)   # Decimal('0.000345') or None for free / local models
```

See [`examples/`](examples/) for register → key → invoke walkthroughs.

## Configuration

Pass endpoint and API key explicitly:

```python
Intelligence(endpoint="https://intelligence.forktex.com/api", api_key="sk-...")
```

Or via an `IntelligenceSettings` object:

```python
from forktex_intelligence import IntelligenceSettings, Intelligence

settings = IntelligenceSettings(endpoint="...", api_key="...")
async with Intelligence(settings=settings) as ai:
    ...
```

When used via the `forktex` CLI, settings are loaded from environment variables and `.forktex/` config files automatically.

| Variable | Description | Default |
|----------|-------------|---------|
| `FORKTEX_INTELLIGENCE_ENDPOINT` | Intelligence API endpoint | `https://intelligence.forktex.com/api` |
| `FORKTEX_INTELLIGENCE_API_KEY` | Intelligence API key | *(required)* |

### Local dev (point at your `make local` stack)

```bash
export FORKTEX_INTELLIGENCE_ENDPOINT=http://localhost:8001/api
export FORKTEX_INTELLIGENCE_API_KEY=dev-key
```

Or programmatically:

```python
from forktex_intelligence import Intelligence
intel = Intelligence(endpoint="http://localhost:8001/api", api_key="dev-key")
```

## What's in the package

| Module | Purpose |
|--------|---------|
| `forktex_intelligence.api` | High-level `Intelligence` facade (root AI methods, `intel.chat`, `intel.knowledge`, `intel.config`, …) |
| `forktex_intelligence.ai` | Per-modality sub-handles (`ChatHandle`, `EmbedHandle`, `ExtractHandle`, `AudioHandle`, `VideoHandle`) |
| `forktex_intelligence.resources` | Entity wrappers — `Space`, `KnowledgeEntry` |
| `forktex_intelligence.tool_loop` | `run_with_tools(...)` streaming-with-tools async iterator |
| `forktex_intelligence.inputs` | `Inputs`, `Outputs`, `OutputDelta` — the unified shape any model accepts and returns |
| `forktex_intelligence.validation` | Client-side capability gate — refuses incompatible inputs before HTTP |
| `forktex_intelligence.cost` | `estimate(model, inputs)` — best-effort cost from descriptor pricing |
| `forktex_intelligence.client` | Low-level `ForktexIntelligenceClient` (raw HTTP; advanced) |
| `forktex_intelligence.client.generated` | Wire-level Pydantic models + `_GeneratedOperations` from the OpenAPI spec |
| `forktex_intelligence.streams` | SSE event types and parser |
| `forktex_intelligence.config` | `IntelligenceSettings` — endpoint, API key |

All response models come from the OpenAPI codegen pipeline — one source of truth shared between the server and every consumer.

## Repository

This SDK lives inside the [`forktex/intelligence`](https://github.com/forktex/intelligence) monorepo alongside the API server (`api/`). The SDK package is independently versioned and published to PyPI.

## Development

The [`Makefile`](Makefile) is generated by `forktex fsd makefile sync` from [`forktex.json`](forktex.json) — do not hand-edit.

```bash
make help              # list every available target
make deps              # editable install with the dev group
make format            # ruff format
make lint              # ruff check
make test              # pytest tests/
make codegen-check     # verify the generated client imports cleanly
make build             # python3 -m build → dist/
make ci                # format-check + lint + license-check + audit + test + build
make clean             # remove caches and dist/
```

`make ci` is the single command that gates a publish: format-check, lint, dual-license header check, dependency CVE audit, full test suite, and `python -m build` + `twine check`.

### License headers

Every source file carries the AGPL-3.0 + Commercial dual-license SPDX header, applied idempotently via:

```bash
make license-check    # CI gate — fails if any source file is missing the header
make license-fix      # add or refresh headers across src/, tests/, scripts/
make license-strip    # remove headers (used before license-model changes)
```

## License

Dual-licensed — **AGPL-3.0-or-later** for open-source use, **commercial** for everything else (proprietary products, SaaS without source release, redistribution in closed-source form). See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE) for the full terms.

Commercial licensing inquiries: info@forktex.com.

The 1.0.0 release on PyPI remains under MIT; from **0.2.3** onwards the package ships AGPL-3.0+Commercial.

