Metadata-Version: 2.4
Name: sequenx-ai
Version: 0.1.1
Summary: Python client for the SequenxAI time-series platform API
Author-email: SequenxAI <lcw_1497007939@163.com>
License-Expression: LicenseRef-Proprietary
Keywords: time-series,forecasting,sequenxai
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0,>=0.27
Provides-Extra: pandas
Requires-Dist: pandas>=2.0; extra == "pandas"
Provides-Extra: polars
Requires-Dist: polars>=1.0; extra == "polars"

# sequenx (SequenxAI Python client)

Python client for the SequenxAI platform API (`packages/contracts/openapi.yaml` is the single
source of truth for the wire format). Published on PyPI as `sequenx-ai`:

```bash
pip install sequenx-ai
```

To work on the client itself, install it from this repository in editable mode
(`pip install -e packages/sequenx-py`).

```python
from sequenx import SequenxClient

client = SequenxClient("sqx_live_...")
result = client.forecast(series, h=96)      # series: list[dict] with unique_id/ds/y
print(result["model_used"], result["usage"]["billable_points"])
client.close()
```

Covered endpoints (v1): `POST /forecast`, `POST /forecast/rolling`, `POST /forecast/batch`
(+ get / cancel / delete job), `POST /clean` (dry-run), `GET /models`. `POST /anomaly-detection`
is intentionally not covered (endpoint not open).

## Idempotency and retries

The control plane claims an `Idempotency-Key` on `POST /forecast`, `POST /forecast/rolling` and
`POST /forecast/batch` only: a repeated identical request replays the stored response instead of
charging again. The SDK sends the key on exactly those three routes and reuses it across retries,
so a transport error or a 429/5xx is retried safely (`max_retries=0` disables retries).

A retry that races the original request can answer 409 (`IDEMPOTENCY_IN_PROGRESS`): the request
that claimed the key is still running. The SDK retries it with the same key (the control plane
replays the stored response once it settles). If it still cannot finish, the raised
`ConflictError` carries the `idempotency_key` it used, so the call can be replayed safely:

```python
from sequenx import ConflictError

try:
    out = client.forecast(series, h=96)
except ConflictError as exc:
    out = client.forecast(series, h=96, idempotency_key=exc.idempotency_key)
```

The SDK generates one key per call; pass your own `idempotency_key=` to `forecast`,
`forecast_rolling` or `forecast_batch` when you want to hold on to it yourself.

Every other route is re-run by the control plane, so the SDK neither sends a key nor retries it
automatically: `POST /clean` (a free dry-run), `POST /forecast/batch/{job_id}/cancel` and
`DELETE /forecast/batch/{job_id}` (a repeated delete would answer 404 although the first delete
succeeded — read the job with `batch_job()` when the outcome matters). `GET` requests are retried.

## Batch jobs

`forecast_batch()` submits a job; `batch_job()` polls it, `cancel_batch_job()` cancels it and
`delete_batch_job()` removes a finished job and its result file. Polling is the caller's loop.

## Errors

Errors are typed (`AuthenticationError`, `ValidationError`, `RateLimitedError`, `ServerError`,
`TransportError`, ...) and carry the contract's `code` / `request_id` / `status`.

## Response types

Responses are typed too (`ForecastResponse`, `RollingForecastResponse`, `ModelList`,
`BatchJobSummary`, `BatchJobDetail`, `CleanResponse`, ...); the shapes mirror the contract
schemas and the package ships `py.typed`. Nested objects the SDK does not model (intervals,
cleaning report, effective policy) stay plain dictionaries.

## DataFrames

`pandas` and `polars` frames are accepted as input (`pip install -e "packages/sequenx-py[pandas]"`
or `[polars]`); neither is required.

## Development

```bash
pip install -e packages/sequenx-py -r packages/sequenx-py/requirements-dev.txt
python -m pytest -q          # unit + contract drift tests
python -m ruff check src tests
SEQUENX_SDK_LIVE_SMOKE=1 SEQUENX_API_KEY=sqx_live_... python scripts/live_smoke.py
```

The live smoke is opt-in and never passes silently: without the flag and key it exits 2 with
instructions. The contract drift test reads `packages/contracts/openapi.yaml` and fails when the
SDK and the contract disagree; Gitee Go runs it via `scripts/ci/gitee-verify.sh sdk`.
