Metadata-Version: 2.5
Name: xevyo
Version: 0.1.0
Summary: Client SDK and self-hostable server for the xevyo AI assistant platform.
Author: Xevyo
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agents,ai,assistant,llm,rag,self-hosted
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.7
Requires-Dist: typer<1.0,>=0.12
Provides-Extra: all
Requires-Dist: alembic<2.0,>=1.13; extra == 'all'
Requires-Dist: asyncpg<1.0,>=0.29; extra == 'all'
Requires-Dist: bcrypt<5.0,>=4.1; extra == 'all'
Requires-Dist: beautifulsoup4>=4.12; extra == 'all'
Requires-Dist: celery<6.0,>=5.3; extra == 'all'
Requires-Dist: email-validator<3.0,>=2.0; extra == 'all'
Requires-Dist: fastapi<1.0,>=0.115; extra == 'all'
Requires-Dist: lxml>=5.0; extra == 'all'
Requires-Dist: markdown>=3.6; extra == 'all'
Requires-Dist: numpy>=1.26; extra == 'all'
Requires-Dist: pdf2image>=1.17; extra == 'all'
Requires-Dist: pgvector<1.0,>=0.3; extra == 'all'
Requires-Dist: pillow>=10.0; extra == 'all'
Requires-Dist: pydantic-settings<3.0,>=2.3; extra == 'all'
Requires-Dist: pyjwt<3.0,>=2.8; extra == 'all'
Requires-Dist: pypdf>=5.0; extra == 'all'
Requires-Dist: pytesseract>=0.3.13; extra == 'all'
Requires-Dist: python-docx>=1.1; extra == 'all'
Requires-Dist: python-multipart<1.0,>=0.0.9; extra == 'all'
Requires-Dist: redis<6.0,>=5.0; extra == 'all'
Requires-Dist: sentence-transformers>=3.0; extra == 'all'
Requires-Dist: sqlalchemy[asyncio]<3.0,>=2.0; extra == 'all'
Requires-Dist: torch>=2.4; extra == 'all'
Requires-Dist: trafilatura>=2.0; extra == 'all'
Requires-Dist: uvicorn[standard]<1.0,>=0.30; extra == 'all'
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: documents
Requires-Dist: beautifulsoup4>=4.12; extra == 'documents'
Requires-Dist: lxml>=5.0; extra == 'documents'
Requires-Dist: markdown>=3.6; extra == 'documents'
Requires-Dist: pdf2image>=1.17; extra == 'documents'
Requires-Dist: pillow>=10.0; extra == 'documents'
Requires-Dist: pypdf>=5.0; extra == 'documents'
Requires-Dist: pytesseract>=0.3.13; extra == 'documents'
Requires-Dist: python-docx>=1.1; extra == 'documents'
Requires-Dist: trafilatura>=2.0; extra == 'documents'
Provides-Extra: local-embeddings
Requires-Dist: numpy>=1.26; extra == 'local-embeddings'
Requires-Dist: sentence-transformers>=3.0; extra == 'local-embeddings'
Requires-Dist: torch>=2.4; extra == 'local-embeddings'
Provides-Extra: server
Requires-Dist: alembic<2.0,>=1.13; extra == 'server'
Requires-Dist: asyncpg<1.0,>=0.29; extra == 'server'
Requires-Dist: bcrypt<5.0,>=4.1; extra == 'server'
Requires-Dist: celery<6.0,>=5.3; extra == 'server'
Requires-Dist: email-validator<3.0,>=2.0; extra == 'server'
Requires-Dist: fastapi<1.0,>=0.115; extra == 'server'
Requires-Dist: pgvector<1.0,>=0.3; extra == 'server'
Requires-Dist: pydantic-settings<3.0,>=2.3; extra == 'server'
Requires-Dist: pyjwt<3.0,>=2.8; extra == 'server'
Requires-Dist: python-multipart<1.0,>=0.0.9; extra == 'server'
Requires-Dist: redis<6.0,>=5.0; extra == 'server'
Requires-Dist: sqlalchemy[asyncio]<3.0,>=2.0; extra == 'server'
Requires-Dist: uvicorn[standard]<1.0,>=0.30; extra == 'server'
Description-Content-Type: text/markdown

# xevyo

Two things live in this one package, same split as `openai`/`openai[...]`:

1. **A thin client SDK** (`pip install xevyo`) — `import xevyo; client =
   xevyo.Client(api_key=...)`, then `client.chats.ask(...)`. No server, no
   database, three dependencies (httpx, pydantic, typer). This is what
   most people installing `xevyo` from PyPI want.
2. **A self-hostable server** (`pip install xevyo[server]`) — RAG, chat
   storage, tool orchestration, and a web UI, all behind `xevyo serve`.
   Someone runs this once; everyone else uses the SDK against it.

```
pip install xevyo[server] && xevyo serve   ──►  a running xevyo server
                                                          ▲
pip install xevyo (elsewhere)                            │
import xevyo; xevyo.Client(api_key=...)  ─────────────────┘
```

> **Status:** early release. Storage, auth, chats, knowledge/RAG, tool
> orchestration, the client SDK, and the web UI are in place and
> independently verified; the client SDK's `protocol="gateway"` mode has
> been confirmed working against a real server. End-to-end testing of
> `protocol="xevyo"` (the native self-hosted server) against a live
> Postgres/Redis deployment is still outstanding — see
> [TESTING.md](TESTING.md).

## Install

### As a client (most people)

```bash
pip install xevyo
```

`xevyo.Client` talks to one of two backends, selected with `protocol=`:

```python
import xevyo

# protocol="xevyo" (default) — a native, self-hosted xevyo[server] instance
client = xevyo.Client(api_key="xvo_...", base_url="https://your-xevyo-server.example.com")
reply = client.chats.ask("What's in my uploaded PDF?")
print(reply.text())  # a method call

# protocol="gateway" — Xevyo's own hosted completions gateway
# (not a generic Open WebUI API — it won't work against an unrelated OWUI install)
client = xevyo.Client(api_key="xk-...", base_url="https://your-gateway.example.com", protocol="gateway")
reply = client.chats.ask("Hello!")
print(reply.text)  # a plain attribute, not a method — different return type

# api_key/base_url also read from XEVYO_API_KEY / XEVYO_BASE_URL if omitted
```

`protocol="gateway"` is stateless (no persisted chat history, no
knowledge/RAG yet) and talks to Xevyo's branded `/xevyo/v1/chat/completions`
gateway. `protocol="xevyo"` is the fuller, stateful API (persisted chats,
knowledge/RAG, tool-calling) for a self-hosted server — create an API key
via `POST /api/auth/api-keys` (after signing up/logging in), or from the
web UI's Settings > API keys.

### As a server (to host xevyo yourself)

```bash
pip install "xevyo[server]"
```

xevyo's server requires:

- **PostgreSQL with the [pgvector](https://github.com/pgvector/pgvector) extension** — there is no embedded/SQLite mode.
- **Redis** — background knowledge ingestion runs on Celery; `xevyo worker` needs Redis reachable alongside `xevyo serve`.

Heavier server-side capabilities are further opt-in, layered on top of `[server]`:

| Extra              | Adds                                              |
| ------------------ | ------------------------------------------------- |
| `local-embeddings` | torch, sentence-transformers (on-device models)   |
| `documents`        | PDF/DOCX/HTML parsing and OCR                     |
| `all`              | `server` + `local-embeddings` + `documents`       |

```bash
pip install "xevyo[server,local-embeddings]"
```

## Usage

```bash
xevyo version                              # always available
xevyo serve --host 0.0.0.0 --port 8080     # web UI + API — needs [server]
xevyo worker                                # background knowledge ingestion, separate process — needs [server]
xevyo migrate                                # needs [server]
```

Running `xevyo serve`/`worker`/`migrate` without the `server` extra
installed fails with a clear message telling you to `pip install
'xevyo[server]'`, rather than an import traceback.

## Configuration

Settings are read from the environment with the `XEVYO_` prefix, or from a
`.env` file in the working directory.

| Variable                          | Default                                                  | Purpose                             |
| ---------------------------------- | --------------------------------------------------------- | ------------------------------------ |
| `XEVYO_DATA_DIR`                   | `~/.xevyo`                                                 | Uploads, caches, JWT secret file     |
| `XEVYO_DATABASE_URL`               | `postgresql+asyncpg://xevyo:xevyo@localhost:5432/xevyo`   | Postgres + pgvector DSN              |
| `XEVYO_REDIS_URL`                  | `redis://localhost:6379/0`                                 | Celery broker/backend                |
| `XEVYO_LLM_BASE_URL`               | `http://localhost:8000/v1`                                 | Any OpenAI-compatible endpoint       |
| `XEVYO_LLM_API_KEY`                | unset                                                        | LLM provider API key, if required    |
| `XEVYO_LLM_MODEL`                  | `default`                                                    | Model name sent to the LLM endpoint  |
| `XEVYO_SERVE_FRONTEND`             | `true`                                                        | Serve the bundled web UI             |
| `XEVYO_CORS_ALLOW_ORIGINS`         | `[]`                                                           | CORS origins for the API             |

## Development

```bash
python -m venv .venv && .venv/Scripts/activate   # Windows
pip install -e ".[server,dev]"   # [server] needed too: most tests exercise server-side code
pytest
ruff check .
mypy src/xevyo
```

See [TESTING.md](TESTING.md) for the full picture: installing from a built
wheel, what the unit test suite does and doesn't cover, and how to run a
complete live-stack test against real Postgres/Redis/an LLM endpoint.

### Frontend

The web UI lives in [`frontend/`](frontend/) — a separate React/Vite
project, not part of the Python package's dependency tree.

```bash
cd frontend
npm install
npm run dev              # dev server, proxies /api to XEVYO_BACKEND (default :8080)
```

To bundle the built UI into the wheel:

```bash
python scripts/build_frontend.py   # npm run build, then copies dist/ -> src/xevyo/server/static/
uv build                             # or: pip install .
```

Building the frontend requires Node.js — but only at package-build/release
time. `pip install xevyo` never needs Node: the built assets ship inside
the sdist and wheel (see `[tool.hatch.build]` in `pyproject.toml`).

## License

Apache License 2.0 — see [LICENSE](LICENSE).
