diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e870f09..0a467db 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,11 +1,11 @@ -name: Publish Python alpha +name: Publish Python pre-release on: workflow_dispatch: inputs: version: description: Exact version in pyproject.toml required: true - default: '0.1.0a1' + default: '0.1.0b1' permissions: contents: read jobs: @@ -25,11 +25,13 @@ jobs: RELEASE_VERSION: ${{ inputs.version }} run: | python - <<'PY' - import os, tomllib + import os, re, tomllib with open('pyproject.toml', 'rb') as f: version = tomllib.load(f)['project']['version'] assert version == os.environ['RELEASE_VERSION'], 'release version mismatch' - assert 'a' in version, 'this workflow publishes alpha versions only' + assert re.fullmatch(r'\d+\.\d+\.\d+(a|b)\d+', version), ( + 'this workflow publishes alpha (aN) or beta (bN) pre-releases only' + ) PY - run: python -m pip install build twine - run: python -m build diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..04275c3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +## 0.1.0b1 + +First beta of the Python AI Protection SDK. The `webdecoy_ai_protection` package +API is unchanged from `0.1.0a1`; this release moves the package from alpha to beta. + +- Add a runnable Ollama example (`examples/ollama_budget.py`) that wraps one + non-streaming `ollama.AsyncClient.generate` call in a per-attempt model budget, + with pinned example requirements (`examples/requirements-ollama.txt`). +- Add tests for the Ollama example against the pinned `ollama==0.6.3` Python SDK + with an in-memory HTTP transport: serialization, usage normalization, denial + before the provider, privacy, cancellation and accounting failures. `ollama` is + added to the `dev` extra only; it is not a runtime dependency. +- Document the Ollama example in the README. +- The publish workflow now accepts beta (`bN`) as well as alpha (`aN`) + pre-release versions. +- Update maturity labels and install instructions to `0.1.0b1`. + +```sh +python -m pip install 'webdecoy-ai-protection[fastapi]==0.1.0b1' +``` + +Earlier releases are described in the +[GitHub releases](https://github.com/WebDecoy/ai-protection-python/releases). diff --git a/README.md b/README.md index 9560275..3b71406 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Async request admission for Python AI endpoints. Local application rules run in your process; bot detection runs in WebDecoy. Apache-2.0 licensed. -**Alpha preview.** This first implementation covers +**Beta.** This release covers admission, shared account/session quotas, reporting and an explicit FastAPI/Starlette route wrapper, including optional concurrency leases across streamed responses. Per-attempt model budgets and usage reporting are also available. Browser evidence @@ -13,10 +13,10 @@ and MCP adapters are not yet implemented. It is not a prompt-injection filter or Requires Python 3.11+ and asyncio. HTTPX is the only core runtime dependency. FastAPI/Starlette support is optional; synchronous applications and Trio are not -supported in this preview. +supported in this beta. ```sh -python -m pip install 'webdecoy-ai-protection[fastapi]==0.1.0a1' +python -m pip install 'webdecoy-ai-protection[fastapi]==0.1.0b1' ``` For core-only applications, omit `[fastapi]`. For development from this checkout, @@ -274,7 +274,7 @@ Use `BudgetCompletion(value, usage)` to preserve provider output separately from accounting. A return value without that wrapper is preserved with unknown usage. For streaming, consume the stream **inside** the callback and await terminal usage; returning a `StreamingResponse` or iterator is not completion. Arrange budget -denial before committing HTTP headers. This preview has no automatic budgeted +denial before committing HTTP headers. This beta has no automatic budgeted HTTP-streaming bridge. When composing concurrency, wrap the complete budgeted provider attempt inside the concurrency-owned work; FastAPI's concurrency wrapper already owns its handler and full response lifecycle. @@ -363,7 +363,7 @@ not detection effectiveness, customer savings, or production capacity. [`examples/ollama_budget.py`](examples/ollama_budget.py) wraps a real [`ollama.AsyncClient.generate`](https://github.com/ollama/ollama-python) call -with the existing published WebDecoy SDK. Install the example dependencies: +with the published WebDecoy SDK. Install the example dependencies: ```sh python -m pip install -r examples/requirements-ollama.txt diff --git a/examples/requirements-ollama.txt b/examples/requirements-ollama.txt index 6a1da65..5f9fd7b 100644 --- a/examples/requirements-ollama.txt +++ b/examples/requirements-ollama.txt @@ -1,2 +1,2 @@ -webdecoy-ai-protection==0.1.0a1 +webdecoy-ai-protection==0.1.0b1 ollama==0.6.3 diff --git a/pyproject.toml b/pyproject.toml index 5e145bd..a3664bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "webdecoy-ai-protection" -version = "0.1.0a1" +version = "0.1.0b1" description = "Async request admission for Python AI endpoints using WebDecoy" readme = "README.md" requires-python = ">=3.11"