Skip to content

Add generated control-plane client (preview)#3

Draft
njbrake wants to merge 6 commits into
mainfrom
codegen/control-plane-preview
Draft

Add generated control-plane client (preview)#3
njbrake wants to merge 6 commits into
mainfrom
codegen/control-plane-preview

Conversation

@njbrake
Copy link
Copy Markdown
Member

@njbrake njbrake commented Jun 5, 2026

Note: this draft PR was created by Claude via back-and-forth with @njbrake. The reasoning and decisions are his; the prose is Claude's and the client code is generator output.

Draft preview. Adds the generated control-plane client (API keys, users, budgets, pricing, usage) produced from the otari gateway OpenAPI spec by OpenAPI Generator, dropped into src/otari/_generated.

Purpose: review the generated surface and design the integration that exposes these management methods through this SDK's public client. The inference and proxy surface, and batches, stay hand-written and are untouched here.

Notes:

  • This is raw generator output. Wiring it into the public client (re-exports, shared auth, error mapping) is the follow-up.
  • Repo CI (lint, typecheck) may be red on the generated code until it is wired in and ignore rules are added. That is expected for a preview.
  • Batches are intentionally excluded: their responses are untyped in the spec, and this SDK already implements them by hand.

Generated from the mozilla-ai/otari OpenAPI spec. Part of mozilla-ai/otari#96.

njbrake and others added 6 commits June 5, 2026 17:15
Generated control-plane client (keys, users, budgets, pricing, usage) from
the otari gateway OpenAPI spec via OpenAPI Generator. Preview for review and
integration design; not yet wired into the public client.

Part of mozilla-ai/otari#96

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full CRUD lifecycle tests for every control-plane endpoint (keys, users,
budgets, pricing, usage) driving the generated client against a real gateway
started on SQLite with a master key (no provider creds needed). Verified
22 endpoint operations pass; documents the Bearer-auth requirement and the
per-language test pattern.

Part of mozilla-ai/otari#96

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Regenerate the control-plane client as a clean subpackage (otari._control_plane).
- Add OtariClient.control_plane: typed accessors (keys/users/budgets/pricing/usage)
  sharing one client authed with Authorization: Bearer using an admin credential
  (admin_key / GATEWAY_ADMIN_KEY / platform_token). Management endpoints require
  Bearer, not the Otari-Key inference header.
- Add admin_key param + ControlPlane facade; export ControlPlane.
- Exclude the generated subpackage from ruff/mypy; add its runtime deps.
- Integration tests now drive the public control_plane surface end-to-end
  (full CRUD per endpoint + admin-credential guard); 6 pass against a live
  gateway on SQLite.

Part of mozilla-ai/otari#96

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eway

- Add .github/workflows/ci.yml: ruff + mypy + pytest on push/PR across
  Python 3.11-3.13 (the repo previously only ran checks on release).
- Integration tests skip cleanly when no gateway is on PATH (set
  OTARI_GATEWAY_CMD to run them), so CI is green without a gateway and
  passes with one.
- Register the 'integration' marker; per-file-ignore the subprocess/URL
  audit rules for the test harness.

Part of mozilla-ai/otari#96

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the OpenAI-SDK delegation with a hand-written shell over the
OpenAPI-generated core (otari._client), generated from the otari spec.
The gateway is only OpenAI-compatible and has endpoints (notably the
Anthropic-shaped /messages) the OpenAI SDK cannot represent; generating
from the otari spec models the real contract.

Core (unmodified generator output) replaces the old _control_plane
subpackage and covers every endpoint with typed request/response models.

Shell (the real work):
- Auth modes preserved: platform -> Authorization: Bearer <token>;
  non-platform -> Otari-Key: Bearer <key>; control-plane -> Authorization:
  Bearer <admin/master key>. Fed into the generated ApiClient default
  headers and the streaming shim's httpx requests.
- Ergonomic methods keep the existing public names/signatures
  (completion/response/embedding/moderation/rerank/list_models/batches)
  and add message(...) for the previously-missing /messages endpoint.
  control_plane accessor now backed by _client.
- SSE streaming shim (_streaming.py): the generated core buffers and
  cannot stream, so stream=True does a raw httpx streaming POST, parses
  text/event-stream framing, terminates on [DONE], and yields typed
  ChatCompletionChunk (chat) / parsed JSON (responses, messages).
- Typed error mapping: generated ApiException (.status/.body) -> the
  errors.py hierarchy (Authentication 401/403, InsufficientFunds 402,
  ModelNotFound 404, BatchNotComplete 409, RateLimit 429, GatewayTimeout
  504, UpstreamProvider 502/5xx, UnsupportedCapability cross-mode, generic
  OtariError). The streaming path adapts failed responses through the same
  mapper.
- Async client wraps the sync generated core via asyncio.to_thread and
  streams natively over httpx.AsyncClient.

Drop the openai dependency from inference. Update ruff/mypy excludes to
src/otari/_client. Rewrite unit tests to mock the generated transport
(RESTClientObject.request) and respx for SSE; control-plane integration
tests updated to import from _client and verified green against a live
gateway.

Note: chat streaming cannot be live-verified in this sandbox (no provider
key on the gateway); the SSE shim is unit-tested over mocked chunk bytes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fail CI when the gateway OpenAPI spec exposes an endpoint the SDK's public
API does not account for. A checked-in manifest (sdk-endpoints.txt) pins the
covered and intentionally-excluded endpoint sets; a pytest test fetches the
canonical spec and asserts spec is a subset of (covered + excluded), naming
any unaccounted endpoint. Wired as a dedicated CI step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant