diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9ea3a45 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v4 + + - uses: astral-sh/setup-uv@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --extra dev + + - name: Lint + run: uv run ruff check . + + - name: Type check + run: uv run mypy src/ + + - name: Test + # Integration tests skip automatically when no gateway is on PATH. + run: uv run pytest + + - name: Endpoint-coverage drift gate + # Fetches the canonical gateway OpenAPI spec and fails if it exposes an + # endpoint absent from sdk-endpoints.txt ([covered] or [excluded]). + # Network is available in CI, so this must not skip here. + run: uv run pytest tests/unit/test_endpoint_coverage.py -v diff --git a/README.md b/README.md index a36110f..873a29f 100644 --- a/README.md +++ b/README.md @@ -195,6 +195,21 @@ response = client.response( print(response.output_text) ``` +### Messages API (Anthropic-shaped) + +The gateway's `/messages` endpoint (Anthropic message shape) is exposed via +`message(...)`. Set `stream=True` to iterate raw message-stream event dicts. + +```python +message = client.message( + model="anthropic:claude-3-5-sonnet", + messages=[{"role": "user", "content": "Hello!"}], + max_tokens=256, +) + +print(message.content) +``` + ### Embeddings ```python diff --git a/pyproject.toml b/pyproject.toml index 3aaacfd..cf4bf3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,8 +22,12 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "openai>=1.99.3", + # Streaming shim (raw SSE over httpx); the generated core cannot stream. "httpx>=0.25.0", + # Runtime deps of the OpenAPI-generated core (otari._client). + "urllib3>=2.1.0", + "python-dateutil>=2.8.2", + "pydantic>=2.0.0", ] [project.urls] @@ -36,6 +40,7 @@ Issues = "https://github.com/mozilla-ai/otari-sdk-python/issues" dev = [ "pytest>=8.0", "pytest-asyncio>=0.24", + "respx>=0.21", "ruff>=0.8", "mypy>=1.13", ] @@ -46,15 +51,25 @@ packages = ["src/otari"] [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" +markers = [ + "integration: tests that require a running gateway (skipped if none is available)", +] [tool.ruff] target-version = "py311" line-length = 120 +# Generated core client (OpenAPI Generator output) is not hand-linted. +extend-exclude = ["src/otari/_client"] [tool.ruff.lint] select = ["E", "F", "I", "N", "W", "UP", "S", "B", "A", "C4", "DTZ", "T10", "ISC", "ICN", "PIE", "PT", "RSE", "RET", "SIM", "TID", "TCH", "ARG", "PLC", "PLE", "PLW", "TRY", "FLY", "PERF", "RUF"] ignore = ["S101", "TRY003", "PLW0603"] +[tool.ruff.lint.per-file-ignores] +# Integration tests spawn the gateway subprocess and poll it over HTTP; the +# subprocess/URL/temp-file audit rules don't apply to that test harness. +"tests/integration/*" = ["S603", "S310", "SIM115", "SIM117", "PLC0415", "TC003"] + [tool.ruff.lint.isort] known-first-party = ["otari"] @@ -63,3 +78,10 @@ python_version = "3.11" strict = true warn_return_any = true warn_unused_configs = true +# Generated core client (OpenAPI Generator output) is not type-checked here. +exclude = ["src/otari/_client/"] + +[[tool.mypy.overrides]] +module = ["otari._client.*"] +ignore_errors = true +ignore_missing_imports = true diff --git a/sdk-endpoints.txt b/sdk-endpoints.txt new file mode 100644 index 0000000..9da2578 --- /dev/null +++ b/sdk-endpoints.txt @@ -0,0 +1,61 @@ +# Endpoint-coverage drift manifest for the otari gateway. +# +# This file pins which gateway OpenAPI endpoints this SDK's PUBLIC API accounts +# for. CI fetches the canonical spec +# https://raw.githubusercontent.com/mozilla-ai/otari/main/docs/public/openapi.json +# computes its set of "METHOD path" pairs (excluding /health* meta routes), and +# asserts that set is a subset of (covered + excluded). A new gateway endpoint +# in neither section FAILS the build: add a wrapper and list it under [covered], +# or deliberately defer it under [excluded] with a one-word reason. +# +# All four otari SDKs (python/ts/go/rust) keep this list identical: they target +# the same gateway. Lines are "METHOD /path"; blank lines and # comments ignore. + +[covered] +# Inference +POST /v1/chat/completions +POST /v1/responses +POST /v1/messages +POST /v1/embeddings +POST /v1/moderations +POST /v1/rerank +GET /v1/models +# Batches +POST /v1/batches +GET /v1/batches +GET /v1/batches/{batch_id} +POST /v1/batches/{batch_id}/cancel +GET /v1/batches/{batch_id}/results +# Control plane: keys +POST /v1/keys +GET /v1/keys +GET /v1/keys/{key_id} +PATCH /v1/keys/{key_id} +DELETE /v1/keys/{key_id} +# Control plane: users +POST /v1/users +GET /v1/users +GET /v1/users/{user_id} +PATCH /v1/users/{user_id} +DELETE /v1/users/{user_id} +GET /v1/users/{user_id}/usage +# Control plane: budgets +POST /v1/budgets +GET /v1/budgets +GET /v1/budgets/{budget_id} +PATCH /v1/budgets/{budget_id} +DELETE /v1/budgets/{budget_id} +# Control plane: pricing +POST /v1/pricing +GET /v1/pricing +GET /v1/pricing/{model_key} +GET /v1/pricing/{model_key}/history +DELETE /v1/pricing/{model_key} +# Control plane: usage +GET /v1/usage + +[excluded] +POST /v1/audio/speech # binary, not yet wrapped +POST /v1/audio/transcriptions # binary, not yet wrapped +POST /v1/images/generations # binary, not yet wrapped +GET /v1/models/{model_id} # redundant, list_models covers discovery diff --git a/src/otari/__init__.py b/src/otari/__init__.py index 1fd260f..f6e9895 100644 --- a/src/otari/__init__.py +++ b/src/otari/__init__.py @@ -9,7 +9,7 @@ platform_token="your-token-here", ) - response = await client.completion( + response = client.completion( model="openai:gpt-4o-mini", messages=[{"role": "user", "content": "Hello!"}], ) @@ -20,6 +20,7 @@ from otari.async_client import AsyncOtariClient from otari.client import OtariClient +from otari.control_plane import ControlPlane from otari.errors import ( AuthenticationError, BatchNotCompleteError, @@ -32,23 +33,20 @@ UpstreamProviderError, ) from otari.types import ( - AsyncStream, BatchRequestItem, BatchResult, BatchResultError, BatchResultItem, ChatCompletion, ChatCompletionChunk, - ChatCompletionMessageParam, CreateBatchParams, CreateEmbeddingResponse, - EmbeddingCreateParams, ListBatchesOptions, - Model, + MessageResponse, + ModelObject, + ModerationResponse, OtariClientOptions, - Response, - ResponseStreamEvent, - Stream, + RerankResponse, ) try: @@ -59,7 +57,6 @@ __all__ = [ "AsyncOtariClient", - "AsyncStream", "AuthenticationError", "BatchNotCompleteError", "BatchRequestItem", @@ -68,22 +65,21 @@ "BatchResultItem", "ChatCompletion", "ChatCompletionChunk", - "ChatCompletionMessageParam", + "ControlPlane", "CreateBatchParams", "CreateEmbeddingResponse", - "EmbeddingCreateParams", "GatewayTimeoutError", "InsufficientFundsError", "ListBatchesOptions", - "Model", + "MessageResponse", "ModelNotFoundError", + "ModelObject", + "ModerationResponse", "OtariClient", "OtariClientOptions", "OtariError", "RateLimitError", - "Response", - "ResponseStreamEvent", - "Stream", + "RerankResponse", "UnsupportedCapabilityError", "UpstreamProviderError", ] diff --git a/src/otari/_base.py b/src/otari/_base.py index 32bf6b0..86e7b58 100644 --- a/src/otari/_base.py +++ b/src/otari/_base.py @@ -4,19 +4,24 @@ synchronous or asynchronous: auth-mode resolution, base-URL normalization, header building, and error mapping. The concrete clients (:class:`~otari.client.OtariClient` and -:class:`~otari.async_client.AsyncOtariClient`) construct their own OpenAI and -httpx clients and implement the I/O methods on top of this base. +:class:`~otari.async_client.AsyncOtariClient`) construct their own generated +``_client`` and httpx clients and implement the I/O methods on top of this base. + +Option C: the inference path is a thin shell over the OpenAPI-generated core in +:mod:`otari._client` (typed models + per-endpoint API classes). The generated +``ApiException`` is the single error type all generated calls raise; this module +maps it to the typed otari exception hierarchy in :mod:`otari.errors`. """ from __future__ import annotations +import json import os import re import urllib.parse -from typing import TYPE_CHECKING, Any - -import openai +from typing import TYPE_CHECKING, Any, Protocol, TypeVar, cast +from otari._client.exceptions import ApiException from otari.errors import ( AuthenticationError, BatchNotCompleteError, @@ -46,21 +51,17 @@ # Matches the gateway server's own alias chain (OTARI_AI_TOKEN preferred). _ENV_PLATFORM_TOKEN = "OTARI_AI_TOKEN" # noqa: S105 _ENV_PLATFORM_TOKEN_LEGACY = "GATEWAY_PLATFORM_TOKEN" # noqa: S105 - -_STATUS_TO_ERROR: dict[int, type[AuthenticationError] | type[ModelNotFoundError]] = { - 401: AuthenticationError, - 403: AuthenticationError, - 404: ModelNotFoundError, -} +# Admin/master credential for the control-plane (management) endpoints. +_ENV_ADMIN_KEY = "GATEWAY_ADMIN_KEY" class _BaseOtariClient: """Transport-agnostic base for the otari gateway clients. - Subclasses are responsible for constructing the underlying OpenAI client - (``OpenAI`` or ``AsyncOpenAI``) and the httpx client (``httpx.Client`` or - ``httpx.AsyncClient``) using the resolved configuration attributes set up - here. + Subclasses are responsible for constructing the generated ``_client`` + ``ApiClient`` (seeded with the default headers assembled here) and an httpx + client (``httpx.Client`` or ``httpx.AsyncClient``) for the SSE streaming + shim, using the resolved configuration attributes set up here. """ platform_mode: bool @@ -72,8 +73,8 @@ def __init__( *, api_key: str | None = None, platform_token: str | None = None, + admin_key: str | None = None, default_headers: dict[str, str] | None = None, - openai_options: dict[str, Any] | None = None, ) -> None: # Canonical OTARI_AI_TOKEN wins over the legacy GATEWAY_PLATFORM_TOKEN. resolved_platform_token = ( @@ -111,206 +112,201 @@ def __init__( api_base_url = cleaned if cleaned.endswith("/v1") else f"{cleaned}/v1" self._base_url = api_base_url + # The generated core's operation paths already include the ``/v1`` + # prefix, so the generated ``Configuration.host`` is the gateway root. + self._gateway_root_url = api_base_url.removesuffix("/v1") headers: dict[str, str] = {**(default_headers or {})} # Auth resolution (same logic as TS SDK / Python GatewayProvider): - # 1. Explicit platform_token -> platform mode + # 1. Explicit platform_token -> platform mode (Bearer Authorization) # 2. OTARI_AI_TOKEN (or legacy GATEWAY_PLATFORM_TOKEN) env + no api_key # option -> platform mode - # 3. Otherwise -> non-platform mode + # 3. Otherwise -> non-platform mode (Otari-Key header) if resolved_platform_token and not api_key: self.platform_mode = True self._platform_token: str | None = resolved_platform_token self._api_key: str | None = None - # In platform mode the OpenAI client carries the Bearer token. - self._openai_api_key = resolved_platform_token + headers["Authorization"] = f"Bearer {resolved_platform_token}" else: self.platform_mode = False self._platform_token = None self._api_key = resolved_api_key or None if resolved_api_key: headers[GATEWAY_HEADER_NAME] = f"Bearer {resolved_api_key}" - # In non-platform mode we still need to pass *some* API key to the - # OpenAI client (it validates the field). - self._openai_api_key = resolved_api_key or "unused" - - # Configuration the concrete client uses to build its OpenAI client. - self._openai_base_url = api_base_url - self._openai_default_headers = headers or None - self._openai_extra_kwargs: dict[str, Any] = {**(openai_options or {})} - # Store auth headers for batch/raw HTTP calls. - self._auth_headers: dict[str, str] = {} - if resolved_platform_token and not api_key: - self._auth_headers["Authorization"] = f"Bearer {resolved_platform_token}" - elif resolved_api_key: - self._auth_headers[GATEWAY_HEADER_NAME] = f"Bearer {resolved_api_key}" - if default_headers: - self._auth_headers.update(default_headers) + # Default headers fed into the generated ApiClient and the streaming + # shim's httpx requests. Includes the auth header for the active mode. + self._default_headers: dict[str, str] = headers + + # Control-plane (management) auth. Those endpoints expect + # ``Authorization: Bearer ``, distinct from the + # ``Otari-Key`` virtual key used for inference. In platform mode the + # platform token already serves as that bearer; for a self-hosted + # gateway the caller passes the master key as ``admin_key`` (or via + # ``GATEWAY_ADMIN_KEY``). + self._admin_token: str | None = ( + admin_key or os.environ.get(_ENV_ADMIN_KEY) or resolved_platform_token + ) # -- Error handling ----------------------------------------------------- - def _handle_error(self, error: Exception) -> None: - """Convert ``openai.APIStatusError`` to typed otari exceptions. + def _map_api_exception(self, error: ApiException) -> OtariError: + """Map a generated ``ApiException`` to a typed otari exception. - Most mappings only apply in platform mode; in non-platform mode the - original error propagates unchanged. The one exception is - :class:`UnsupportedCapabilityError`, which surfaces in both modes. - """ - if not isinstance(error, openai.APIStatusError): - return + ``ApiException`` carries ``.status`` (int) and ``.body`` (the raw JSON + string the gateway returned) plus ``.headers``. The gateway encodes the + human-readable reason under the ``detail`` key (FastAPI convention). - status = error.status_code - headers = error.response.headers - correlation_id = headers.get("x-correlation-id") - retry_after = headers.get("retry-after") + Most status mappings only apply in platform mode; in non-platform mode + the generic :class:`OtariError` is raised so the caller still gets a + single SDK exception type. The one cross-mode case is + :class:`UnsupportedCapabilityError`, surfaced in both modes. + """ + status = error.status if isinstance(error.status, int) else 0 + headers = error.headers or {} + detail = self._extract_detail(error) + correlation_id = _header_get(headers, "x-correlation-id") + retry_after = _header_get(headers, "retry-after") - detail = str(getattr(error, "message", str(error))) - if correlation_id: - detail = f"{detail} (correlation_id={correlation_id})" + full = f"{detail} (correlation_id={correlation_id})" if correlation_id else detail # Unsupported-capability is surfaced regardless of mode. if status == 400 and _UNSUPPORTED_MODERATION_RE.search(detail): provider = _parse_unsupported_provider(detail) capability = "multimodal_moderation" if "multimodal" in detail else "moderation" - raise UnsupportedCapabilityError( - detail, + return UnsupportedCapabilityError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME, provider=provider, capability=capability, - ) from error - - # The rest of the mappings only apply in platform mode. - if not self.platform_mode: - return - - if (error_cls := _STATUS_TO_ERROR.get(status)) is not None: - raise error_cls( - detail, - status_code=status, - original_error=error, - provider_name=PROVIDER_NAME, - ) from error + ) + if status in (401, 403): + return AuthenticationError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) if status == 402: - raise InsufficientFundsError( - detail, + return InsufficientFundsError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) + if status == 404: + return ModelNotFoundError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) + if status == 409: + return BatchNotCompleteError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME, - ) from error - + batch_id=_extract_batch_id(detail), + batch_status=_extract_status(detail), + ) if status == 429: - raise RateLimitError( - detail, + return RateLimitError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME, retry_after=retry_after, - ) from error - - if status == 502: - raise UpstreamProviderError( - detail, - status_code=status, - original_error=error, - provider_name=PROVIDER_NAME, - ) from error - + ) if status == 504: - raise GatewayTimeoutError( - detail, - status_code=status, - original_error=error, - provider_name=PROVIDER_NAME, - ) from error - - # Unrecognized status: let the original error propagate. - - def _build_batch_headers(self) -> dict[str, str]: - """Build the headers used for raw batch HTTP requests.""" - return { - "Content-Type": "application/json", - **self._auth_headers, - } + return GatewayTimeoutError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) + # 502 and any other 5xx are upstream-provider failures. + if status == 502 or 500 <= status < 600: + return UpstreamProviderError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) - def _map_batch_error(self, response: httpx.Response) -> None: - """Map a failed batch HTTP response to a typed SDK error. + return OtariError( + full, status_code=status, original_error=error, provider_name=PROVIDER_NAME + ) - ``response.json()`` is read synchronously, so this works for both the - sync and async clients (the async client has already received the full - body by the time it calls this). + @staticmethod + def _extract_detail(error: ApiException) -> str: + """Pull the gateway's human-readable detail from an ``ApiException`` body.""" + body = error.body + if isinstance(body, (bytes, bytearray)): + body = body.decode("utf-8", "replace") + if isinstance(body, str) and body: + try: + parsed = json.loads(body) + except (ValueError, TypeError): + return body + if isinstance(parsed, dict): + detail = parsed.get("detail") or parsed.get("message") or parsed.get("error") + if isinstance(detail, str): + return detail + if detail is not None: + return str(detail) + return body + return error.reason or "An error occurred" + + def _map_streaming_response(self, response: httpx.Response, body: bytes) -> OtariError: + """Map a failed raw streaming response to a typed otari exception. + + The SSE shim issues raw httpx requests, so it never goes through the + generated client and never raises ``ApiException``. To keep one mapping + path, adapt the failed response into an ``ApiException`` and reuse + :meth:`_map_api_exception`. """ - try: - data = response.json() - detail = data.get("detail", response.reason_phrase) - except Exception: - detail = response.reason_phrase or "" - - message = detail if isinstance(detail, str) else (response.reason_phrase or "") - correlation_id = response.headers.get("x-correlation-id") - full_message = f"{message} (correlation_id={correlation_id})" if correlation_id else message - - status = response.status_code + exc = ApiException( + status=response.status_code, + reason=response.reason_phrase, + body=body.decode("utf-8", "replace"), + ) + exc.headers = dict(response.headers) + return self._map_api_exception(exc) - if status in (401, 403): - raise AuthenticationError( - full_message, - status_code=status, - provider_name=PROVIDER_NAME, - ) - if status == 404: - msg = ( - full_message - if "not found" in full_message.lower() - else f"This gateway does not support batch operations. Upgrade your gateway. ({full_message})" - ) - raise OtariError(msg, status_code=404, provider_name=PROVIDER_NAME) +# --------------------------------------------------------------------------- +# Module-level helpers +# --------------------------------------------------------------------------- - if status == 409: - raise BatchNotCompleteError( - full_message, - status_code=409, - provider_name=PROVIDER_NAME, - batch_id=_extract_batch_id(message), - batch_status=_extract_status(message), - ) - if status == 422: - raise OtariError(full_message, status_code=422, provider_name=PROVIDER_NAME) +class _FromDict(Protocol): + """Structural type for the generated request models' ``from_dict`` classmethod.""" - if status == 429: - raise RateLimitError( - full_message, - status_code=429, - provider_name=PROVIDER_NAME, - retry_after=response.headers.get("retry-after"), - ) + @classmethod + def from_dict(cls, obj: dict[str, Any] | None) -> Any: ... - if status == 502: - raise UpstreamProviderError( - full_message, - status_code=502, - provider_name=PROVIDER_NAME, - ) - if status == 504: - raise GatewayTimeoutError( - full_message, - status_code=504, - provider_name=PROVIDER_NAME, - ) +_M = TypeVar("_M", bound=_FromDict) - raise OtariError(full_message, status_code=status, provider_name=PROVIDER_NAME) +def build_request(model: type[_M], body: dict[str, Any]) -> _M: + """Build a generated request model from ``body``, narrowing the ``Optional``. -# --------------------------------------------------------------------------- -# Module-level helpers -# --------------------------------------------------------------------------- + The generated ``from_dict`` is typed ``-> Optional[Self]`` (it returns ``None`` + only for ``None`` input); we always pass a real dict, so the result is never + ``None``. This wrapper keeps that fact in one place instead of scattering + ``# type: ignore`` across every ergonomic method. + """ + return cast("_M", model.from_dict(body)) + + +def _header_get(headers: Any, name: str) -> str | None: + """Case-insensitively read a header from a dict or HTTPHeaderDict.""" + if headers is None: + return None + getter = getattr(headers, "get", None) + if getter is not None: + value = getter(name) + if value is not None: + return str(value) + lowered = name.lower() + try: + for key, value in dict(headers).items(): + if str(key).lower() == lowered: + return str(value) + except (TypeError, ValueError): + return None + return None def _parse_unsupported_provider(detail: str) -> str: diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py new file mode 100644 index 0000000..c5d554b --- /dev/null +++ b/src/otari/_client/__init__.py @@ -0,0 +1,400 @@ +# coding: utf-8 + +# flake8: noqa + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +__version__ = "1.0.0" + +# Define package exports +__all__ = [ + "AudioApi", + "BatchesApi", + "BudgetsApi", + "ChatApi", + "EmbeddingsApi", + "HealthApi", + "ImagesApi", + "KeysApi", + "MessagesApi", + "ModelsApi", + "ModerationsApi", + "PricingApi", + "RerankApi", + "ResponsesApi", + "UsageApi", + "UsersApi", + "ApiResponse", + "ApiClient", + "Configuration", + "OpenApiException", + "ApiTypeError", + "ApiValueError", + "ApiKeyError", + "ApiAttributeError", + "ApiException", + "AudioSpeechRequest", + "BatchRequestItem", + "BudgetResponse", + "CCChatCompletionAudio", + "CCChatCompletionMessage", + "CCChatCompletionMessageCustomToolCall", + "CCChatCompletionMessageFunctionToolCall", + "CCChatCompletionMessageToolCallsInner", + "CCChatCompletionTokenLogprob", + "CCChoice", + "CCChoiceLogprobs", + "CCCompletionTokensDetails", + "CCCompletionUsage", + "CCCustom", + "CCFunction", + "CCFunctionCall", + "CCKChatCompletionTokenLogprob", + "CCKChoiceDelta", + "CCKChoiceDeltaFunctionCall", + "CCKChoiceDeltaToolCall", + "CCKChoiceDeltaToolCallFunction", + "CCKChoiceLogprobs", + "CCKChunkChoice", + "CCKCompletionTokensDetails", + "CCKCompletionUsage", + "CCKPromptTokensDetails", + "CCKReasoning", + "CCKTopLogprob", + "CCPromptTokensDetails", + "CCReasoning", + "CCTopLogprob", + "Caller", + "ChatCompletion", + "ChatCompletionChunk", + "ChatCompletionRequest", + "ChatMessageInput", + "Content", + "Content1", + "Content2", + "Content2AnyOfInner", + "Content3", + "Content4", + "Content5", + "Content6", + "Content7", + "Content8", + "Content9Inner", + "ContentAnyOfInner", + "CreateBatchRequest", + "CreateBudgetRequest", + "CreateEmbeddingResponse", + "CreateKeyRequest", + "CreateKeyResponse", + "CreateUserRequest", + "EMBEmbedding", + "EMBUsage", + "EmbeddingRequest", + "GuardrailConfig", + "HTTPValidationError", + "ImageGenerationRequest", + "Input", + "Input1", + "KeyInfo", + "LocationInner", + "MRBase64PDFSource", + "MRBashCodeExecutionOutputBlock", + "MRBashCodeExecutionResultBlock", + "MRBashCodeExecutionToolResultBlock", + "MRBashCodeExecutionToolResultError", + "MRCacheCreation", + "MRCitationCharLocation", + "MRCitationContentBlockLocation", + "MRCitationPageLocation", + "MRCitationsConfig", + "MRCitationsSearchResultLocation", + "MRCitationsWebSearchResultLocation", + "MRCodeExecutionOutputBlock", + "MRCodeExecutionResultBlock", + "MRCodeExecutionToolResultBlock", + "MRCodeExecutionToolResultError", + "MRContainer", + "MRContainerUploadBlock", + "MRDirectCaller", + "MRDocumentBlock", + "MREncryptedCodeExecutionResultBlock", + "MRPlainTextSource", + "MRRedactedThinkingBlock", + "MRRefusalStopDetails", + "MRServerToolCaller", + "MRServerToolCaller20260120", + "MRServerToolUsage", + "MRServerToolUseBlock", + "MRTextBlock", + "MRTextBlockCitationsInner", + "MRTextEditorCodeExecutionCreateResultBlock", + "MRTextEditorCodeExecutionStrReplaceResultBlock", + "MRTextEditorCodeExecutionToolResultBlock", + "MRTextEditorCodeExecutionToolResultError", + "MRTextEditorCodeExecutionViewResultBlock", + "MRThinkingBlock", + "MRToolReferenceBlock", + "MRToolSearchToolResultBlock", + "MRToolSearchToolResultError", + "MRToolSearchToolSearchResultBlock", + "MRToolUseBlock", + "MRUsage", + "MRWebFetchBlock", + "MRWebFetchToolResultBlock", + "MRWebFetchToolResultErrorBlock", + "MRWebSearchResultBlock", + "MRWebSearchToolResultBlock", + "MRWebSearchToolResultError", + "MSGAudio", + "MSGChatCompletionAssistantMessageParam", + "MSGChatCompletionContentPartImageParam", + "MSGChatCompletionContentPartInputAudioParam", + "MSGChatCompletionContentPartRefusalParam", + "MSGChatCompletionContentPartTextParam", + "MSGChatCompletionDeveloperMessageParam", + "MSGChatCompletionFunctionMessageParam", + "MSGChatCompletionMessageCustomToolCallParam", + "MSGChatCompletionMessageFunctionToolCallParam", + "MSGChatCompletionSystemMessageParam", + "MSGChatCompletionToolMessageParam", + "MSGChatCompletionUserMessageParam", + "MSGCustom", + "MSGFile", + "MSGFileFile", + "MSGFunction", + "MSGFunctionCall", + "MSGImageURL", + "MSGInputAudio", + "McpServerConfig", + "MessageResponse", + "MessagesRequest", + "Model", + "ModelListResponse", + "ModelObject", + "ModelPricingInfo", + "ModerationRequest", + "ModerationResponse", + "ModerationResult", + "PricingResponse", + "RRRerankMeta", + "RRRerankResult", + "RRRerankUsage", + "RerankRequest", + "RerankResponse", + "ResponsesRequest", + "SetPricingRequest", + "Source", + "System", + "ToolCallsInner", + "ToolChoice", + "UpdateBudgetRequest", + "UpdateKeyRequest", + "UpdateUserRequest", + "UsageEntry", + "UsageLogResponse", + "UserResponse", + "ValidationError", +] + +# import apis into sdk package +from otari._client.api.audio_api import AudioApi as AudioApi +from otari._client.api.batches_api import BatchesApi as BatchesApi +from otari._client.api.budgets_api import BudgetsApi as BudgetsApi +from otari._client.api.chat_api import ChatApi as ChatApi +from otari._client.api.embeddings_api import EmbeddingsApi as EmbeddingsApi +from otari._client.api.health_api import HealthApi as HealthApi +from otari._client.api.images_api import ImagesApi as ImagesApi +from otari._client.api.keys_api import KeysApi as KeysApi +from otari._client.api.messages_api import MessagesApi as MessagesApi +from otari._client.api.models_api import ModelsApi as ModelsApi +from otari._client.api.moderations_api import ModerationsApi as ModerationsApi +from otari._client.api.pricing_api import PricingApi as PricingApi +from otari._client.api.rerank_api import RerankApi as RerankApi +from otari._client.api.responses_api import ResponsesApi as ResponsesApi +from otari._client.api.usage_api import UsageApi as UsageApi +from otari._client.api.users_api import UsersApi as UsersApi + +# import ApiClient +from otari._client.api_response import ApiResponse as ApiResponse +from otari._client.api_client import ApiClient as ApiClient +from otari._client.configuration import Configuration as Configuration +from otari._client.exceptions import OpenApiException as OpenApiException +from otari._client.exceptions import ApiTypeError as ApiTypeError +from otari._client.exceptions import ApiValueError as ApiValueError +from otari._client.exceptions import ApiKeyError as ApiKeyError +from otari._client.exceptions import ApiAttributeError as ApiAttributeError +from otari._client.exceptions import ApiException as ApiException + +# import models into sdk package +from otari._client.models.audio_speech_request import AudioSpeechRequest as AudioSpeechRequest +from otari._client.models.batch_request_item import BatchRequestItem as BatchRequestItem +from otari._client.models.budget_response import BudgetResponse as BudgetResponse +from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio as CCChatCompletionAudio +from otari._client.models.cc_chat_completion_message import CCChatCompletionMessage as CCChatCompletionMessage +from otari._client.models.cc_chat_completion_message_custom_tool_call import CCChatCompletionMessageCustomToolCall as CCChatCompletionMessageCustomToolCall +from otari._client.models.cc_chat_completion_message_function_tool_call import CCChatCompletionMessageFunctionToolCall as CCChatCompletionMessageFunctionToolCall +from otari._client.models.cc_chat_completion_message_tool_calls_inner import CCChatCompletionMessageToolCallsInner as CCChatCompletionMessageToolCallsInner +from otari._client.models.cc_chat_completion_token_logprob import CCChatCompletionTokenLogprob as CCChatCompletionTokenLogprob +from otari._client.models.cc_choice import CCChoice as CCChoice +from otari._client.models.cc_choice_logprobs import CCChoiceLogprobs as CCChoiceLogprobs +from otari._client.models.cc_completion_tokens_details import CCCompletionTokensDetails as CCCompletionTokensDetails +from otari._client.models.cc_completion_usage import CCCompletionUsage as CCCompletionUsage +from otari._client.models.cc_custom import CCCustom as CCCustom +from otari._client.models.cc_function import CCFunction as CCFunction +from otari._client.models.cc_function_call import CCFunctionCall as CCFunctionCall +from otari._client.models.cck_chat_completion_token_logprob import CCKChatCompletionTokenLogprob as CCKChatCompletionTokenLogprob +from otari._client.models.cck_choice_delta import CCKChoiceDelta as CCKChoiceDelta +from otari._client.models.cck_choice_delta_function_call import CCKChoiceDeltaFunctionCall as CCKChoiceDeltaFunctionCall +from otari._client.models.cck_choice_delta_tool_call import CCKChoiceDeltaToolCall as CCKChoiceDeltaToolCall +from otari._client.models.cck_choice_delta_tool_call_function import CCKChoiceDeltaToolCallFunction as CCKChoiceDeltaToolCallFunction +from otari._client.models.cck_choice_logprobs import CCKChoiceLogprobs as CCKChoiceLogprobs +from otari._client.models.cck_chunk_choice import CCKChunkChoice as CCKChunkChoice +from otari._client.models.cck_completion_tokens_details import CCKCompletionTokensDetails as CCKCompletionTokensDetails +from otari._client.models.cck_completion_usage import CCKCompletionUsage as CCKCompletionUsage +from otari._client.models.cck_prompt_tokens_details import CCKPromptTokensDetails as CCKPromptTokensDetails +from otari._client.models.cck_reasoning import CCKReasoning as CCKReasoning +from otari._client.models.cck_top_logprob import CCKTopLogprob as CCKTopLogprob +from otari._client.models.cc_prompt_tokens_details import CCPromptTokensDetails as CCPromptTokensDetails +from otari._client.models.cc_reasoning import CCReasoning as CCReasoning +from otari._client.models.cc_top_logprob import CCTopLogprob as CCTopLogprob +from otari._client.models.caller import Caller as Caller +from otari._client.models.chat_completion import ChatCompletion as ChatCompletion +from otari._client.models.chat_completion_chunk import ChatCompletionChunk as ChatCompletionChunk +from otari._client.models.chat_completion_request import ChatCompletionRequest as ChatCompletionRequest +from otari._client.models.chat_message_input import ChatMessageInput as ChatMessageInput +from otari._client.models.content import Content as Content +from otari._client.models.content1 import Content1 as Content1 +from otari._client.models.content2 import Content2 as Content2 +from otari._client.models.content2_any_of_inner import Content2AnyOfInner as Content2AnyOfInner +from otari._client.models.content3 import Content3 as Content3 +from otari._client.models.content4 import Content4 as Content4 +from otari._client.models.content5 import Content5 as Content5 +from otari._client.models.content6 import Content6 as Content6 +from otari._client.models.content7 import Content7 as Content7 +from otari._client.models.content8 import Content8 as Content8 +from otari._client.models.content9_inner import Content9Inner as Content9Inner +from otari._client.models.content_any_of_inner import ContentAnyOfInner as ContentAnyOfInner +from otari._client.models.create_batch_request import CreateBatchRequest as CreateBatchRequest +from otari._client.models.create_budget_request import CreateBudgetRequest as CreateBudgetRequest +from otari._client.models.create_embedding_response import CreateEmbeddingResponse as CreateEmbeddingResponse +from otari._client.models.create_key_request import CreateKeyRequest as CreateKeyRequest +from otari._client.models.create_key_response import CreateKeyResponse as CreateKeyResponse +from otari._client.models.create_user_request import CreateUserRequest as CreateUserRequest +from otari._client.models.emb_embedding import EMBEmbedding as EMBEmbedding +from otari._client.models.emb_usage import EMBUsage as EMBUsage +from otari._client.models.embedding_request import EmbeddingRequest as EmbeddingRequest +from otari._client.models.guardrail_config import GuardrailConfig as GuardrailConfig +from otari._client.models.http_validation_error import HTTPValidationError as HTTPValidationError +from otari._client.models.image_generation_request import ImageGenerationRequest as ImageGenerationRequest +from otari._client.models.input import Input as Input +from otari._client.models.input1 import Input1 as Input1 +from otari._client.models.key_info import KeyInfo as KeyInfo +from otari._client.models.location_inner import LocationInner as LocationInner +from otari._client.models.mr_base64_pdf_source import MRBase64PDFSource as MRBase64PDFSource +from otari._client.models.mr_bash_code_execution_output_block import MRBashCodeExecutionOutputBlock as MRBashCodeExecutionOutputBlock +from otari._client.models.mr_bash_code_execution_result_block import MRBashCodeExecutionResultBlock as MRBashCodeExecutionResultBlock +from otari._client.models.mr_bash_code_execution_tool_result_block import MRBashCodeExecutionToolResultBlock as MRBashCodeExecutionToolResultBlock +from otari._client.models.mr_bash_code_execution_tool_result_error import MRBashCodeExecutionToolResultError as MRBashCodeExecutionToolResultError +from otari._client.models.mr_cache_creation import MRCacheCreation as MRCacheCreation +from otari._client.models.mr_citation_char_location import MRCitationCharLocation as MRCitationCharLocation +from otari._client.models.mr_citation_content_block_location import MRCitationContentBlockLocation as MRCitationContentBlockLocation +from otari._client.models.mr_citation_page_location import MRCitationPageLocation as MRCitationPageLocation +from otari._client.models.mr_citations_config import MRCitationsConfig as MRCitationsConfig +from otari._client.models.mr_citations_search_result_location import MRCitationsSearchResultLocation as MRCitationsSearchResultLocation +from otari._client.models.mr_citations_web_search_result_location import MRCitationsWebSearchResultLocation as MRCitationsWebSearchResultLocation +from otari._client.models.mr_code_execution_output_block import MRCodeExecutionOutputBlock as MRCodeExecutionOutputBlock +from otari._client.models.mr_code_execution_result_block import MRCodeExecutionResultBlock as MRCodeExecutionResultBlock +from otari._client.models.mr_code_execution_tool_result_block import MRCodeExecutionToolResultBlock as MRCodeExecutionToolResultBlock +from otari._client.models.mr_code_execution_tool_result_error import MRCodeExecutionToolResultError as MRCodeExecutionToolResultError +from otari._client.models.mr_container import MRContainer as MRContainer +from otari._client.models.mr_container_upload_block import MRContainerUploadBlock as MRContainerUploadBlock +from otari._client.models.mr_direct_caller import MRDirectCaller as MRDirectCaller +from otari._client.models.mr_document_block import MRDocumentBlock as MRDocumentBlock +from otari._client.models.mr_encrypted_code_execution_result_block import MREncryptedCodeExecutionResultBlock as MREncryptedCodeExecutionResultBlock +from otari._client.models.mr_plain_text_source import MRPlainTextSource as MRPlainTextSource +from otari._client.models.mr_redacted_thinking_block import MRRedactedThinkingBlock as MRRedactedThinkingBlock +from otari._client.models.mr_refusal_stop_details import MRRefusalStopDetails as MRRefusalStopDetails +from otari._client.models.mr_server_tool_caller import MRServerToolCaller as MRServerToolCaller +from otari._client.models.mr_server_tool_caller20260120 import MRServerToolCaller20260120 as MRServerToolCaller20260120 +from otari._client.models.mr_server_tool_usage import MRServerToolUsage as MRServerToolUsage +from otari._client.models.mr_server_tool_use_block import MRServerToolUseBlock as MRServerToolUseBlock +from otari._client.models.mr_text_block import MRTextBlock as MRTextBlock +from otari._client.models.mr_text_block_citations_inner import MRTextBlockCitationsInner as MRTextBlockCitationsInner +from otari._client.models.mr_text_editor_code_execution_create_result_block import MRTextEditorCodeExecutionCreateResultBlock as MRTextEditorCodeExecutionCreateResultBlock +from otari._client.models.mr_text_editor_code_execution_str_replace_result_block import MRTextEditorCodeExecutionStrReplaceResultBlock as MRTextEditorCodeExecutionStrReplaceResultBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_block import MRTextEditorCodeExecutionToolResultBlock as MRTextEditorCodeExecutionToolResultBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_error import MRTextEditorCodeExecutionToolResultError as MRTextEditorCodeExecutionToolResultError +from otari._client.models.mr_text_editor_code_execution_view_result_block import MRTextEditorCodeExecutionViewResultBlock as MRTextEditorCodeExecutionViewResultBlock +from otari._client.models.mr_thinking_block import MRThinkingBlock as MRThinkingBlock +from otari._client.models.mr_tool_reference_block import MRToolReferenceBlock as MRToolReferenceBlock +from otari._client.models.mr_tool_search_tool_result_block import MRToolSearchToolResultBlock as MRToolSearchToolResultBlock +from otari._client.models.mr_tool_search_tool_result_error import MRToolSearchToolResultError as MRToolSearchToolResultError +from otari._client.models.mr_tool_search_tool_search_result_block import MRToolSearchToolSearchResultBlock as MRToolSearchToolSearchResultBlock +from otari._client.models.mr_tool_use_block import MRToolUseBlock as MRToolUseBlock +from otari._client.models.mr_usage import MRUsage as MRUsage +from otari._client.models.mr_web_fetch_block import MRWebFetchBlock as MRWebFetchBlock +from otari._client.models.mr_web_fetch_tool_result_block import MRWebFetchToolResultBlock as MRWebFetchToolResultBlock +from otari._client.models.mr_web_fetch_tool_result_error_block import MRWebFetchToolResultErrorBlock as MRWebFetchToolResultErrorBlock +from otari._client.models.mr_web_search_result_block import MRWebSearchResultBlock as MRWebSearchResultBlock +from otari._client.models.mr_web_search_tool_result_block import MRWebSearchToolResultBlock as MRWebSearchToolResultBlock +from otari._client.models.mr_web_search_tool_result_error import MRWebSearchToolResultError as MRWebSearchToolResultError +from otari._client.models.msg_audio import MSGAudio as MSGAudio +from otari._client.models.msg_chat_completion_assistant_message_param import MSGChatCompletionAssistantMessageParam as MSGChatCompletionAssistantMessageParam +from otari._client.models.msg_chat_completion_content_part_image_param import MSGChatCompletionContentPartImageParam as MSGChatCompletionContentPartImageParam +from otari._client.models.msg_chat_completion_content_part_input_audio_param import MSGChatCompletionContentPartInputAudioParam as MSGChatCompletionContentPartInputAudioParam +from otari._client.models.msg_chat_completion_content_part_refusal_param import MSGChatCompletionContentPartRefusalParam as MSGChatCompletionContentPartRefusalParam +from otari._client.models.msg_chat_completion_content_part_text_param import MSGChatCompletionContentPartTextParam as MSGChatCompletionContentPartTextParam +from otari._client.models.msg_chat_completion_developer_message_param import MSGChatCompletionDeveloperMessageParam as MSGChatCompletionDeveloperMessageParam +from otari._client.models.msg_chat_completion_function_message_param import MSGChatCompletionFunctionMessageParam as MSGChatCompletionFunctionMessageParam +from otari._client.models.msg_chat_completion_message_custom_tool_call_param import MSGChatCompletionMessageCustomToolCallParam as MSGChatCompletionMessageCustomToolCallParam +from otari._client.models.msg_chat_completion_message_function_tool_call_param import MSGChatCompletionMessageFunctionToolCallParam as MSGChatCompletionMessageFunctionToolCallParam +from otari._client.models.msg_chat_completion_system_message_param import MSGChatCompletionSystemMessageParam as MSGChatCompletionSystemMessageParam +from otari._client.models.msg_chat_completion_tool_message_param import MSGChatCompletionToolMessageParam as MSGChatCompletionToolMessageParam +from otari._client.models.msg_chat_completion_user_message_param import MSGChatCompletionUserMessageParam as MSGChatCompletionUserMessageParam +from otari._client.models.msg_custom import MSGCustom as MSGCustom +from otari._client.models.msg_file import MSGFile as MSGFile +from otari._client.models.msg_file_file import MSGFileFile as MSGFileFile +from otari._client.models.msg_function import MSGFunction as MSGFunction +from otari._client.models.msg_function_call import MSGFunctionCall as MSGFunctionCall +from otari._client.models.msg_image_url import MSGImageURL as MSGImageURL +from otari._client.models.msg_input_audio import MSGInputAudio as MSGInputAudio +from otari._client.models.mcp_server_config import McpServerConfig as McpServerConfig +from otari._client.models.message_response import MessageResponse as MessageResponse +from otari._client.models.messages_request import MessagesRequest as MessagesRequest +from otari._client.models.model import Model as Model +from otari._client.models.model_list_response import ModelListResponse as ModelListResponse +from otari._client.models.model_object import ModelObject as ModelObject +from otari._client.models.model_pricing_info import ModelPricingInfo as ModelPricingInfo +from otari._client.models.moderation_request import ModerationRequest as ModerationRequest +from otari._client.models.moderation_response import ModerationResponse as ModerationResponse +from otari._client.models.moderation_result import ModerationResult as ModerationResult +from otari._client.models.pricing_response import PricingResponse as PricingResponse +from otari._client.models.rr_rerank_meta import RRRerankMeta as RRRerankMeta +from otari._client.models.rr_rerank_result import RRRerankResult as RRRerankResult +from otari._client.models.rr_rerank_usage import RRRerankUsage as RRRerankUsage +from otari._client.models.rerank_request import RerankRequest as RerankRequest +from otari._client.models.rerank_response import RerankResponse as RerankResponse +from otari._client.models.responses_request import ResponsesRequest as ResponsesRequest +from otari._client.models.set_pricing_request import SetPricingRequest as SetPricingRequest +from otari._client.models.source import Source as Source +from otari._client.models.system import System as System +from otari._client.models.tool_calls_inner import ToolCallsInner as ToolCallsInner +from otari._client.models.tool_choice import ToolChoice as ToolChoice +from otari._client.models.update_budget_request import UpdateBudgetRequest as UpdateBudgetRequest +from otari._client.models.update_key_request import UpdateKeyRequest as UpdateKeyRequest +from otari._client.models.update_user_request import UpdateUserRequest as UpdateUserRequest +from otari._client.models.usage_entry import UsageEntry as UsageEntry +from otari._client.models.usage_log_response import UsageLogResponse as UsageLogResponse +from otari._client.models.user_response import UserResponse as UserResponse +from otari._client.models.validation_error import ValidationError as ValidationError + diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py new file mode 100644 index 0000000..460b2a7 --- /dev/null +++ b/src/otari/_client/api/__init__.py @@ -0,0 +1,20 @@ +# flake8: noqa + +# import apis into api package +from otari._client.api.audio_api import AudioApi +from otari._client.api.batches_api import BatchesApi +from otari._client.api.budgets_api import BudgetsApi +from otari._client.api.chat_api import ChatApi +from otari._client.api.embeddings_api import EmbeddingsApi +from otari._client.api.health_api import HealthApi +from otari._client.api.images_api import ImagesApi +from otari._client.api.keys_api import KeysApi +from otari._client.api.messages_api import MessagesApi +from otari._client.api.models_api import ModelsApi +from otari._client.api.moderations_api import ModerationsApi +from otari._client.api.pricing_api import PricingApi +from otari._client.api.rerank_api import RerankApi +from otari._client.api.responses_api import ResponsesApi +from otari._client.api.usage_api import UsageApi +from otari._client.api.users_api import UsersApi + diff --git a/src/otari/_client/api/audio_api.py b/src/otari/_client/api/audio_api.py new file mode 100644 index 0000000..2418145 --- /dev/null +++ b/src/otari/_client/api/audio_api.py @@ -0,0 +1,685 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import StrictFloat, StrictInt, StrictStr +from typing import Any, Optional, Union +from otari._client.models.audio_speech_request import AudioSpeechRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class AudioApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_speech_v1_audio_speech_post( + self, + audio_speech_request: AudioSpeechRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Create Speech + + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param audio_speech_request: (required) + :type audio_speech_request: AudioSpeechRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_speech_v1_audio_speech_post_serialize( + audio_speech_request=audio_speech_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_speech_v1_audio_speech_post_with_http_info( + self, + audio_speech_request: AudioSpeechRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Create Speech + + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param audio_speech_request: (required) + :type audio_speech_request: AudioSpeechRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_speech_v1_audio_speech_post_serialize( + audio_speech_request=audio_speech_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_speech_v1_audio_speech_post_without_preload_content( + self, + audio_speech_request: AudioSpeechRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Speech + + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param audio_speech_request: (required) + :type audio_speech_request: AudioSpeechRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_speech_v1_audio_speech_post_serialize( + audio_speech_request=audio_speech_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_speech_v1_audio_speech_post_serialize( + self, + audio_speech_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if audio_speech_request is not None: + _body_params = audio_speech_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'audio/L16', + 'audio/aac', + 'audio/flac', + 'audio/mpeg', + 'audio/opus', + 'audio/wav' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/audio/speech', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def create_transcription_v1_audio_transcriptions_post( + self, + file: StrictStr, + model: StrictStr, + language: Optional[StrictStr] = None, + prompt: Optional[StrictStr] = None, + response_format: Optional[StrictStr] = None, + temperature: Optional[Union[StrictFloat, StrictInt]] = None, + user: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Create Transcription + + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param file: (required) + :type file: str + :param model: (required) + :type model: str + :param language: + :type language: str + :param prompt: + :type prompt: str + :param response_format: + :type response_format: str + :param temperature: + :type temperature: float + :param user: + :type user: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_transcription_v1_audio_transcriptions_post_serialize( + file=file, + model=model, + language=language, + prompt=prompt, + response_format=response_format, + temperature=temperature, + user=user, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_transcription_v1_audio_transcriptions_post_with_http_info( + self, + file: StrictStr, + model: StrictStr, + language: Optional[StrictStr] = None, + prompt: Optional[StrictStr] = None, + response_format: Optional[StrictStr] = None, + temperature: Optional[Union[StrictFloat, StrictInt]] = None, + user: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Create Transcription + + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param file: (required) + :type file: str + :param model: (required) + :type model: str + :param language: + :type language: str + :param prompt: + :type prompt: str + :param response_format: + :type response_format: str + :param temperature: + :type temperature: float + :param user: + :type user: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_transcription_v1_audio_transcriptions_post_serialize( + file=file, + model=model, + language=language, + prompt=prompt, + response_format=response_format, + temperature=temperature, + user=user, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_transcription_v1_audio_transcriptions_post_without_preload_content( + self, + file: StrictStr, + model: StrictStr, + language: Optional[StrictStr] = None, + prompt: Optional[StrictStr] = None, + response_format: Optional[StrictStr] = None, + temperature: Optional[Union[StrictFloat, StrictInt]] = None, + user: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Transcription + + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param file: (required) + :type file: str + :param model: (required) + :type model: str + :param language: + :type language: str + :param prompt: + :type prompt: str + :param response_format: + :type response_format: str + :param temperature: + :type temperature: float + :param user: + :type user: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_transcription_v1_audio_transcriptions_post_serialize( + file=file, + model=model, + language=language, + prompt=prompt, + response_format=response_format, + temperature=temperature, + user=user, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_transcription_v1_audio_transcriptions_post_serialize( + self, + file, + model, + language, + prompt, + response_format, + temperature, + user, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + if file is not None: + _form_params.append(('file', file)) + if language is not None: + _form_params.append(('language', language)) + if model is not None: + _form_params.append(('model', model)) + if prompt is not None: + _form_params.append(('prompt', prompt)) + if response_format is not None: + _form_params.append(('response_format', response_format)) + if temperature is not None: + _form_params.append(('temperature', temperature)) + if user is not None: + _form_params.append(('user', user)) + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'multipart/form-data' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/audio/transcriptions', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/batches_api.py b/src/otari/_client/api/batches_api.py new file mode 100644 index 0000000..64614c8 --- /dev/null +++ b/src/otari/_client/api/batches_api.py @@ -0,0 +1,1458 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import StrictInt, StrictStr +from typing import Any, Optional +from otari._client.models.create_batch_request import CreateBatchRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class BatchesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def cancel_batch_v1_batches_batch_id_cancel_post( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Cancel Batch + + Cancel a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._cancel_batch_v1_batches_batch_id_cancel_post_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def cancel_batch_v1_batches_batch_id_cancel_post_with_http_info( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Cancel Batch + + Cancel a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._cancel_batch_v1_batches_batch_id_cancel_post_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def cancel_batch_v1_batches_batch_id_cancel_post_without_preload_content( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Cancel Batch + + Cancel a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._cancel_batch_v1_batches_batch_id_cancel_post_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _cancel_batch_v1_batches_batch_id_cancel_post_serialize( + self, + batch_id, + provider, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if batch_id is not None: + _path_params['batch_id'] = batch_id + # process the query parameters + if provider is not None: + + _query_params.append(('provider', provider)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/batches/{batch_id}/cancel', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def create_batch_v1_batches_post( + self, + create_batch_request: CreateBatchRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Create Batch + + Create a batch of LLM requests for asynchronous processing. + + :param create_batch_request: (required) + :type create_batch_request: CreateBatchRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_batch_v1_batches_post_serialize( + create_batch_request=create_batch_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_batch_v1_batches_post_with_http_info( + self, + create_batch_request: CreateBatchRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Create Batch + + Create a batch of LLM requests for asynchronous processing. + + :param create_batch_request: (required) + :type create_batch_request: CreateBatchRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_batch_v1_batches_post_serialize( + create_batch_request=create_batch_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_batch_v1_batches_post_without_preload_content( + self, + create_batch_request: CreateBatchRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Batch + + Create a batch of LLM requests for asynchronous processing. + + :param create_batch_request: (required) + :type create_batch_request: CreateBatchRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_batch_v1_batches_post_serialize( + create_batch_request=create_batch_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_batch_v1_batches_post_serialize( + self, + create_batch_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_batch_request is not None: + _body_params = create_batch_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/batches', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_batches_v1_batches_get( + self, + provider: StrictStr, + after: Optional[StrictStr] = None, + limit: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """List Batches + + List batches for a provider. + + :param provider: (required) + :type provider: str + :param after: + :type after: str + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_batches_v1_batches_get_serialize( + provider=provider, + after=after, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_batches_v1_batches_get_with_http_info( + self, + provider: StrictStr, + after: Optional[StrictStr] = None, + limit: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """List Batches + + List batches for a provider. + + :param provider: (required) + :type provider: str + :param after: + :type after: str + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_batches_v1_batches_get_serialize( + provider=provider, + after=after, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_batches_v1_batches_get_without_preload_content( + self, + provider: StrictStr, + after: Optional[StrictStr] = None, + limit: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Batches + + List batches for a provider. + + :param provider: (required) + :type provider: str + :param after: + :type after: str + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_batches_v1_batches_get_serialize( + provider=provider, + after=after, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_batches_v1_batches_get_serialize( + self, + provider, + after, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if provider is not None: + + _query_params.append(('provider', provider)) + + if after is not None: + + _query_params.append(('after', after)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/batches', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def retrieve_batch_results_v1_batches_batch_id_results_get( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Retrieve Batch Results + + Retrieve the results of a completed batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_results_v1_batches_batch_id_results_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '409': None, + '422': "HTTPValidationError", + '502': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def retrieve_batch_results_v1_batches_batch_id_results_get_with_http_info( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Retrieve Batch Results + + Retrieve the results of a completed batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_results_v1_batches_batch_id_results_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '409': None, + '422': "HTTPValidationError", + '502': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def retrieve_batch_results_v1_batches_batch_id_results_get_without_preload_content( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Retrieve Batch Results + + Retrieve the results of a completed batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_results_v1_batches_batch_id_results_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '409': None, + '422': "HTTPValidationError", + '502': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _retrieve_batch_results_v1_batches_batch_id_results_get_serialize( + self, + batch_id, + provider, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if batch_id is not None: + _path_params['batch_id'] = batch_id + # process the query parameters + if provider is not None: + + _query_params.append(('provider', provider)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/batches/{batch_id}/results', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def retrieve_batch_v1_batches_batch_id_get( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Retrieve Batch + + Retrieve the status of a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_v1_batches_batch_id_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def retrieve_batch_v1_batches_batch_id_get_with_http_info( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Retrieve Batch + + Retrieve the status of a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_v1_batches_batch_id_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def retrieve_batch_v1_batches_batch_id_get_without_preload_content( + self, + batch_id: StrictStr, + provider: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Retrieve Batch + + Retrieve the status of a batch. + + :param batch_id: (required) + :type batch_id: str + :param provider: (required) + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._retrieve_batch_v1_batches_batch_id_get_serialize( + batch_id=batch_id, + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _retrieve_batch_v1_batches_batch_id_get_serialize( + self, + batch_id, + provider, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if batch_id is not None: + _path_params['batch_id'] = batch_id + # process the query parameters + if provider is not None: + + _query_params.append(('provider', provider)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/batches/{batch_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/budgets_api.py b/src/otari/_client/api/budgets_api.py new file mode 100644 index 0000000..a78e6b0 --- /dev/null +++ b/src/otari/_client/api/budgets_api.py @@ -0,0 +1,1415 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.budget_response import BudgetResponse +from otari._client.models.create_budget_request import CreateBudgetRequest +from otari._client.models.update_budget_request import UpdateBudgetRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class BudgetsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_budget_v1_budgets_post( + self, + create_budget_request: CreateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> BudgetResponse: + """Create Budget + + Create a new budget. + + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_budget_v1_budgets_post_serialize( + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_budget_v1_budgets_post_with_http_info( + self, + create_budget_request: CreateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[BudgetResponse]: + """Create Budget + + Create a new budget. + + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_budget_v1_budgets_post_serialize( + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_budget_v1_budgets_post_without_preload_content( + self, + create_budget_request: CreateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Budget + + Create a new budget. + + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_budget_v1_budgets_post_serialize( + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_budget_v1_budgets_post_serialize( + self, + create_budget_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_budget_request is not None: + _body_params = create_budget_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/budgets', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_budget_v1_budgets_budget_id_delete( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Delete Budget + + Delete a budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_budget_v1_budgets_budget_id_delete_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_budget_v1_budgets_budget_id_delete_with_http_info( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Delete Budget + + Delete a budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_budget_v1_budgets_budget_id_delete_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_budget_v1_budgets_budget_id_delete_without_preload_content( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Budget + + Delete a budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_budget_v1_budgets_budget_id_delete_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_budget_v1_budgets_budget_id_delete_serialize( + self, + budget_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if budget_id is not None: + _path_params['budget_id'] = budget_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/budgets/{budget_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_budget_v1_budgets_budget_id_get( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> BudgetResponse: + """Get Budget + + Get details of a specific budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_budget_v1_budgets_budget_id_get_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_budget_v1_budgets_budget_id_get_with_http_info( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[BudgetResponse]: + """Get Budget + + Get details of a specific budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_budget_v1_budgets_budget_id_get_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_budget_v1_budgets_budget_id_get_without_preload_content( + self, + budget_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Budget + + Get details of a specific budget. + + :param budget_id: (required) + :type budget_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_budget_v1_budgets_budget_id_get_serialize( + budget_id=budget_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_budget_v1_budgets_budget_id_get_serialize( + self, + budget_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if budget_id is not None: + _path_params['budget_id'] = budget_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/budgets/{budget_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_budgets_v1_budgets_get( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[BudgetResponse]: + """List Budgets + + List all budgets with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budgets_v1_budgets_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_budgets_v1_budgets_get_with_http_info( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[BudgetResponse]]: + """List Budgets + + List all budgets with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budgets_v1_budgets_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_budgets_v1_budgets_get_without_preload_content( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Budgets + + List all budgets with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budgets_v1_budgets_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_budgets_v1_budgets_get_serialize( + self, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/budgets', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_budget_v1_budgets_budget_id_patch( + self, + budget_id: StrictStr, + update_budget_request: UpdateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> BudgetResponse: + """Update Budget + + Update a budget. + + :param budget_id: (required) + :type budget_id: str + :param update_budget_request: (required) + :type update_budget_request: UpdateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_budget_v1_budgets_budget_id_patch_serialize( + budget_id=budget_id, + update_budget_request=update_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_budget_v1_budgets_budget_id_patch_with_http_info( + self, + budget_id: StrictStr, + update_budget_request: UpdateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[BudgetResponse]: + """Update Budget + + Update a budget. + + :param budget_id: (required) + :type budget_id: str + :param update_budget_request: (required) + :type update_budget_request: UpdateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_budget_v1_budgets_budget_id_patch_serialize( + budget_id=budget_id, + update_budget_request=update_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_budget_v1_budgets_budget_id_patch_without_preload_content( + self, + budget_id: StrictStr, + update_budget_request: UpdateBudgetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update Budget + + Update a budget. + + :param budget_id: (required) + :type budget_id: str + :param update_budget_request: (required) + :type update_budget_request: UpdateBudgetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_budget_v1_budgets_budget_id_patch_serialize( + budget_id=budget_id, + update_budget_request=update_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_budget_v1_budgets_budget_id_patch_serialize( + self, + budget_id, + update_budget_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if budget_id is not None: + _path_params['budget_id'] = budget_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_budget_request is not None: + _body_params = update_budget_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/budgets/{budget_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/chat_api.py b/src/otari/_client/api/chat_api.py new file mode 100644 index 0000000..8e4b9aa --- /dev/null +++ b/src/otari/_client/api/chat_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from otari._client.models.chat_completion import ChatCompletion +from otari._client.models.chat_completion_request import ChatCompletionRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ChatApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def chat_completions_v1_chat_completions_post( + self, + chat_completion_request: ChatCompletionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ChatCompletion: + """Chat Completions + + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param chat_completion_request: (required) + :type chat_completion_request: ChatCompletionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._chat_completions_v1_chat_completions_post_serialize( + chat_completion_request=chat_completion_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChatCompletion", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def chat_completions_v1_chat_completions_post_with_http_info( + self, + chat_completion_request: ChatCompletionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ChatCompletion]: + """Chat Completions + + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param chat_completion_request: (required) + :type chat_completion_request: ChatCompletionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._chat_completions_v1_chat_completions_post_serialize( + chat_completion_request=chat_completion_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChatCompletion", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def chat_completions_v1_chat_completions_post_without_preload_content( + self, + chat_completion_request: ChatCompletionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Chat Completions + + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param chat_completion_request: (required) + :type chat_completion_request: ChatCompletionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._chat_completions_v1_chat_completions_post_serialize( + chat_completion_request=chat_completion_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChatCompletion", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _chat_completions_v1_chat_completions_post_serialize( + self, + chat_completion_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if chat_completion_request is not None: + _body_params = chat_completion_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/chat/completions', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/embeddings_api.py b/src/otari/_client/api/embeddings_api.py new file mode 100644 index 0000000..dc1879a --- /dev/null +++ b/src/otari/_client/api/embeddings_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from otari._client.models.create_embedding_response import CreateEmbeddingResponse +from otari._client.models.embedding_request import EmbeddingRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class EmbeddingsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_embedding_v1_embeddings_post( + self, + embedding_request: EmbeddingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> CreateEmbeddingResponse: + """Create Embedding + + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param embedding_request: (required) + :type embedding_request: EmbeddingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_embedding_v1_embeddings_post_serialize( + embedding_request=embedding_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateEmbeddingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_embedding_v1_embeddings_post_with_http_info( + self, + embedding_request: EmbeddingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[CreateEmbeddingResponse]: + """Create Embedding + + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param embedding_request: (required) + :type embedding_request: EmbeddingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_embedding_v1_embeddings_post_serialize( + embedding_request=embedding_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateEmbeddingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_embedding_v1_embeddings_post_without_preload_content( + self, + embedding_request: EmbeddingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Embedding + + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param embedding_request: (required) + :type embedding_request: EmbeddingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_embedding_v1_embeddings_post_serialize( + embedding_request=embedding_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateEmbeddingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_embedding_v1_embeddings_post_serialize( + self, + embedding_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if embedding_request is not None: + _body_params = embedding_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/embeddings', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/health_api.py b/src/otari/_client/api/health_api.py new file mode 100644 index 0000000..4248817 --- /dev/null +++ b/src/otari/_client/api/health_api.py @@ -0,0 +1,771 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import StrictStr +from typing import Any, Dict + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class HealthApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def health_check_health_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Dict[str, str]: + """Health Check + + General health check endpoint. Returns basic health status. For infrastructure monitoring, use /health/readiness or /health/liveness instead. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_check_health_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, str]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def health_check_health_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Dict[str, str]]: + """Health Check + + General health check endpoint. Returns basic health status. For infrastructure monitoring, use /health/readiness or /health/liveness instead. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_check_health_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, str]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def health_check_health_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Health Check + + General health check endpoint. Returns basic health status. For infrastructure monitoring, use /health/readiness or /health/liveness instead. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_check_health_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, str]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _health_check_health_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def health_liveness_health_liveness_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> str: + """Health Liveness + + Liveness probe endpoint. Simple check to verify the process is alive and responding. Used by Kubernetes/container orchestrators for liveness probes. Returns: Plain text \"I'm alive!\" message + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_liveness_health_liveness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "str", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def health_liveness_health_liveness_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[str]: + """Health Liveness + + Liveness probe endpoint. Simple check to verify the process is alive and responding. Used by Kubernetes/container orchestrators for liveness probes. Returns: Plain text \"I'm alive!\" message + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_liveness_health_liveness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "str", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def health_liveness_health_liveness_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Health Liveness + + Liveness probe endpoint. Simple check to verify the process is alive and responding. Used by Kubernetes/container orchestrators for liveness probes. Returns: Plain text \"I'm alive!\" message + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_liveness_health_liveness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "str", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _health_liveness_health_liveness_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health/liveness', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def health_readiness_health_readiness_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Dict[str, object]: + """Health Readiness + + Readiness probe endpoint. Checks if the gateway is ready to serve requests by validating: - Database connectivity - Service availability Used by Kubernetes/container orchestrators for readiness probes. Returns HTTP 503 if any dependency is unavailable. Returns: dict: Status object with health details Raises: HTTPException: 503 if service is not ready + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_readiness_health_readiness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, object]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def health_readiness_health_readiness_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Dict[str, object]]: + """Health Readiness + + Readiness probe endpoint. Checks if the gateway is ready to serve requests by validating: - Database connectivity - Service availability Used by Kubernetes/container orchestrators for readiness probes. Returns HTTP 503 if any dependency is unavailable. Returns: dict: Status object with health details Raises: HTTPException: 503 if service is not ready + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_readiness_health_readiness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, object]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def health_readiness_health_readiness_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Health Readiness + + Readiness probe endpoint. Checks if the gateway is ready to serve requests by validating: - Database connectivity - Service availability Used by Kubernetes/container orchestrators for readiness probes. Returns HTTP 503 if any dependency is unavailable. Returns: dict: Status object with health details Raises: HTTPException: 503 if service is not ready + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._health_readiness_health_readiness_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Dict[str, object]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _health_readiness_health_readiness_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health/readiness', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/images_api.py b/src/otari/_client/api/images_api.py new file mode 100644 index 0000000..f5b26ab --- /dev/null +++ b/src/otari/_client/api/images_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from typing import Any +from otari._client.models.image_generation_request import ImageGenerationRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ImagesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_image_v1_images_generations_post( + self, + image_generation_request: ImageGenerationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Create Image + + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param image_generation_request: (required) + :type image_generation_request: ImageGenerationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_image_v1_images_generations_post_serialize( + image_generation_request=image_generation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_image_v1_images_generations_post_with_http_info( + self, + image_generation_request: ImageGenerationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Create Image + + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param image_generation_request: (required) + :type image_generation_request: ImageGenerationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_image_v1_images_generations_post_serialize( + image_generation_request=image_generation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_image_v1_images_generations_post_without_preload_content( + self, + image_generation_request: ImageGenerationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Image + + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param image_generation_request: (required) + :type image_generation_request: ImageGenerationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_image_v1_images_generations_post_serialize( + image_generation_request=image_generation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_image_v1_images_generations_post_serialize( + self, + image_generation_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if image_generation_request is not None: + _body_params = image_generation_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/images/generations', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/keys_api.py b/src/otari/_client/api/keys_api.py new file mode 100644 index 0000000..1a9432b --- /dev/null +++ b/src/otari/_client/api/keys_api.py @@ -0,0 +1,1416 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.create_key_request import CreateKeyRequest +from otari._client.models.create_key_response import CreateKeyResponse +from otari._client.models.key_info import KeyInfo +from otari._client.models.update_key_request import UpdateKeyRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class KeysApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_key_v1_keys_post( + self, + create_key_request: CreateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> CreateKeyResponse: + """Create Key + + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + + :param create_key_request: (required) + :type create_key_request: CreateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_key_v1_keys_post_serialize( + create_key_request=create_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateKeyResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_key_v1_keys_post_with_http_info( + self, + create_key_request: CreateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[CreateKeyResponse]: + """Create Key + + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + + :param create_key_request: (required) + :type create_key_request: CreateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_key_v1_keys_post_serialize( + create_key_request=create_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateKeyResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_key_v1_keys_post_without_preload_content( + self, + create_key_request: CreateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Key + + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + + :param create_key_request: (required) + :type create_key_request: CreateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_key_v1_keys_post_serialize( + create_key_request=create_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CreateKeyResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_key_v1_keys_post_serialize( + self, + create_key_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_key_request is not None: + _body_params = create_key_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/keys', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_key_v1_keys_key_id_delete( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Delete Key + + Delete (revoke) an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_key_v1_keys_key_id_delete_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_key_v1_keys_key_id_delete_with_http_info( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Delete Key + + Delete (revoke) an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_key_v1_keys_key_id_delete_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_key_v1_keys_key_id_delete_without_preload_content( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Key + + Delete (revoke) an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_key_v1_keys_key_id_delete_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_key_v1_keys_key_id_delete_serialize( + self, + key_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if key_id is not None: + _path_params['key_id'] = key_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/keys/{key_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_key_v1_keys_key_id_get( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> KeyInfo: + """Get Key + + Get details of a specific API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_key_v1_keys_key_id_get_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_key_v1_keys_key_id_get_with_http_info( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[KeyInfo]: + """Get Key + + Get details of a specific API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_key_v1_keys_key_id_get_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_key_v1_keys_key_id_get_without_preload_content( + self, + key_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Key + + Get details of a specific API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_key_v1_keys_key_id_get_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_key_v1_keys_key_id_get_serialize( + self, + key_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if key_id is not None: + _path_params['key_id'] = key_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/keys/{key_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_keys_v1_keys_get( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[KeyInfo]: + """List Keys + + List all API keys. Requires master key authentication. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_keys_v1_keys_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[KeyInfo]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_keys_v1_keys_get_with_http_info( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[KeyInfo]]: + """List Keys + + List all API keys. Requires master key authentication. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_keys_v1_keys_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[KeyInfo]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_keys_v1_keys_get_without_preload_content( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Keys + + List all API keys. Requires master key authentication. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_keys_v1_keys_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[KeyInfo]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_keys_v1_keys_get_serialize( + self, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/keys', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_key_v1_keys_key_id_patch( + self, + key_id: StrictStr, + update_key_request: UpdateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> KeyInfo: + """Update Key + + Update an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param update_key_request: (required) + :type update_key_request: UpdateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_key_v1_keys_key_id_patch_serialize( + key_id=key_id, + update_key_request=update_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_key_v1_keys_key_id_patch_with_http_info( + self, + key_id: StrictStr, + update_key_request: UpdateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[KeyInfo]: + """Update Key + + Update an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param update_key_request: (required) + :type update_key_request: UpdateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_key_v1_keys_key_id_patch_serialize( + key_id=key_id, + update_key_request=update_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_key_v1_keys_key_id_patch_without_preload_content( + self, + key_id: StrictStr, + update_key_request: UpdateKeyRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update Key + + Update an API key. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :param update_key_request: (required) + :type update_key_request: UpdateKeyRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_key_v1_keys_key_id_patch_serialize( + key_id=key_id, + update_key_request=update_key_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_key_v1_keys_key_id_patch_serialize( + self, + key_id, + update_key_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if key_id is not None: + _path_params['key_id'] = key_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_key_request is not None: + _body_params = update_key_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/keys/{key_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/messages_api.py b/src/otari/_client/api/messages_api.py new file mode 100644 index 0000000..6b65bff --- /dev/null +++ b/src/otari/_client/api/messages_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from otari._client.models.message_response import MessageResponse +from otari._client.models.messages_request import MessagesRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class MessagesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_message_v1_messages_post( + self, + messages_request: MessagesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> MessageResponse: + """Create Message + + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param messages_request: (required) + :type messages_request: MessagesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_message_v1_messages_post_serialize( + messages_request=messages_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "MessageResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_message_v1_messages_post_with_http_info( + self, + messages_request: MessagesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[MessageResponse]: + """Create Message + + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param messages_request: (required) + :type messages_request: MessagesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_message_v1_messages_post_serialize( + messages_request=messages_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "MessageResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_message_v1_messages_post_without_preload_content( + self, + messages_request: MessagesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Message + + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param messages_request: (required) + :type messages_request: MessagesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_message_v1_messages_post_serialize( + messages_request=messages_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "MessageResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_message_v1_messages_post_serialize( + self, + messages_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if messages_request is not None: + _body_params = messages_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/messages', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/models_api.py b/src/otari/_client/api/models_api.py new file mode 100644 index 0000000..6b43e30 --- /dev/null +++ b/src/otari/_client/api/models_api.py @@ -0,0 +1,567 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing import Optional +from typing_extensions import Annotated +from otari._client.models.model_list_response import ModelListResponse +from otari._client.models.model_object import ModelObject + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ModelsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def get_model_v1_models_model_id_get( + self, + model_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ModelObject: + """Get Model + + Get details for a specific model. + + :param model_id: (required) + :type model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_model_v1_models_model_id_get_serialize( + model_id=model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelObject", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_model_v1_models_model_id_get_with_http_info( + self, + model_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ModelObject]: + """Get Model + + Get details for a specific model. + + :param model_id: (required) + :type model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_model_v1_models_model_id_get_serialize( + model_id=model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelObject", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_model_v1_models_model_id_get_without_preload_content( + self, + model_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Model + + Get details for a specific model. + + :param model_id: (required) + :type model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_model_v1_models_model_id_get_serialize( + model_id=model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelObject", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_model_v1_models_model_id_get_serialize( + self, + model_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if model_id is not None: + _path_params['model_id'] = model_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/models/{model_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_models_v1_models_get( + self, + provider: Annotated[Optional[StrictStr], Field(description="Filter models by provider name")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ModelListResponse: + """List Models + + List all available models. Returns models auto-discovered from configured providers, enriched with pricing data from the model_pricing table when available. Models that only exist in the pricing table are also included for backward compatibility. + + :param provider: Filter models by provider name + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_models_v1_models_get_serialize( + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelListResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_models_v1_models_get_with_http_info( + self, + provider: Annotated[Optional[StrictStr], Field(description="Filter models by provider name")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ModelListResponse]: + """List Models + + List all available models. Returns models auto-discovered from configured providers, enriched with pricing data from the model_pricing table when available. Models that only exist in the pricing table are also included for backward compatibility. + + :param provider: Filter models by provider name + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_models_v1_models_get_serialize( + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelListResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_models_v1_models_get_without_preload_content( + self, + provider: Annotated[Optional[StrictStr], Field(description="Filter models by provider name")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Models + + List all available models. Returns models auto-discovered from configured providers, enriched with pricing data from the model_pricing table when available. Models that only exist in the pricing table are also included for backward compatibility. + + :param provider: Filter models by provider name + :type provider: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_models_v1_models_get_serialize( + provider=provider, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelListResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_models_v1_models_get_serialize( + self, + provider, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if provider is not None: + + _query_params.append(('provider', provider)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/models', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/moderations_api.py b/src/otari/_client/api/moderations_api.py new file mode 100644 index 0000000..e8e0cee --- /dev/null +++ b/src/otari/_client/api/moderations_api.py @@ -0,0 +1,331 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import StrictBool +from typing import Optional +from otari._client.models.moderation_request import ModerationRequest +from otari._client.models.moderation_response import ModerationResponse + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ModerationsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_moderation_v1_moderations_post( + self, + moderation_request: ModerationRequest, + include_raw: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ModerationResponse: + """Create Moderation + + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param moderation_request: (required) + :type moderation_request: ModerationRequest + :param include_raw: + :type include_raw: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_moderation_v1_moderations_post_serialize( + moderation_request=moderation_request, + include_raw=include_raw, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModerationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_moderation_v1_moderations_post_with_http_info( + self, + moderation_request: ModerationRequest, + include_raw: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ModerationResponse]: + """Create Moderation + + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param moderation_request: (required) + :type moderation_request: ModerationRequest + :param include_raw: + :type include_raw: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_moderation_v1_moderations_post_serialize( + moderation_request=moderation_request, + include_raw=include_raw, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModerationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_moderation_v1_moderations_post_without_preload_content( + self, + moderation_request: ModerationRequest, + include_raw: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Moderation + + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param moderation_request: (required) + :type moderation_request: ModerationRequest + :param include_raw: + :type include_raw: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_moderation_v1_moderations_post_serialize( + moderation_request=moderation_request, + include_raw=include_raw, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModerationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_moderation_v1_moderations_post_serialize( + self, + moderation_request, + include_raw, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if include_raw is not None: + + _query_params.append(('include_raw', include_raw)) + + # process the header parameters + # process the form parameters + # process the body parameter + if moderation_request is not None: + _body_params = moderation_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/moderations', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/pricing_api.py b/src/otari/_client/api/pricing_api.py new file mode 100644 index 0000000..a735ba8 --- /dev/null +++ b/src/otari/_client/api/pricing_api.py @@ -0,0 +1,1439 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from datetime import datetime +from pydantic import Field, StrictStr +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.pricing_response import PricingResponse +from otari._client.models.set_pricing_request import SetPricingRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class PricingApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def delete_pricing_v1_pricing_model_key_delete( + self, + model_key: StrictStr, + effective_at: Annotated[Optional[datetime], Field(description="ISO datetime identifying a specific pricing row to delete")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Delete Pricing + + Delete pricing entries for a model. + + :param model_key: (required) + :type model_key: str + :param effective_at: ISO datetime identifying a specific pricing row to delete + :type effective_at: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_pricing_v1_pricing_model_key_delete_serialize( + model_key=model_key, + effective_at=effective_at, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_pricing_v1_pricing_model_key_delete_with_http_info( + self, + model_key: StrictStr, + effective_at: Annotated[Optional[datetime], Field(description="ISO datetime identifying a specific pricing row to delete")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Delete Pricing + + Delete pricing entries for a model. + + :param model_key: (required) + :type model_key: str + :param effective_at: ISO datetime identifying a specific pricing row to delete + :type effective_at: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_pricing_v1_pricing_model_key_delete_serialize( + model_key=model_key, + effective_at=effective_at, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_pricing_v1_pricing_model_key_delete_without_preload_content( + self, + model_key: StrictStr, + effective_at: Annotated[Optional[datetime], Field(description="ISO datetime identifying a specific pricing row to delete")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Pricing + + Delete pricing entries for a model. + + :param model_key: (required) + :type model_key: str + :param effective_at: ISO datetime identifying a specific pricing row to delete + :type effective_at: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_pricing_v1_pricing_model_key_delete_serialize( + model_key=model_key, + effective_at=effective_at, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_pricing_v1_pricing_model_key_delete_serialize( + self, + model_key, + effective_at, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if model_key is not None: + _path_params['model_key'] = model_key + # process the query parameters + if effective_at is not None: + if isinstance(effective_at, datetime): + _query_params.append( + ( + 'effective_at', + effective_at.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('effective_at', effective_at)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/pricing/{model_key}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_pricing_history_v1_pricing_model_key_history_get( + self, + model_key: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[PricingResponse]: + """Get Pricing History + + Return the full pricing history for a model. + + :param model_key: (required) + :type model_key: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_history_v1_pricing_model_key_history_get_serialize( + model_key=model_key, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_pricing_history_v1_pricing_model_key_history_get_with_http_info( + self, + model_key: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[PricingResponse]]: + """Get Pricing History + + Return the full pricing history for a model. + + :param model_key: (required) + :type model_key: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_history_v1_pricing_model_key_history_get_serialize( + model_key=model_key, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_pricing_history_v1_pricing_model_key_history_get_without_preload_content( + self, + model_key: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Pricing History + + Return the full pricing history for a model. + + :param model_key: (required) + :type model_key: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_history_v1_pricing_model_key_history_get_serialize( + model_key=model_key, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_pricing_history_v1_pricing_model_key_history_get_serialize( + self, + model_key, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if model_key is not None: + _path_params['model_key'] = model_key + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/pricing/{model_key}/history', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_pricing_v1_pricing_model_key_get( + self, + model_key: StrictStr, + as_of: Annotated[Optional[datetime], Field(description="ISO datetime for effective lookup")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> PricingResponse: + """Get Pricing + + Get pricing for a specific model as of a timestamp. + + :param model_key: (required) + :type model_key: str + :param as_of: ISO datetime for effective lookup + :type as_of: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_v1_pricing_model_key_get_serialize( + model_key=model_key, + as_of=as_of, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_pricing_v1_pricing_model_key_get_with_http_info( + self, + model_key: StrictStr, + as_of: Annotated[Optional[datetime], Field(description="ISO datetime for effective lookup")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[PricingResponse]: + """Get Pricing + + Get pricing for a specific model as of a timestamp. + + :param model_key: (required) + :type model_key: str + :param as_of: ISO datetime for effective lookup + :type as_of: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_v1_pricing_model_key_get_serialize( + model_key=model_key, + as_of=as_of, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_pricing_v1_pricing_model_key_get_without_preload_content( + self, + model_key: StrictStr, + as_of: Annotated[Optional[datetime], Field(description="ISO datetime for effective lookup")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Pricing + + Get pricing for a specific model as of a timestamp. + + :param model_key: (required) + :type model_key: str + :param as_of: ISO datetime for effective lookup + :type as_of: datetime + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_pricing_v1_pricing_model_key_get_serialize( + model_key=model_key, + as_of=as_of, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_pricing_v1_pricing_model_key_get_serialize( + self, + model_key, + as_of, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if model_key is not None: + _path_params['model_key'] = model_key + # process the query parameters + if as_of is not None: + if isinstance(as_of, datetime): + _query_params.append( + ( + 'as_of', + as_of.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('as_of', as_of)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/pricing/{model_key}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_pricing_v1_pricing_get( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[PricingResponse]: + """List Pricing + + List all model pricing. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_pricing_v1_pricing_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_pricing_v1_pricing_get_with_http_info( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[PricingResponse]]: + """List Pricing + + List all model pricing. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_pricing_v1_pricing_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_pricing_v1_pricing_get_without_preload_content( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Pricing + + List all model pricing. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_pricing_v1_pricing_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[PricingResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_pricing_v1_pricing_get_serialize( + self, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/pricing', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def set_pricing_v1_pricing_post( + self, + set_pricing_request: SetPricingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> PricingResponse: + """Set Pricing + + Set or update pricing for a model. + + :param set_pricing_request: (required) + :type set_pricing_request: SetPricingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_pricing_v1_pricing_post_serialize( + set_pricing_request=set_pricing_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def set_pricing_v1_pricing_post_with_http_info( + self, + set_pricing_request: SetPricingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[PricingResponse]: + """Set Pricing + + Set or update pricing for a model. + + :param set_pricing_request: (required) + :type set_pricing_request: SetPricingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_pricing_v1_pricing_post_serialize( + set_pricing_request=set_pricing_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def set_pricing_v1_pricing_post_without_preload_content( + self, + set_pricing_request: SetPricingRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Set Pricing + + Set or update pricing for a model. + + :param set_pricing_request: (required) + :type set_pricing_request: SetPricingRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_pricing_v1_pricing_post_serialize( + set_pricing_request=set_pricing_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "PricingResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _set_pricing_v1_pricing_post_serialize( + self, + set_pricing_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if set_pricing_request is not None: + _body_params = set_pricing_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/pricing', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/rerank_api.py b/src/otari/_client/api/rerank_api.py new file mode 100644 index 0000000..78cf4df --- /dev/null +++ b/src/otari/_client/api/rerank_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from otari._client.models.rerank_request import RerankRequest +from otari._client.models.rerank_response import RerankResponse + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class RerankApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_rerank_v1_rerank_post( + self, + rerank_request: RerankRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RerankResponse: + """Create Rerank + + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param rerank_request: (required) + :type rerank_request: RerankRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_rerank_v1_rerank_post_serialize( + rerank_request=rerank_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RerankResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_rerank_v1_rerank_post_with_http_info( + self, + rerank_request: RerankRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[RerankResponse]: + """Create Rerank + + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param rerank_request: (required) + :type rerank_request: RerankRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_rerank_v1_rerank_post_serialize( + rerank_request=rerank_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RerankResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_rerank_v1_rerank_post_without_preload_content( + self, + rerank_request: RerankRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Rerank + + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + + :param rerank_request: (required) + :type rerank_request: RerankRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_rerank_v1_rerank_post_serialize( + rerank_request=rerank_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RerankResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_rerank_v1_rerank_post_serialize( + self, + rerank_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if rerank_request is not None: + _body_params = rerank_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/rerank', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/responses_api.py b/src/otari/_client/api/responses_api.py new file mode 100644 index 0000000..36f6a1c --- /dev/null +++ b/src/otari/_client/api/responses_api.py @@ -0,0 +1,312 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from typing import Any +from otari._client.models.responses_request import ResponsesRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ResponsesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_response_v1_responses_post( + self, + responses_request: ResponsesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Create Response + + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param responses_request: (required) + :type responses_request: ResponsesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_response_v1_responses_post_serialize( + responses_request=responses_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_response_v1_responses_post_with_http_info( + self, + responses_request: ResponsesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Create Response + + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param responses_request: (required) + :type responses_request: ResponsesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_response_v1_responses_post_serialize( + responses_request=responses_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_response_v1_responses_post_without_preload_content( + self, + responses_request: ResponsesRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Response + + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and platform mode. Platform-mode requests resolve credentials via the platform service and (for non-tool-loop requests) get multi-attempt fallback across the resolved route. Tool-loop requests collapse to a single attempt — once ``on_first_response`` lock-in plumbing lands across the codebase, a follow-up will enable pre-lock-in fallback for tool-loop requests too. + + :param responses_request: (required) + :type responses_request: ResponsesRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_response_v1_responses_post_serialize( + responses_request=responses_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_response_v1_responses_post_serialize( + self, + responses_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if responses_request is not None: + _body_params = responses_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/responses', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/usage_api.py b/src/otari/_client/api/usage_api.py new file mode 100644 index 0000000..7782989 --- /dev/null +++ b/src/otari/_client/api/usage_api.py @@ -0,0 +1,390 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from datetime import datetime +from pydantic import Field, StrictStr +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.usage_entry import UsageEntry + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class UsageApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def list_usage_v1_usage_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[UsageEntry]: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_usage_v1_usage_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[UsageEntry]]: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_usage_v1_usage_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_usage_v1_usage_get_serialize( + self, + start_date, + end_date, + user_id, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/usage', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/users_api.py b/src/otari/_client/api/users_api.py new file mode 100644 index 0000000..b105597 --- /dev/null +++ b/src/otari/_client/api/users_api.py @@ -0,0 +1,1713 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.create_user_request import CreateUserRequest +from otari._client.models.update_user_request import UpdateUserRequest +from otari._client.models.usage_log_response import UsageLogResponse +from otari._client.models.user_response import UserResponse + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class UsersApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_user_v1_users_post( + self, + create_user_request: CreateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> UserResponse: + """Create User + + Create a new user. + + :param create_user_request: (required) + :type create_user_request: CreateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_user_v1_users_post_serialize( + create_user_request=create_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_user_v1_users_post_with_http_info( + self, + create_user_request: CreateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[UserResponse]: + """Create User + + Create a new user. + + :param create_user_request: (required) + :type create_user_request: CreateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_user_v1_users_post_serialize( + create_user_request=create_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_user_v1_users_post_without_preload_content( + self, + create_user_request: CreateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create User + + Create a new user. + + :param create_user_request: (required) + :type create_user_request: CreateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_user_v1_users_post_serialize( + create_user_request=create_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_user_v1_users_post_serialize( + self, + create_user_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_user_request is not None: + _body_params = create_user_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/users', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_user_v1_users_user_id_delete( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Delete User + + Delete a user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_user_v1_users_user_id_delete_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_user_v1_users_user_id_delete_with_http_info( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Delete User + + Delete a user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_user_v1_users_user_id_delete_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_user_v1_users_user_id_delete_without_preload_content( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete User + + Delete a user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_user_v1_users_user_id_delete_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_user_v1_users_user_id_delete_serialize( + self, + user_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if user_id is not None: + _path_params['user_id'] = user_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/users/{user_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_user_usage_v1_users_user_id_usage_get( + self, + user_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[UsageLogResponse]: + """Get User Usage + + Get usage history for a specific user. + + :param user_id: (required) + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_usage_v1_users_user_id_usage_get_serialize( + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_user_usage_v1_users_user_id_usage_get_with_http_info( + self, + user_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[UsageLogResponse]]: + """Get User Usage + + Get usage history for a specific user. + + :param user_id: (required) + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_usage_v1_users_user_id_usage_get_serialize( + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_user_usage_v1_users_user_id_usage_get_without_preload_content( + self, + user_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get User Usage + + Get usage history for a specific user. + + :param user_id: (required) + :type user_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_usage_v1_users_user_id_usage_get_serialize( + user_id=user_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_user_usage_v1_users_user_id_usage_get_serialize( + self, + user_id, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if user_id is not None: + _path_params['user_id'] = user_id + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/users/{user_id}/usage', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_user_v1_users_user_id_get( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> UserResponse: + """Get User + + Get details of a specific user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_v1_users_user_id_get_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_user_v1_users_user_id_get_with_http_info( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[UserResponse]: + """Get User + + Get details of a specific user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_v1_users_user_id_get_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_user_v1_users_user_id_get_without_preload_content( + self, + user_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get User + + Get details of a specific user. + + :param user_id: (required) + :type user_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_user_v1_users_user_id_get_serialize( + user_id=user_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_user_v1_users_user_id_get_serialize( + self, + user_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if user_id is not None: + _path_params['user_id'] = user_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/users/{user_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_users_v1_users_get( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[UserResponse]: + """List Users + + List all users with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_users_v1_users_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UserResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_users_v1_users_get_with_http_info( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[UserResponse]]: + """List Users + + List all users with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_users_v1_users_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UserResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_users_v1_users_get_without_preload_content( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Users + + List all users with pagination. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_users_v1_users_get_serialize( + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UserResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_users_v1_users_get_serialize( + self, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/users', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_user_v1_users_user_id_patch( + self, + user_id: StrictStr, + update_user_request: UpdateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> UserResponse: + """Update User + + Update a user. + + :param user_id: (required) + :type user_id: str + :param update_user_request: (required) + :type update_user_request: UpdateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_user_v1_users_user_id_patch_serialize( + user_id=user_id, + update_user_request=update_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_user_v1_users_user_id_patch_with_http_info( + self, + user_id: StrictStr, + update_user_request: UpdateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[UserResponse]: + """Update User + + Update a user. + + :param user_id: (required) + :type user_id: str + :param update_user_request: (required) + :type update_user_request: UpdateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_user_v1_users_user_id_patch_serialize( + user_id=user_id, + update_user_request=update_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_user_v1_users_user_id_patch_without_preload_content( + self, + user_id: StrictStr, + update_user_request: UpdateUserRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update User + + Update a user. + + :param user_id: (required) + :type user_id: str + :param update_user_request: (required) + :type update_user_request: UpdateUserRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_user_v1_users_user_id_patch_serialize( + user_id=user_id, + update_user_request=update_user_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UserResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_user_v1_users_user_id_patch_serialize( + self, + user_id, + update_user_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if user_id is not None: + _path_params['user_id'] = user_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_user_request is not None: + _body_params = update_user_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/users/{user_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api_client.py b/src/otari/_client/api_client.py new file mode 100644 index 0000000..d8d0b13 --- /dev/null +++ b/src/otari/_client/api_client.py @@ -0,0 +1,804 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + + +import datetime +from dateutil.parser import parse +from enum import Enum +import decimal +import json +import mimetypes +import os +import re +import tempfile +import uuid + +from urllib.parse import quote +from typing import Tuple, Optional, List, Dict, Union +from pydantic import SecretStr + +from otari._client.configuration import Configuration +from otari._client.api_response import ApiResponse, T as ApiResponseT +import otari._client.models +from otari._client import rest +from otari._client.exceptions import ( + ApiValueError, + ApiException, + BadRequestException, + UnauthorizedException, + ForbiddenException, + NotFoundException, + ServiceException +) + +RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]] + +class ApiClient: + """Generic API client for OpenAPI client library builds. + + OpenAPI generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the OpenAPI + templates. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + """ + + PRIMITIVE_TYPES = (float, bool, bytes, str, int) + NATIVE_TYPES_MAPPING = { + 'int': int, + 'long': int, # TODO remove as only py3 is supported? + 'float': float, + 'str': str, + 'bool': bool, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, + 'UUID': uuid.UUID, + 'object': object, + } + _pool = None + + def __init__( + self, + configuration=None, + header_name=None, + header_value=None, + cookie=None + ) -> None: + # use default configuration if none is provided + if configuration is None: + configuration = Configuration.get_default() + self.configuration = configuration + + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = 'OpenAPI-Generator/1.0.0/python' + self.client_side_validation = configuration.client_side_validation + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + pass + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + + _default = None + + @classmethod + def get_default(cls): + """Return new instance of ApiClient. + + This method returns newly created, based on default constructor, + object of ApiClient class or returns a copy of default + ApiClient. + + :return: The ApiClient object. + """ + if cls._default is None: + cls._default = ApiClient() + return cls._default + + @classmethod + def set_default(cls, default): + """Set default instance of ApiClient. + + It stores default ApiClient. + + :param default: object of ApiClient. + """ + cls._default = default + + def param_serialize( + self, + method, + resource_path, + path_params=None, + query_params=None, + header_params=None, + body=None, + post_params=None, + files=None, auth_settings=None, + collection_formats=None, + _host=None, + _request_auth=None + ) -> RequestSerialized: + + """Builds the HTTP request params needed by the request. + :param method: Method to call. + :param resource_path: Path to method endpoint. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :return: tuple of form (path, http_method, query_params, header_params, + body, post_params, files) + """ + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) + header_params = dict( + self.parameters_to_tuples(header_params,collection_formats) + ) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples( + path_params, + collection_formats + ) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # post parameters + if post_params or files: + post_params = post_params if post_params else [] + post_params = self.sanitize_for_serialization(post_params) + post_params = self.parameters_to_tuples( + post_params, + collection_formats + ) + if files: + post_params.extend(self.files_parameters(files)) + + # auth setting + self.update_params_for_auth( + header_params, + query_params, + auth_settings, + resource_path, + method, + body, + request_auth=_request_auth + ) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + if _host is None or self.configuration.ignore_operation_servers: + url = self.configuration.host + resource_path + else: + # use server/host defined in path or operation instead + url = _host + resource_path + + # query parameters + if query_params: + query_params = self.sanitize_for_serialization(query_params) + url_query = self.parameters_to_url_query( + query_params, + collection_formats + ) + url += "?" + url_query + + return method, url, header_params, body, post_params + + + def call_api( + self, + method, + url, + header_params=None, + body=None, + post_params=None, + _request_timeout=None + ) -> rest.RESTResponse: + """Makes the HTTP request (synchronous) + :param method: Method to call. + :param url: Path to method endpoint. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param _request_timeout: timeout setting for this request. + :return: RESTResponse + """ + + try: + # perform request and return response + response_data = self.rest_client.request( + method, url, + headers=header_params, + body=body, post_params=post_params, + _request_timeout=_request_timeout + ) + + except ApiException as e: + raise e + + return response_data + + def response_deserialize( + self, + response_data: rest.RESTResponse, + response_types_map: Optional[Dict[str, ApiResponseT]]=None + ) -> ApiResponse[ApiResponseT]: + """Deserializes response into an object. + :param response_data: RESTResponse object to be deserialized. + :param response_types_map: dict of response types. + :return: ApiResponse + """ + + msg = "RESTResponse.read() must be called before passing it to response_deserialize()" + assert response_data.data is not None, msg + + response_type = response_types_map.get(str(response_data.status), None) + if not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599: + # if not found, look for '1XX', '2XX', etc. + response_type = response_types_map.get(str(response_data.status)[0] + "XX", None) + + # deserialize response data + response_text = None + return_data = None + try: + if response_type in ("bytearray", "bytes"): + return_data = response_data.data + elif response_type == "file": + return_data = self.__deserialize_file(response_data) + elif response_type is not None: + match = None + content_type = response_data.headers.get('content-type') + if content_type is not None: + match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) + encoding = match.group(1) if match else "utf-8" + response_text = response_data.data.decode(encoding) + return_data = self.deserialize(response_text, response_type, content_type) + finally: + if not 200 <= response_data.status <= 299: + raise ApiException.from_response( + http_resp=response_data, + body=response_text, + data=return_data, + ) + + return ApiResponse( + status_code = response_data.status, + data = return_data, + headers = response_data.headers, + raw_data = response_data.data + ) + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is SecretStr, return obj.get_secret_value() + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is OpenAPI model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, Enum): + return obj.value + elif isinstance(obj, SecretStr): + return obj.get_secret_value() + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, uuid.UUID): + return str(obj) + elif isinstance(obj, list): + return [ + self.sanitize_for_serialization(sub_obj) for sub_obj in obj + ] + elif isinstance(obj, tuple): + return tuple( + self.sanitize_for_serialization(sub_obj) for sub_obj in obj + ) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) + elif isinstance(obj, dict): + return { + key: self.sanitize_for_serialization(val) + for key, val in obj.items() + } + + # Convert model obj to dict except + # attributes `openapi_types`, `attribute_map` + # and attributes which value is not None. + # Convert attribute name to json key in + # model definition for request. + if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')): + obj_dict = obj.to_dict() + else: + obj_dict = obj.__dict__ + + return self.sanitize_for_serialization(obj_dict) + + + def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + :param content_type: content type of response. + + :return: deserialized object. + """ + + # fetch data from response object + if content_type is None: + try: + data = json.loads(response_text) + except ValueError: + data = response_text + elif re.match(r'^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE): + if response_text == "": + data = "" + else: + data = json.loads(response_text) + elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE): + data = response_text + else: + raise ApiException( + status=0, + reason="Unsupported content type: {0}".format(content_type) + ) + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if isinstance(klass, str): + if klass.startswith('List['): + m = re.match(r'List\[(.*)]', klass) + assert m is not None, "Malformed List type definition" + sub_kls = m.group(1) + return [self.__deserialize(sub_data, sub_kls) + for sub_data in data] + + if klass.startswith('Dict['): + m = re.match(r'Dict\[([^,]*), (.*)]', klass) + assert m is not None, "Malformed Dict type definition" + sub_kls = m.group(2) + return {k: self.__deserialize(v, sub_kls) + for k, v in data.items()} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr(otari._client.models, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass is object: + return self.__deserialize_object(data) + elif klass is datetime.date: + return self.__deserialize_date(data) + elif klass is datetime.datetime: + return self.__deserialize_datetime(data) + elif klass is decimal.Decimal: + return decimal.Decimal(data) + elif klass is uuid.UUID: + return uuid.UUID(data) + elif issubclass(klass, Enum): + return self.__deserialize_enum(data, klass) + else: + return self.__deserialize_model(data, klass) + + def parameters_to_tuples(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: Parameters as list of tuples, collections formatted + """ + new_params: List[Tuple[str, str]] = [] + if collection_formats is None: + collection_formats = {} + for k, v in params.items() if isinstance(params, dict) else params: + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(str(value) for value in v))) + else: + new_params.append((k, v)) + return new_params + + def parameters_to_url_query(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: URL query string (e.g. a=Hello%20World&b=123) + """ + new_params: List[Tuple[str, str]] = [] + if collection_formats is None: + collection_formats = {} + for k, v in params.items() if isinstance(params, dict) else params: + if isinstance(v, bool): + v = str(v).lower() + if isinstance(v, (int, float)): + v = str(v) + if isinstance(v, dict): + v = json.dumps(v) + + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, quote(str(value))) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(quote(str(value)) for value in v)) + ) + else: + new_params.append((k, quote(str(v)))) + + return "&".join(["=".join(map(str, item)) for item in new_params]) + + def files_parameters( + self, + files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], + ): + """Builds form parameters. + + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + for k, v in files.items(): + if isinstance(v, str): + with open(v, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + elif isinstance(v, bytes): + filename = k + filedata = v + elif isinstance(v, tuple): + filename, filedata = v + elif isinstance(v, list): + for file_param in v: + params.extend(self.files_parameters({k: file_param})) + continue + else: + raise ValueError("Unsupported file value") + mimetype = ( + mimetypes.guess_type(filename)[0] + or 'application/octet-stream' + ) + params.append( + tuple([k, tuple([filename, filedata, mimetype])]) + ) + return params + + def select_header_accept(self, accepts: List[str]) -> Optional[str]: + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return None + + for accept in accepts: + if re.search('json', accept, re.IGNORECASE): + return accept + + return accepts[0] + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return None + + for content_type in content_types: + if re.search('json', content_type, re.IGNORECASE): + return content_type + + return content_types[0] + + def update_params_for_auth( + self, + headers, + queries, + auth_settings, + resource_path, + method, + body, + request_auth=None + ) -> None: + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param queries: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + :resource_path: A string representation of the HTTP request resource path. + :method: A string representation of the HTTP request method. + :body: A object representing the body of the HTTP request. + The object type is the return value of sanitize_for_serialization(). + :param request_auth: if set, the provided settings will + override the token in the configuration. + """ + if not auth_settings: + return + + if request_auth: + self._apply_auth_params( + headers, + queries, + resource_path, + method, + body, + request_auth + ) + else: + for auth in auth_settings: + auth_setting = self.configuration.auth_settings().get(auth) + if auth_setting: + self._apply_auth_params( + headers, + queries, + resource_path, + method, + body, + auth_setting + ) + + def _apply_auth_params( + self, + headers, + queries, + resource_path, + method, + body, + auth_setting + ) -> None: + """Updates the request parameters based on a single auth_setting + + :param headers: Header parameters dict to be updated. + :param queries: Query parameters tuple list to be updated. + :resource_path: A string representation of the HTTP request resource path. + :method: A string representation of the HTTP request method. + :body: A object representing the body of the HTTP request. + The object type is the return value of sanitize_for_serialization(). + :param auth_setting: auth settings for the endpoint + """ + if auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] + elif auth_setting['in'] == 'header': + if auth_setting['type'] != 'http-signature': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + queries.append((auth_setting['key'], auth_setting['value'])) + else: + raise ApiValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + handle file downloading + save response body into a tmp file and return the instance + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.headers.get("Content-Disposition") + if content_disposition: + m = re.search( + r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition + ) + assert m is not None, "Unexpected 'content-disposition' header value" + filename = os.path.basename(m.group(1)) # Strip any directory traversal + if filename in ("", ".", ".."): # fall back to tmp filename + filename = os.path.basename(path) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "wb") as f: + f.write(response.data) + + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return str(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return an original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + try: + return parse(string).date() + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason="Failed to parse `{0}` as date object".format(string) + ) + + def __deserialize_datetime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + try: + return parse(string) + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as datetime object" + .format(string) + ) + ) + + def __deserialize_enum(self, data, klass): + """Deserializes primitive type to enum. + + :param data: primitive type. + :param klass: class literal. + :return: enum value. + """ + try: + return klass(data) + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as `{1}`" + .format(data, klass) + ) + ) + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + return klass.from_dict(data) diff --git a/src/otari/_client/api_response.py b/src/otari/_client/api_response.py new file mode 100644 index 0000000..9bc7c11 --- /dev/null +++ b/src/otari/_client/api_response.py @@ -0,0 +1,21 @@ +"""API response object.""" + +from __future__ import annotations +from typing import Optional, Generic, Mapping, TypeVar +from pydantic import Field, StrictInt, StrictBytes, BaseModel + +T = TypeVar("T") + +class ApiResponse(BaseModel, Generic[T]): + """ + API response object + """ + + status_code: StrictInt = Field(description="HTTP status code") + headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers") + data: T = Field(description="Deserialized data given the data type") + raw_data: StrictBytes = Field(description="Raw data (HTTP response body)") + + model_config = { + "arbitrary_types_allowed": True + } diff --git a/src/otari/_client/configuration.py b/src/otari/_client/configuration.py new file mode 100644 index 0000000..5cd7bc4 --- /dev/null +++ b/src/otari/_client/configuration.py @@ -0,0 +1,596 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import copy +import http.client as httplib +import logging +from logging import FileHandler +import multiprocessing +import sys +from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union +from typing_extensions import NotRequired, Self + +import urllib3 + + +JSON_SCHEMA_VALIDATION_KEYWORDS = { + 'multipleOf', 'maximum', 'exclusiveMaximum', + 'minimum', 'exclusiveMinimum', 'maxLength', + 'minLength', 'pattern', 'maxItems', 'minItems' +} + +ServerVariablesT = Dict[str, str] + +GenericAuthSetting = TypedDict( + "GenericAuthSetting", + { + "type": str, + "in": str, + "key": str, + "value": str, + }, +) + + +OAuth2AuthSetting = TypedDict( + "OAuth2AuthSetting", + { + "type": Literal["oauth2"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +APIKeyAuthSetting = TypedDict( + "APIKeyAuthSetting", + { + "type": Literal["api_key"], + "in": str, + "key": str, + "value": Optional[str], + }, +) + + +BasicAuthSetting = TypedDict( + "BasicAuthSetting", + { + "type": Literal["basic"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": Optional[str], + }, +) + + +BearerFormatAuthSetting = TypedDict( + "BearerFormatAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "format": Literal["JWT"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +BearerAuthSetting = TypedDict( + "BearerAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +HTTPSignatureAuthSetting = TypedDict( + "HTTPSignatureAuthSetting", + { + "type": Literal["http-signature"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": None, + }, +) + + +AuthSettings = TypedDict( + "AuthSettings", + { + }, + total=False, +) + + +class HostSettingVariable(TypedDict): + description: str + default_value: str + enum_values: List[str] + + +class HostSetting(TypedDict): + url: str + description: str + variables: NotRequired[Dict[str, HostSettingVariable]] + + +class Configuration: + """This class contains various settings of the API client. + + :param host: Base url. + :param ignore_operation_servers + Boolean to ignore operation servers for the API client. + Config will use `host` as the base url regardless of the operation servers. + :param api_key: Dict to store API key(s). + Each entry in the dict specifies an API key. + The dict key is the name of the security scheme in the OAS specification. + The dict value is the API key secret. + :param api_key_prefix: Dict to store API prefix (e.g. Bearer). + The dict key is the name of the security scheme in the OAS specification. + The dict value is an API key prefix when generating the auth data. + :param username: Username for HTTP basic authentication. + :param password: Password for HTTP basic authentication. + :param access_token: Access token. + :param server_index: Index to servers configuration. + :param server_variables: Mapping with string values to replace variables in + templated server configuration. The validation of enums is performed for + variables with defined enum values before. + :param server_operation_index: Mapping from operation ID to an index to server + configuration. + :param server_operation_variables: Mapping from operation ID to a mapping with + string values to replace variables in templated server configuration. + The validation of enums is performed for variables with defined enum + values before. + :param verify_ssl: bool - Set this to false to skip verifying SSL certificate + when calling API from https server. + :param ssl_ca_cert: str - the path to a file of concatenated CA certificates + in PEM format. + :param retries: int | urllib3.util.retry.Retry - Retry configuration. + :param ca_cert_data: verify the peer using concatenated CA certificate data + in PEM (str) or DER (bytes) format. + :param cert_file: the path to a client certificate file, for mTLS. + :param key_file: the path to a client key file, for mTLS. + :param assert_hostname: Set this to True/False to enable/disable SSL hostname verification. + :param tls_server_name: SSL/TLS Server Name Indication (SNI). Set this to the SNI value expected by the server. + :param connection_pool_maxsize: Connection pool max size. None in the constructor is coerced to 100 for async and cpu_count * 5 for sync. + :param proxy: Proxy URL. + :param proxy_headers: Proxy headers. + :param safe_chars_for_path_param: Safe characters for path parameter encoding. + :param client_side_validation: Enable client-side validation. Default True. + :param socket_options: Options to pass down to the underlying urllib3 socket. + :param datetime_format: Datetime format string for serialization. + :param date_format: Date format string for serialization. + + """ + + _default: ClassVar[Optional[Self]] = None + + def __init__( + self, + host: Optional[str]=None, + api_key: Optional[Dict[str, str]]=None, + api_key_prefix: Optional[Dict[str, str]]=None, + username: Optional[str]=None, + password: Optional[str]=None, + access_token: Optional[str]=None, + server_index: Optional[int]=None, + server_variables: Optional[ServerVariablesT]=None, + server_operation_index: Optional[Dict[int, int]]=None, + server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None, + ignore_operation_servers: bool=False, + ssl_ca_cert: Optional[str]=None, + retries: Optional[Union[int, urllib3.util.retry.Retry]] = None, + ca_cert_data: Optional[Union[str, bytes]] = None, + cert_file: Optional[str]=None, + key_file: Optional[str]=None, + verify_ssl: bool=True, + assert_hostname: Optional[bool]=None, + tls_server_name: Optional[str]=None, + connection_pool_maxsize: Optional[int]=None, + proxy: Optional[str]=None, + proxy_headers: Optional[Any]=None, + safe_chars_for_path_param: str='', + client_side_validation: bool=True, + socket_options: Optional[Any]=None, + datetime_format: str="%Y-%m-%dT%H:%M:%S.%f%z", + date_format: str="%Y-%m-%d", + *, + debug: Optional[bool] = None, + ) -> None: + """Constructor + """ + self._base_path = "http://localhost" if host is None else host + """Default Base url + """ + self.server_index = 0 if server_index is None and host is None else server_index + self.server_operation_index = server_operation_index or {} + """Default server index + """ + self.server_variables = server_variables or {} + self.server_operation_variables = server_operation_variables or {} + """Default server variables + """ + self.ignore_operation_servers = ignore_operation_servers + """Ignore operation servers + """ + self.temp_folder_path = None + """Temp file folder for downloading files + """ + # Authentication Settings + self.api_key = {} + if api_key: + self.api_key = api_key + """dict to store API key(s) + """ + self.api_key_prefix = {} + if api_key_prefix: + self.api_key_prefix = api_key_prefix + """dict to store API prefix (e.g. Bearer) + """ + self.refresh_api_key_hook = None + """function hook to refresh API key if expired + """ + self.username = username + """Username for HTTP basic authentication + """ + self.password = password + """Password for HTTP basic authentication + """ + self.access_token = access_token + """Access token + """ + self.logger = {} + """Logging Settings + """ + self.logger["package_logger"] = logging.getLogger("otari._client") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + """Log format + """ + self.logger_stream_handler = None + """Log stream handler + """ + self.logger_file_handler: Optional[FileHandler] = None + """Log file handler + """ + self.logger_file = None + """Debug file location + """ + if debug is not None: + self.debug = debug + else: + self.__debug = False + """Debug switch + """ + + self.verify_ssl = verify_ssl + """SSL/TLS verification + Set this to false to skip verifying SSL certificate when calling API + from https server. + """ + self.ssl_ca_cert = ssl_ca_cert + """Set this to customize the certificate file to verify the peer. + """ + self.ca_cert_data = ca_cert_data + """Set this to verify the peer using PEM (str) or DER (bytes) + certificate data. + """ + self.cert_file = cert_file + """client certificate file + """ + self.key_file = key_file + """client key file + """ + self.assert_hostname = assert_hostname + """Set this to True/False to enable/disable SSL hostname verification. + """ + self.tls_server_name = tls_server_name + """SSL/TLS Server Name Indication (SNI) + Set this to the SNI value expected by the server. + """ + + self.connection_pool_maxsize = connection_pool_maxsize if connection_pool_maxsize is not None else multiprocessing.cpu_count() * 5 + """urllib3 connection pool's maximum number of connections saved + per pool. None in the constructor is coerced to cpu_count * 5. + """ + + self.proxy = proxy + """Proxy URL + """ + self.proxy_headers = proxy_headers + """Proxy headers + """ + self.safe_chars_for_path_param = safe_chars_for_path_param + """Safe chars for path_param + """ + self.retries = retries + """Retry configuration + """ + # Enable client side validation + self.client_side_validation = client_side_validation + + self.socket_options = socket_options + """Options to pass down to the underlying urllib3 socket + """ + + self.datetime_format = datetime_format + """datetime format + """ + + self.date_format = date_format + """date format + """ + + def __deepcopy__(self, memo: Dict[int, Any]) -> Self: + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k not in ('logger', 'logger_file_handler'): + setattr(result, k, copy.deepcopy(v, memo)) + # shallow copy of loggers + result.logger = copy.copy(self.logger) + # use setters to configure loggers + result.logger_file = self.logger_file + result.debug = self.debug + return result + + def __setattr__(self, name: str, value: Any) -> None: + object.__setattr__(self, name, value) + + @classmethod + def set_default(cls, default: Optional[Self]) -> None: + """Set default instance of configuration. + + It stores default configuration, which can be + returned by get_default_copy method. + + :param default: object of Configuration + """ + cls._default = default + + @classmethod + def get_default_copy(cls) -> Self: + """Deprecated. Please use `get_default` instead. + + Deprecated. Please use `get_default` instead. + + :return: The configuration object. + """ + return cls.get_default() + + @classmethod + def get_default(cls) -> Self: + """Return the default configuration. + + This method returns newly created, based on default constructor, + object of Configuration class or returns a copy of default + configuration. + + :return: The configuration object. + """ + if cls._default is None: + cls._default = cls() + return cls._default + + @property + def logger_file(self) -> Optional[str]: + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value: Optional[str]) -> None: + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in self.logger.items(): + logger.addHandler(self.logger_file_handler) + + @property + def debug(self) -> bool: + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value: bool) -> None: + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in self.logger.items(): + logger.setLevel(logging.DEBUG) + # turn on httplib debug + httplib.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in self.logger.items(): + logger.setLevel(logging.WARNING) + # turn off httplib debug + httplib.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self) -> str: + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value: str) -> None: + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier: str, alias: Optional[str]=None) -> Optional[str]: + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :param alias: The alternative identifier of apiKey. + :return: The token for api key authentication. + """ + if self.refresh_api_key_hook is not None: + self.refresh_api_key_hook(self) + key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None) + if key: + prefix = self.api_key_prefix.get(identifier) + if prefix: + return "%s %s" % (prefix, key) + else: + return key + + return None + + def get_basic_auth_token(self) -> Optional[str]: + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + username = "" + if self.username is not None: + username = self.username + password = "" + if self.password is not None: + password = self.password + + return urllib3.util.make_headers( + basic_auth=username + ':' + password + ).get('authorization') + + def auth_settings(self)-> AuthSettings: + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + auth: AuthSettings = {} + return auth + + def to_debug_report(self) -> str: + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: 0.0.0-dev\n"\ + "SDK Package Version: 1.0.0".\ + format(env=sys.platform, pyversion=sys.version) + + def get_host_settings(self) -> List[HostSetting]: + """Gets an array of host settings + + :return: An array of host settings + """ + return [ + { + 'url': "", + 'description': "No description provided", + } + ] + + def get_host_from_settings( + self, + index: Optional[int], + variables: Optional[ServerVariablesT]=None, + servers: Optional[List[HostSetting]]=None, + ) -> str: + """Gets host URL based on the index and variables + :param index: array index of the host settings + :param variables: hash of variable and the corresponding value + :param servers: an array of host settings or None + :return: URL based on host settings + """ + if index is None: + return self._base_path + + variables = {} if variables is None else variables + servers = self.get_host_settings() if servers is None else servers + + try: + server = servers[index] + except IndexError: + raise ValueError( + "Invalid index {0} when selecting the host settings. " + "Must be less than {1}".format(index, len(servers))) + + url = server['url'] + + # go through variables and replace placeholders + for variable_name, variable in server.get('variables', {}).items(): + used_value = variables.get( + variable_name, variable['default_value']) + + if 'enum_values' in variable \ + and variable['enum_values'] \ + and used_value not in variable['enum_values']: + raise ValueError( + "The variable `{0}` in the host URL has invalid value " + "{1}. Must be {2}.".format( + variable_name, variables[variable_name], + variable['enum_values'])) + + url = url.replace("{" + variable_name + "}", used_value) + + return url + + @property + def host(self) -> str: + """Return generated host.""" + return self.get_host_from_settings(self.server_index, variables=self.server_variables) + + @host.setter + def host(self, value: str) -> None: + """Fix base path.""" + self._base_path = value + self.server_index = None diff --git a/src/otari/_client/exceptions.py b/src/otari/_client/exceptions.py new file mode 100644 index 0000000..2a606c6 --- /dev/null +++ b/src/otari/_client/exceptions.py @@ -0,0 +1,218 @@ +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from typing import Any, Optional +from typing_extensions import Self + +class OpenApiException(Exception): + """The base exception class for all OpenAPIExceptions""" + + +class ApiTypeError(OpenApiException, TypeError): + def __init__(self, msg, path_to_item=None, valid_classes=None, + key_type=None) -> None: + """ Raises an exception for TypeErrors + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list): a list of keys an indices to get to the + current_item + None if unset + valid_classes (tuple): the primitive classes that current item + should be an instance of + None if unset + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + None if unset + """ + self.path_to_item = path_to_item + self.valid_classes = valid_classes + self.key_type = key_type + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiTypeError, self).__init__(full_msg) + + +class ApiValueError(OpenApiException, ValueError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list) the path to the exception in the + received_data dict. None if unset + """ + + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiValueError, self).__init__(full_msg) + + +class ApiAttributeError(OpenApiException, AttributeError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Raised when an attribute reference or assignment fails. + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiAttributeError, self).__init__(full_msg) + + +class ApiKeyError(OpenApiException, KeyError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiKeyError, self).__init__(full_msg) + + +class ApiException(OpenApiException): + + def __init__( + self, + status=None, + reason=None, + http_resp=None, + *, + body: Optional[str] = None, + data: Optional[Any] = None, + ) -> None: + self.status = status + self.reason = reason + self.body = body + self.data = data + self.headers = None + + if http_resp: + if self.status is None: + self.status = http_resp.status + if self.reason is None: + self.reason = http_resp.reason + if self.body is None: + try: + self.body = http_resp.data.decode('utf-8') + except Exception: + pass + self.headers = http_resp.headers + + @classmethod + def from_response( + cls, + *, + http_resp, + body: Optional[str], + data: Optional[Any], + ) -> Self: + if http_resp.status == 400: + raise BadRequestException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 401: + raise UnauthorizedException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 403: + raise ForbiddenException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 404: + raise NotFoundException(http_resp=http_resp, body=body, data=data) + + # Added new conditions for 409 and 422 + if http_resp.status == 409: + raise ConflictException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 422: + raise UnprocessableEntityException(http_resp=http_resp, body=body, data=data) + + if 500 <= http_resp.status <= 599: + raise ServiceException(http_resp=http_resp, body=body, data=data) + raise ApiException(http_resp=http_resp, body=body, data=data) + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + if self.data: + error_message += "HTTP response data: {0}\n".format(self.data) + + return error_message + + +class BadRequestException(ApiException): + pass + + +class NotFoundException(ApiException): + pass + + +class UnauthorizedException(ApiException): + pass + + +class ForbiddenException(ApiException): + pass + + +class ServiceException(ApiException): + pass + + +class ConflictException(ApiException): + """Exception for HTTP 409 Conflict.""" + pass + + +class UnprocessableEntityException(ApiException): + """Exception for HTTP 422 Unprocessable Entity.""" + pass + + +def render_path(path_to_item): + """Returns a string representation of a path""" + result = "" + for pth in path_to_item: + if isinstance(pth, int): + result += "[{0}]".format(pth) + else: + result += "['{0}']".format(pth) + return result diff --git a/src/otari/_client/models/__init__.py b/src/otari/_client/models/__init__.py new file mode 100644 index 0000000..d886a76 --- /dev/null +++ b/src/otari/_client/models/__init__.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +# flake8: noqa +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +# import models into model package +from otari._client.models.audio_speech_request import AudioSpeechRequest +from otari._client.models.batch_request_item import BatchRequestItem +from otari._client.models.budget_response import BudgetResponse +from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio +from otari._client.models.cc_chat_completion_message import CCChatCompletionMessage +from otari._client.models.cc_chat_completion_message_custom_tool_call import CCChatCompletionMessageCustomToolCall +from otari._client.models.cc_chat_completion_message_function_tool_call import CCChatCompletionMessageFunctionToolCall +from otari._client.models.cc_chat_completion_message_tool_calls_inner import CCChatCompletionMessageToolCallsInner +from otari._client.models.cc_chat_completion_token_logprob import CCChatCompletionTokenLogprob +from otari._client.models.cc_choice import CCChoice +from otari._client.models.cc_choice_logprobs import CCChoiceLogprobs +from otari._client.models.cc_completion_tokens_details import CCCompletionTokensDetails +from otari._client.models.cc_completion_usage import CCCompletionUsage +from otari._client.models.cc_custom import CCCustom +from otari._client.models.cc_function import CCFunction +from otari._client.models.cc_function_call import CCFunctionCall +from otari._client.models.cck_chat_completion_token_logprob import CCKChatCompletionTokenLogprob +from otari._client.models.cck_choice_delta import CCKChoiceDelta +from otari._client.models.cck_choice_delta_function_call import CCKChoiceDeltaFunctionCall +from otari._client.models.cck_choice_delta_tool_call import CCKChoiceDeltaToolCall +from otari._client.models.cck_choice_delta_tool_call_function import CCKChoiceDeltaToolCallFunction +from otari._client.models.cck_choice_logprobs import CCKChoiceLogprobs +from otari._client.models.cck_chunk_choice import CCKChunkChoice +from otari._client.models.cck_completion_tokens_details import CCKCompletionTokensDetails +from otari._client.models.cck_completion_usage import CCKCompletionUsage +from otari._client.models.cck_prompt_tokens_details import CCKPromptTokensDetails +from otari._client.models.cck_reasoning import CCKReasoning +from otari._client.models.cck_top_logprob import CCKTopLogprob +from otari._client.models.cc_prompt_tokens_details import CCPromptTokensDetails +from otari._client.models.cc_reasoning import CCReasoning +from otari._client.models.cc_top_logprob import CCTopLogprob +from otari._client.models.caller import Caller +from otari._client.models.chat_completion import ChatCompletion +from otari._client.models.chat_completion_chunk import ChatCompletionChunk +from otari._client.models.chat_completion_request import ChatCompletionRequest +from otari._client.models.chat_message_input import ChatMessageInput +from otari._client.models.content import Content +from otari._client.models.content1 import Content1 +from otari._client.models.content2 import Content2 +from otari._client.models.content2_any_of_inner import Content2AnyOfInner +from otari._client.models.content3 import Content3 +from otari._client.models.content4 import Content4 +from otari._client.models.content5 import Content5 +from otari._client.models.content6 import Content6 +from otari._client.models.content7 import Content7 +from otari._client.models.content8 import Content8 +from otari._client.models.content9_inner import Content9Inner +from otari._client.models.content_any_of_inner import ContentAnyOfInner +from otari._client.models.create_batch_request import CreateBatchRequest +from otari._client.models.create_budget_request import CreateBudgetRequest +from otari._client.models.create_embedding_response import CreateEmbeddingResponse +from otari._client.models.create_key_request import CreateKeyRequest +from otari._client.models.create_key_response import CreateKeyResponse +from otari._client.models.create_user_request import CreateUserRequest +from otari._client.models.emb_embedding import EMBEmbedding +from otari._client.models.emb_usage import EMBUsage +from otari._client.models.embedding_request import EmbeddingRequest +from otari._client.models.guardrail_config import GuardrailConfig +from otari._client.models.http_validation_error import HTTPValidationError +from otari._client.models.image_generation_request import ImageGenerationRequest +from otari._client.models.input import Input +from otari._client.models.input1 import Input1 +from otari._client.models.key_info import KeyInfo +from otari._client.models.location_inner import LocationInner +from otari._client.models.mr_base64_pdf_source import MRBase64PDFSource +from otari._client.models.mr_bash_code_execution_output_block import MRBashCodeExecutionOutputBlock +from otari._client.models.mr_bash_code_execution_result_block import MRBashCodeExecutionResultBlock +from otari._client.models.mr_bash_code_execution_tool_result_block import MRBashCodeExecutionToolResultBlock +from otari._client.models.mr_bash_code_execution_tool_result_error import MRBashCodeExecutionToolResultError +from otari._client.models.mr_cache_creation import MRCacheCreation +from otari._client.models.mr_citation_char_location import MRCitationCharLocation +from otari._client.models.mr_citation_content_block_location import MRCitationContentBlockLocation +from otari._client.models.mr_citation_page_location import MRCitationPageLocation +from otari._client.models.mr_citations_config import MRCitationsConfig +from otari._client.models.mr_citations_search_result_location import MRCitationsSearchResultLocation +from otari._client.models.mr_citations_web_search_result_location import MRCitationsWebSearchResultLocation +from otari._client.models.mr_code_execution_output_block import MRCodeExecutionOutputBlock +from otari._client.models.mr_code_execution_result_block import MRCodeExecutionResultBlock +from otari._client.models.mr_code_execution_tool_result_block import MRCodeExecutionToolResultBlock +from otari._client.models.mr_code_execution_tool_result_error import MRCodeExecutionToolResultError +from otari._client.models.mr_container import MRContainer +from otari._client.models.mr_container_upload_block import MRContainerUploadBlock +from otari._client.models.mr_direct_caller import MRDirectCaller +from otari._client.models.mr_document_block import MRDocumentBlock +from otari._client.models.mr_encrypted_code_execution_result_block import MREncryptedCodeExecutionResultBlock +from otari._client.models.mr_plain_text_source import MRPlainTextSource +from otari._client.models.mr_redacted_thinking_block import MRRedactedThinkingBlock +from otari._client.models.mr_refusal_stop_details import MRRefusalStopDetails +from otari._client.models.mr_server_tool_caller import MRServerToolCaller +from otari._client.models.mr_server_tool_caller20260120 import MRServerToolCaller20260120 +from otari._client.models.mr_server_tool_usage import MRServerToolUsage +from otari._client.models.mr_server_tool_use_block import MRServerToolUseBlock +from otari._client.models.mr_text_block import MRTextBlock +from otari._client.models.mr_text_block_citations_inner import MRTextBlockCitationsInner +from otari._client.models.mr_text_editor_code_execution_create_result_block import MRTextEditorCodeExecutionCreateResultBlock +from otari._client.models.mr_text_editor_code_execution_str_replace_result_block import MRTextEditorCodeExecutionStrReplaceResultBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_block import MRTextEditorCodeExecutionToolResultBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_error import MRTextEditorCodeExecutionToolResultError +from otari._client.models.mr_text_editor_code_execution_view_result_block import MRTextEditorCodeExecutionViewResultBlock +from otari._client.models.mr_thinking_block import MRThinkingBlock +from otari._client.models.mr_tool_reference_block import MRToolReferenceBlock +from otari._client.models.mr_tool_search_tool_result_block import MRToolSearchToolResultBlock +from otari._client.models.mr_tool_search_tool_result_error import MRToolSearchToolResultError +from otari._client.models.mr_tool_search_tool_search_result_block import MRToolSearchToolSearchResultBlock +from otari._client.models.mr_tool_use_block import MRToolUseBlock +from otari._client.models.mr_usage import MRUsage +from otari._client.models.mr_web_fetch_block import MRWebFetchBlock +from otari._client.models.mr_web_fetch_tool_result_block import MRWebFetchToolResultBlock +from otari._client.models.mr_web_fetch_tool_result_error_block import MRWebFetchToolResultErrorBlock +from otari._client.models.mr_web_search_result_block import MRWebSearchResultBlock +from otari._client.models.mr_web_search_tool_result_block import MRWebSearchToolResultBlock +from otari._client.models.mr_web_search_tool_result_error import MRWebSearchToolResultError +from otari._client.models.msg_audio import MSGAudio +from otari._client.models.msg_chat_completion_assistant_message_param import MSGChatCompletionAssistantMessageParam +from otari._client.models.msg_chat_completion_content_part_image_param import MSGChatCompletionContentPartImageParam +from otari._client.models.msg_chat_completion_content_part_input_audio_param import MSGChatCompletionContentPartInputAudioParam +from otari._client.models.msg_chat_completion_content_part_refusal_param import MSGChatCompletionContentPartRefusalParam +from otari._client.models.msg_chat_completion_content_part_text_param import MSGChatCompletionContentPartTextParam +from otari._client.models.msg_chat_completion_developer_message_param import MSGChatCompletionDeveloperMessageParam +from otari._client.models.msg_chat_completion_function_message_param import MSGChatCompletionFunctionMessageParam +from otari._client.models.msg_chat_completion_message_custom_tool_call_param import MSGChatCompletionMessageCustomToolCallParam +from otari._client.models.msg_chat_completion_message_function_tool_call_param import MSGChatCompletionMessageFunctionToolCallParam +from otari._client.models.msg_chat_completion_system_message_param import MSGChatCompletionSystemMessageParam +from otari._client.models.msg_chat_completion_tool_message_param import MSGChatCompletionToolMessageParam +from otari._client.models.msg_chat_completion_user_message_param import MSGChatCompletionUserMessageParam +from otari._client.models.msg_custom import MSGCustom +from otari._client.models.msg_file import MSGFile +from otari._client.models.msg_file_file import MSGFileFile +from otari._client.models.msg_function import MSGFunction +from otari._client.models.msg_function_call import MSGFunctionCall +from otari._client.models.msg_image_url import MSGImageURL +from otari._client.models.msg_input_audio import MSGInputAudio +from otari._client.models.mcp_server_config import McpServerConfig +from otari._client.models.message_response import MessageResponse +from otari._client.models.messages_request import MessagesRequest +from otari._client.models.model import Model +from otari._client.models.model_list_response import ModelListResponse +from otari._client.models.model_object import ModelObject +from otari._client.models.model_pricing_info import ModelPricingInfo +from otari._client.models.moderation_request import ModerationRequest +from otari._client.models.moderation_response import ModerationResponse +from otari._client.models.moderation_result import ModerationResult +from otari._client.models.pricing_response import PricingResponse +from otari._client.models.rr_rerank_meta import RRRerankMeta +from otari._client.models.rr_rerank_result import RRRerankResult +from otari._client.models.rr_rerank_usage import RRRerankUsage +from otari._client.models.rerank_request import RerankRequest +from otari._client.models.rerank_response import RerankResponse +from otari._client.models.responses_request import ResponsesRequest +from otari._client.models.set_pricing_request import SetPricingRequest +from otari._client.models.source import Source +from otari._client.models.system import System +from otari._client.models.tool_calls_inner import ToolCallsInner +from otari._client.models.tool_choice import ToolChoice +from otari._client.models.update_budget_request import UpdateBudgetRequest +from otari._client.models.update_key_request import UpdateKeyRequest +from otari._client.models.update_user_request import UpdateUserRequest +from otari._client.models.usage_entry import UsageEntry +from otari._client.models.usage_log_response import UsageLogResponse +from otari._client.models.user_response import UserResponse +from otari._client.models.validation_error import ValidationError + diff --git a/src/otari/_client/models/audio_speech_request.py b/src/otari/_client/models/audio_speech_request.py new file mode 100644 index 0000000..0cc33ee --- /dev/null +++ b/src/otari/_client/models/audio_speech_request.py @@ -0,0 +1,120 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AudioSpeechRequest(BaseModel): + """ + OpenAI-compatible audio speech (TTS) request. + """ # noqa: E501 + input: StrictStr + instructions: Optional[StrictStr] = None + model: StrictStr + response_format: Optional[StrictStr] = None + speed: Optional[Union[StrictFloat, StrictInt]] = None + user: Optional[StrictStr] = None + voice: StrictStr + __properties: ClassVar[List[str]] = ["input", "instructions", "model", "response_format", "speed", "user", "voice"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AudioSpeechRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if instructions (nullable) is None + # and model_fields_set contains the field + if self.instructions is None and "instructions" in self.model_fields_set: + _dict['instructions'] = None + + # set to None if response_format (nullable) is None + # and model_fields_set contains the field + if self.response_format is None and "response_format" in self.model_fields_set: + _dict['response_format'] = None + + # set to None if speed (nullable) is None + # and model_fields_set contains the field + if self.speed is None and "speed" in self.model_fields_set: + _dict['speed'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AudioSpeechRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input": obj.get("input"), + "instructions": obj.get("instructions"), + "model": obj.get("model"), + "response_format": obj.get("response_format"), + "speed": obj.get("speed"), + "user": obj.get("user"), + "voice": obj.get("voice") + }) + return _obj + + diff --git a/src/otari/_client/models/batch_request_item.py b/src/otari/_client/models/batch_request_item.py new file mode 100644 index 0000000..149a48d --- /dev/null +++ b/src/otari/_client/models/batch_request_item.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class BatchRequestItem(BaseModel): + """ + BatchRequestItem + """ # noqa: E501 + body: Dict[str, Any] + custom_id: StrictStr + __properties: ClassVar[List[str]] = ["body", "custom_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchRequestItem from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchRequestItem from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "body": obj.get("body"), + "custom_id": obj.get("custom_id") + }) + return _obj + + diff --git a/src/otari/_client/models/budget_response.py b/src/otari/_client/models/budget_response.py new file mode 100644 index 0000000..2b4d473 --- /dev/null +++ b/src/otari/_client/models/budget_response.py @@ -0,0 +1,106 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class BudgetResponse(BaseModel): + """ + Response model for budget information. + """ # noqa: E501 + budget_duration_sec: Optional[StrictInt] + budget_id: StrictStr + created_at: StrictStr + max_budget: Optional[Union[StrictFloat, StrictInt]] + updated_at: StrictStr + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "updated_at"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BudgetResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if budget_duration_sec (nullable) is None + # and model_fields_set contains the field + if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: + _dict['budget_duration_sec'] = None + + # set to None if max_budget (nullable) is None + # and model_fields_set contains the field + if self.max_budget is None and "max_budget" in self.model_fields_set: + _dict['max_budget'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BudgetResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "budget_duration_sec": obj.get("budget_duration_sec"), + "budget_id": obj.get("budget_id"), + "created_at": obj.get("created_at"), + "max_budget": obj.get("max_budget"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/src/otari/_client/models/caller.py b/src/otari/_client/models/caller.py new file mode 100644 index 0000000..a3a2d72 --- /dev/null +++ b/src/otari/_client/models/caller.py @@ -0,0 +1,155 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_direct_caller import MRDirectCaller +from otari._client.models.mr_server_tool_caller import MRServerToolCaller +from otari._client.models.mr_server_tool_caller20260120 import MRServerToolCaller20260120 +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CALLER_ANY_OF_SCHEMAS = ["MRDirectCaller", "MRServerToolCaller", "MRServerToolCaller20260120"] + +class Caller(BaseModel): + """ + Caller + """ + + # data type: MRDirectCaller + anyof_schema_1_validator: Optional[MRDirectCaller] = None + # data type: MRServerToolCaller + anyof_schema_2_validator: Optional[MRServerToolCaller] = None + # data type: MRServerToolCaller20260120 + anyof_schema_3_validator: Optional[MRServerToolCaller20260120] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRDirectCaller, MRServerToolCaller, MRServerToolCaller20260120]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRDirectCaller", "MRServerToolCaller", "MRServerToolCaller20260120" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = Caller.model_construct() + error_messages = [] + # validate data type: MRDirectCaller + if not isinstance(v, MRDirectCaller): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRDirectCaller`") + else: + return v + + # validate data type: MRServerToolCaller + if not isinstance(v, MRServerToolCaller): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRServerToolCaller`") + else: + return v + + # validate data type: MRServerToolCaller20260120 + if not isinstance(v, MRServerToolCaller20260120): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRServerToolCaller20260120`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Caller with anyOf schemas: MRDirectCaller, MRServerToolCaller, MRServerToolCaller20260120. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # anyof_schema_1_validator: Optional[MRDirectCaller] = None + try: + instance.actual_instance = MRDirectCaller.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRServerToolCaller] = None + try: + instance.actual_instance = MRServerToolCaller.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MRServerToolCaller20260120] = None + try: + instance.actual_instance = MRServerToolCaller20260120.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Caller with anyOf schemas: MRDirectCaller, MRServerToolCaller, MRServerToolCaller20260120. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRDirectCaller, MRServerToolCaller, MRServerToolCaller20260120]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/cc_chat_completion_audio.py b/src/otari/_client/models/cc_chat_completion_audio.py new file mode 100644 index 0000000..88acc49 --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_audio.py @@ -0,0 +1,107 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChatCompletionAudio(BaseModel): + """ + If the audio output modality is requested, this object contains data about the audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). + """ # noqa: E501 + id: StrictStr + data: StrictStr + expires_at: StrictInt + transcript: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "data", "expires_at", "transcript"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChatCompletionAudio from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChatCompletionAudio from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "data": obj.get("data"), + "expires_at": obj.get("expires_at"), + "transcript": obj.get("transcript") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_chat_completion_message.py b/src/otari/_client/models/cc_chat_completion_message.py new file mode 100644 index 0000000..b6d515b --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_message.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio +from otari._client.models.cc_chat_completion_message_tool_calls_inner import CCChatCompletionMessageToolCallsInner +from otari._client.models.cc_function_call import CCFunctionCall +from otari._client.models.cc_reasoning import CCReasoning +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChatCompletionMessage(BaseModel): + """ + CCChatCompletionMessage + """ # noqa: E501 + content: Optional[StrictStr] = None + refusal: Optional[StrictStr] = None + role: StrictStr + annotations: Optional[List[Dict[str, Any]]] = None + audio: Optional[CCChatCompletionAudio] = None + function_call: Optional[CCFunctionCall] = None + tool_calls: Optional[List[CCChatCompletionMessageToolCallsInner]] = None + reasoning: Optional[CCReasoning] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "refusal", "role", "annotations", "audio", "function_call", "tool_calls", "reasoning"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['assistant']): + raise ValueError("must be one of enum values ('assistant')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChatCompletionMessage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of audio + if self.audio: + _dict['audio'] = self.audio.to_dict() + # override the default output from pydantic by calling `to_dict()` of function_call + if self.function_call: + _dict['function_call'] = self.function_call.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in tool_calls (list) + _items = [] + if self.tool_calls: + for _item_tool_calls in self.tool_calls: + if _item_tool_calls: + _items.append(_item_tool_calls.to_dict()) + _dict['tool_calls'] = _items + # override the default output from pydantic by calling `to_dict()` of reasoning + if self.reasoning: + _dict['reasoning'] = self.reasoning.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + # set to None if refusal (nullable) is None + # and model_fields_set contains the field + if self.refusal is None and "refusal" in self.model_fields_set: + _dict['refusal'] = None + + # set to None if annotations (nullable) is None + # and model_fields_set contains the field + if self.annotations is None and "annotations" in self.model_fields_set: + _dict['annotations'] = None + + # set to None if audio (nullable) is None + # and model_fields_set contains the field + if self.audio is None and "audio" in self.model_fields_set: + _dict['audio'] = None + + # set to None if function_call (nullable) is None + # and model_fields_set contains the field + if self.function_call is None and "function_call" in self.model_fields_set: + _dict['function_call'] = None + + # set to None if tool_calls (nullable) is None + # and model_fields_set contains the field + if self.tool_calls is None and "tool_calls" in self.model_fields_set: + _dict['tool_calls'] = None + + # set to None if reasoning (nullable) is None + # and model_fields_set contains the field + if self.reasoning is None and "reasoning" in self.model_fields_set: + _dict['reasoning'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChatCompletionMessage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content"), + "refusal": obj.get("refusal"), + "role": obj.get("role"), + "annotations": obj.get("annotations"), + "audio": CCChatCompletionAudio.from_dict(obj["audio"]) if obj.get("audio") is not None else None, + "function_call": CCFunctionCall.from_dict(obj["function_call"]) if obj.get("function_call") is not None else None, + "tool_calls": [CCChatCompletionMessageToolCallsInner.from_dict(_item) for _item in obj["tool_calls"]] if obj.get("tool_calls") is not None else None, + "reasoning": CCReasoning.from_dict(obj["reasoning"]) if obj.get("reasoning") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_chat_completion_message_custom_tool_call.py b/src/otari/_client/models/cc_chat_completion_message_custom_tool_call.py new file mode 100644 index 0000000..cab3b5b --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_message_custom_tool_call.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.cc_custom import CCCustom +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChatCompletionMessageCustomToolCall(BaseModel): + """ + A call to a custom tool created by the model. + """ # noqa: E501 + id: StrictStr + custom: CCCustom + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "custom", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['custom']): + raise ValueError("must be one of enum values ('custom')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChatCompletionMessageCustomToolCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of custom + if self.custom: + _dict['custom'] = self.custom.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChatCompletionMessageCustomToolCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "custom": CCCustom.from_dict(obj["custom"]) if obj.get("custom") is not None else None, + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_chat_completion_message_function_tool_call.py b/src/otari/_client/models/cc_chat_completion_message_function_tool_call.py new file mode 100644 index 0000000..fd1c101 --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_message_function_tool_call.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.cc_function import CCFunction +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChatCompletionMessageFunctionToolCall(BaseModel): + """ + A call to a function tool created by the model. + """ # noqa: E501 + id: StrictStr + function: CCFunction + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "function", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['function']): + raise ValueError("must be one of enum values ('function')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChatCompletionMessageFunctionToolCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of function + if self.function: + _dict['function'] = self.function.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChatCompletionMessageFunctionToolCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "function": CCFunction.from_dict(obj["function"]) if obj.get("function") is not None else None, + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_chat_completion_message_tool_calls_inner.py b/src/otari/_client/models/cc_chat_completion_message_tool_calls_inner.py new file mode 100644 index 0000000..2fd774f --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_message_tool_calls_inner.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.cc_chat_completion_message_custom_tool_call import CCChatCompletionMessageCustomToolCall +from otari._client.models.cc_chat_completion_message_function_tool_call import CCChatCompletionMessageFunctionToolCall +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CCCHATCOMPLETIONMESSAGETOOLCALLSINNER_ANY_OF_SCHEMAS = ["CCChatCompletionMessageCustomToolCall", "CCChatCompletionMessageFunctionToolCall"] + +class CCChatCompletionMessageToolCallsInner(BaseModel): + """ + CCChatCompletionMessageToolCallsInner + """ + + # data type: CCChatCompletionMessageFunctionToolCall + anyof_schema_1_validator: Optional[CCChatCompletionMessageFunctionToolCall] = None + # data type: CCChatCompletionMessageCustomToolCall + anyof_schema_2_validator: Optional[CCChatCompletionMessageCustomToolCall] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[CCChatCompletionMessageCustomToolCall, CCChatCompletionMessageFunctionToolCall]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "CCChatCompletionMessageCustomToolCall", "CCChatCompletionMessageFunctionToolCall" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = CCChatCompletionMessageToolCallsInner.model_construct() + error_messages = [] + # validate data type: CCChatCompletionMessageFunctionToolCall + if not isinstance(v, CCChatCompletionMessageFunctionToolCall): + error_messages.append(f"Error! Input type `{type(v)}` is not `CCChatCompletionMessageFunctionToolCall`") + else: + return v + + # validate data type: CCChatCompletionMessageCustomToolCall + if not isinstance(v, CCChatCompletionMessageCustomToolCall): + error_messages.append(f"Error! Input type `{type(v)}` is not `CCChatCompletionMessageCustomToolCall`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in CCChatCompletionMessageToolCallsInner with anyOf schemas: CCChatCompletionMessageCustomToolCall, CCChatCompletionMessageFunctionToolCall. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[CCChatCompletionMessageFunctionToolCall] = None + try: + instance.actual_instance = CCChatCompletionMessageFunctionToolCall.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[CCChatCompletionMessageCustomToolCall] = None + try: + instance.actual_instance = CCChatCompletionMessageCustomToolCall.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into CCChatCompletionMessageToolCallsInner with anyOf schemas: CCChatCompletionMessageCustomToolCall, CCChatCompletionMessageFunctionToolCall. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], CCChatCompletionMessageCustomToolCall, CCChatCompletionMessageFunctionToolCall]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/cc_chat_completion_token_logprob.py b/src/otari/_client/models/cc_chat_completion_token_logprob.py new file mode 100644 index 0000000..5443004 --- /dev/null +++ b/src/otari/_client/models/cc_chat_completion_token_logprob.py @@ -0,0 +1,120 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from otari._client.models.cc_top_logprob import CCTopLogprob +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChatCompletionTokenLogprob(BaseModel): + """ + CCChatCompletionTokenLogprob + """ # noqa: E501 + token: StrictStr + bytes: Optional[List[StrictInt]] = None + logprob: Union[StrictFloat, StrictInt] + top_logprobs: List[CCTopLogprob] + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["token", "bytes", "logprob", "top_logprobs"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChatCompletionTokenLogprob from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in top_logprobs (list) + _items = [] + if self.top_logprobs: + for _item_top_logprobs in self.top_logprobs: + if _item_top_logprobs: + _items.append(_item_top_logprobs.to_dict()) + _dict['top_logprobs'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if bytes (nullable) is None + # and model_fields_set contains the field + if self.bytes is None and "bytes" in self.model_fields_set: + _dict['bytes'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChatCompletionTokenLogprob from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "token": obj.get("token"), + "bytes": obj.get("bytes"), + "logprob": obj.get("logprob"), + "top_logprobs": [CCTopLogprob.from_dict(_item) for _item in obj["top_logprobs"]] if obj.get("top_logprobs") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_choice.py b/src/otari/_client/models/cc_choice.py new file mode 100644 index 0000000..2a23c8c --- /dev/null +++ b/src/otari/_client/models/cc_choice.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cc_chat_completion_message import CCChatCompletionMessage +from otari._client.models.cc_choice_logprobs import CCChoiceLogprobs +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChoice(BaseModel): + """ + CCChoice + """ # noqa: E501 + finish_reason: StrictStr + index: StrictInt + logprobs: Optional[CCChoiceLogprobs] = None + message: CCChatCompletionMessage + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["finish_reason", "index", "logprobs", "message"] + + @field_validator('finish_reason') + def finish_reason_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['stop', 'length', 'tool_calls', 'content_filter', 'function_call']): + raise ValueError("must be one of enum values ('stop', 'length', 'tool_calls', 'content_filter', 'function_call')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChoice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of logprobs + if self.logprobs: + _dict['logprobs'] = self.logprobs.to_dict() + # override the default output from pydantic by calling `to_dict()` of message + if self.message: + _dict['message'] = self.message.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if logprobs (nullable) is None + # and model_fields_set contains the field + if self.logprobs is None and "logprobs" in self.model_fields_set: + _dict['logprobs'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChoice from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "finish_reason": obj.get("finish_reason"), + "index": obj.get("index"), + "logprobs": CCChoiceLogprobs.from_dict(obj["logprobs"]) if obj.get("logprobs") is not None else None, + "message": CCChatCompletionMessage.from_dict(obj["message"]) if obj.get("message") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_choice_logprobs.py b/src/otari/_client/models/cc_choice_logprobs.py new file mode 100644 index 0000000..7bb4175 --- /dev/null +++ b/src/otari/_client/models/cc_choice_logprobs.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cc_chat_completion_token_logprob import CCChatCompletionTokenLogprob +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCChoiceLogprobs(BaseModel): + """ + Log probability information for the choice. + """ # noqa: E501 + content: Optional[List[CCChatCompletionTokenLogprob]] = None + refusal: Optional[List[CCChatCompletionTokenLogprob]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "refusal"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCChoiceLogprobs from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in refusal (list) + _items = [] + if self.refusal: + for _item_refusal in self.refusal: + if _item_refusal: + _items.append(_item_refusal.to_dict()) + _dict['refusal'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + # set to None if refusal (nullable) is None + # and model_fields_set contains the field + if self.refusal is None and "refusal" in self.model_fields_set: + _dict['refusal'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCChoiceLogprobs from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": [CCChatCompletionTokenLogprob.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "refusal": [CCChatCompletionTokenLogprob.from_dict(_item) for _item in obj["refusal"]] if obj.get("refusal") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_completion_tokens_details.py b/src/otari/_client/models/cc_completion_tokens_details.py new file mode 100644 index 0000000..47caf33 --- /dev/null +++ b/src/otari/_client/models/cc_completion_tokens_details.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCCompletionTokensDetails(BaseModel): + """ + Breakdown of tokens used in a completion. + """ # noqa: E501 + accepted_prediction_tokens: Optional[StrictInt] = None + audio_tokens: Optional[StrictInt] = None + reasoning_tokens: Optional[StrictInt] = None + rejected_prediction_tokens: Optional[StrictInt] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["accepted_prediction_tokens", "audio_tokens", "reasoning_tokens", "rejected_prediction_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCCompletionTokensDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if accepted_prediction_tokens (nullable) is None + # and model_fields_set contains the field + if self.accepted_prediction_tokens is None and "accepted_prediction_tokens" in self.model_fields_set: + _dict['accepted_prediction_tokens'] = None + + # set to None if audio_tokens (nullable) is None + # and model_fields_set contains the field + if self.audio_tokens is None and "audio_tokens" in self.model_fields_set: + _dict['audio_tokens'] = None + + # set to None if reasoning_tokens (nullable) is None + # and model_fields_set contains the field + if self.reasoning_tokens is None and "reasoning_tokens" in self.model_fields_set: + _dict['reasoning_tokens'] = None + + # set to None if rejected_prediction_tokens (nullable) is None + # and model_fields_set contains the field + if self.rejected_prediction_tokens is None and "rejected_prediction_tokens" in self.model_fields_set: + _dict['rejected_prediction_tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCCompletionTokensDetails from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "accepted_prediction_tokens": obj.get("accepted_prediction_tokens"), + "audio_tokens": obj.get("audio_tokens"), + "reasoning_tokens": obj.get("reasoning_tokens"), + "rejected_prediction_tokens": obj.get("rejected_prediction_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_completion_usage.py b/src/otari/_client/models/cc_completion_usage.py new file mode 100644 index 0000000..105ca2f --- /dev/null +++ b/src/otari/_client/models/cc_completion_usage.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cc_completion_tokens_details import CCCompletionTokensDetails +from otari._client.models.cc_prompt_tokens_details import CCPromptTokensDetails +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCCompletionUsage(BaseModel): + """ + Usage statistics for the completion request. + """ # noqa: E501 + completion_tokens: StrictInt + prompt_tokens: StrictInt + total_tokens: StrictInt + completion_tokens_details: Optional[CCCompletionTokensDetails] = None + prompt_tokens_details: Optional[CCPromptTokensDetails] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["completion_tokens", "prompt_tokens", "total_tokens", "completion_tokens_details", "prompt_tokens_details"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCCompletionUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of completion_tokens_details + if self.completion_tokens_details: + _dict['completion_tokens_details'] = self.completion_tokens_details.to_dict() + # override the default output from pydantic by calling `to_dict()` of prompt_tokens_details + if self.prompt_tokens_details: + _dict['prompt_tokens_details'] = self.prompt_tokens_details.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if completion_tokens_details (nullable) is None + # and model_fields_set contains the field + if self.completion_tokens_details is None and "completion_tokens_details" in self.model_fields_set: + _dict['completion_tokens_details'] = None + + # set to None if prompt_tokens_details (nullable) is None + # and model_fields_set contains the field + if self.prompt_tokens_details is None and "prompt_tokens_details" in self.model_fields_set: + _dict['prompt_tokens_details'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCCompletionUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "completion_tokens": obj.get("completion_tokens"), + "prompt_tokens": obj.get("prompt_tokens"), + "total_tokens": obj.get("total_tokens"), + "completion_tokens_details": CCCompletionTokensDetails.from_dict(obj["completion_tokens_details"]) if obj.get("completion_tokens_details") is not None else None, + "prompt_tokens_details": CCPromptTokensDetails.from_dict(obj["prompt_tokens_details"]) if obj.get("prompt_tokens_details") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_custom.py b/src/otari/_client/models/cc_custom.py new file mode 100644 index 0000000..54686ac --- /dev/null +++ b/src/otari/_client/models/cc_custom.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCCustom(BaseModel): + """ + The custom tool that the model called. + """ # noqa: E501 + input: StrictStr + name: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["input", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCCustom from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCCustom from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input": obj.get("input"), + "name": obj.get("name") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_function.py b/src/otari/_client/models/cc_function.py new file mode 100644 index 0000000..af06013 --- /dev/null +++ b/src/otari/_client/models/cc_function.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCFunction(BaseModel): + """ + The function that the model called. + """ # noqa: E501 + arguments: StrictStr + name: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCFunction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCFunction from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_function_call.py b/src/otari/_client/models/cc_function_call.py new file mode 100644 index 0000000..25bb26f --- /dev/null +++ b/src/otari/_client/models/cc_function_call.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCFunctionCall(BaseModel): + """ + Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + """ # noqa: E501 + arguments: StrictStr + name: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCFunctionCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCFunctionCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_prompt_tokens_details.py b/src/otari/_client/models/cc_prompt_tokens_details.py new file mode 100644 index 0000000..dc36bbb --- /dev/null +++ b/src/otari/_client/models/cc_prompt_tokens_details.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCPromptTokensDetails(BaseModel): + """ + Breakdown of tokens used in the prompt. + """ # noqa: E501 + audio_tokens: Optional[StrictInt] = None + cached_tokens: Optional[StrictInt] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["audio_tokens", "cached_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCPromptTokensDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if audio_tokens (nullable) is None + # and model_fields_set contains the field + if self.audio_tokens is None and "audio_tokens" in self.model_fields_set: + _dict['audio_tokens'] = None + + # set to None if cached_tokens (nullable) is None + # and model_fields_set contains the field + if self.cached_tokens is None and "cached_tokens" in self.model_fields_set: + _dict['cached_tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCPromptTokensDetails from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "audio_tokens": obj.get("audio_tokens"), + "cached_tokens": obj.get("cached_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cc_reasoning.py b/src/otari/_client/models/cc_reasoning.py new file mode 100644 index 0000000..a985df3 --- /dev/null +++ b/src/otari/_client/models/cc_reasoning.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCReasoning(BaseModel): + """ + Reasoning content emitted by a model. Serializes as a plain JSON string so that responses are compatible with OpenAI-style clients that expect ``delta.reasoning`` / ``message.reasoning`` to be a string. The Python attribute ``content`` remains available for typed access (e.g. ``message.reasoning.content``). + """ # noqa: E501 + content: StrictStr + __properties: ClassVar[List[str]] = ["content"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCReasoning from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCReasoning from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content") + }) + return _obj + + diff --git a/src/otari/_client/models/cc_top_logprob.py b/src/otari/_client/models/cc_top_logprob.py new file mode 100644 index 0000000..f078648 --- /dev/null +++ b/src/otari/_client/models/cc_top_logprob.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCTopLogprob(BaseModel): + """ + CCTopLogprob + """ # noqa: E501 + token: StrictStr + bytes: Optional[List[StrictInt]] = None + logprob: Union[StrictFloat, StrictInt] + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["token", "bytes", "logprob"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCTopLogprob from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if bytes (nullable) is None + # and model_fields_set contains the field + if self.bytes is None and "bytes" in self.model_fields_set: + _dict['bytes'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCTopLogprob from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "token": obj.get("token"), + "bytes": obj.get("bytes"), + "logprob": obj.get("logprob") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_chat_completion_token_logprob.py b/src/otari/_client/models/cck_chat_completion_token_logprob.py new file mode 100644 index 0000000..cede850 --- /dev/null +++ b/src/otari/_client/models/cck_chat_completion_token_logprob.py @@ -0,0 +1,120 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from otari._client.models.cck_top_logprob import CCKTopLogprob +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChatCompletionTokenLogprob(BaseModel): + """ + CCKChatCompletionTokenLogprob + """ # noqa: E501 + token: StrictStr + bytes: Optional[List[StrictInt]] = None + logprob: Union[StrictFloat, StrictInt] + top_logprobs: List[CCKTopLogprob] + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["token", "bytes", "logprob", "top_logprobs"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChatCompletionTokenLogprob from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in top_logprobs (list) + _items = [] + if self.top_logprobs: + for _item_top_logprobs in self.top_logprobs: + if _item_top_logprobs: + _items.append(_item_top_logprobs.to_dict()) + _dict['top_logprobs'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if bytes (nullable) is None + # and model_fields_set contains the field + if self.bytes is None and "bytes" in self.model_fields_set: + _dict['bytes'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChatCompletionTokenLogprob from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "token": obj.get("token"), + "bytes": obj.get("bytes"), + "logprob": obj.get("logprob"), + "top_logprobs": [CCKTopLogprob.from_dict(_item) for _item in obj["top_logprobs"]] if obj.get("top_logprobs") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_choice_delta.py b/src/otari/_client/models/cck_choice_delta.py new file mode 100644 index 0000000..7e7c7ff --- /dev/null +++ b/src/otari/_client/models/cck_choice_delta.py @@ -0,0 +1,167 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_choice_delta_function_call import CCKChoiceDeltaFunctionCall +from otari._client.models.cck_choice_delta_tool_call import CCKChoiceDeltaToolCall +from otari._client.models.cck_reasoning import CCKReasoning +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChoiceDelta(BaseModel): + """ + CCKChoiceDelta + """ # noqa: E501 + content: Optional[StrictStr] = None + function_call: Optional[CCKChoiceDeltaFunctionCall] = None + refusal: Optional[StrictStr] = None + role: Optional[StrictStr] = None + tool_calls: Optional[List[CCKChoiceDeltaToolCall]] = None + reasoning: Optional[CCKReasoning] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "function_call", "refusal", "role", "tool_calls", "reasoning"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['developer', 'system', 'user', 'assistant', 'tool']): + raise ValueError("must be one of enum values ('developer', 'system', 'user', 'assistant', 'tool')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChoiceDelta from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of function_call + if self.function_call: + _dict['function_call'] = self.function_call.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in tool_calls (list) + _items = [] + if self.tool_calls: + for _item_tool_calls in self.tool_calls: + if _item_tool_calls: + _items.append(_item_tool_calls.to_dict()) + _dict['tool_calls'] = _items + # override the default output from pydantic by calling `to_dict()` of reasoning + if self.reasoning: + _dict['reasoning'] = self.reasoning.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + # set to None if function_call (nullable) is None + # and model_fields_set contains the field + if self.function_call is None and "function_call" in self.model_fields_set: + _dict['function_call'] = None + + # set to None if refusal (nullable) is None + # and model_fields_set contains the field + if self.refusal is None and "refusal" in self.model_fields_set: + _dict['refusal'] = None + + # set to None if role (nullable) is None + # and model_fields_set contains the field + if self.role is None and "role" in self.model_fields_set: + _dict['role'] = None + + # set to None if tool_calls (nullable) is None + # and model_fields_set contains the field + if self.tool_calls is None and "tool_calls" in self.model_fields_set: + _dict['tool_calls'] = None + + # set to None if reasoning (nullable) is None + # and model_fields_set contains the field + if self.reasoning is None and "reasoning" in self.model_fields_set: + _dict['reasoning'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChoiceDelta from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content"), + "function_call": CCKChoiceDeltaFunctionCall.from_dict(obj["function_call"]) if obj.get("function_call") is not None else None, + "refusal": obj.get("refusal"), + "role": obj.get("role"), + "tool_calls": [CCKChoiceDeltaToolCall.from_dict(_item) for _item in obj["tool_calls"]] if obj.get("tool_calls") is not None else None, + "reasoning": CCKReasoning.from_dict(obj["reasoning"]) if obj.get("reasoning") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_choice_delta_function_call.py b/src/otari/_client/models/cck_choice_delta_function_call.py new file mode 100644 index 0000000..b2e0862 --- /dev/null +++ b/src/otari/_client/models/cck_choice_delta_function_call.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChoiceDeltaFunctionCall(BaseModel): + """ + Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + """ # noqa: E501 + arguments: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + name: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaFunctionCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if arguments (nullable) is None + # and model_fields_set contains the field + if self.arguments is None and "arguments" in self.model_fields_set: + _dict['arguments'] = None + + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaFunctionCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_choice_delta_tool_call.py b/src/otari/_client/models/cck_choice_delta_tool_call.py new file mode 100644 index 0000000..cf7e4e9 --- /dev/null +++ b/src/otari/_client/models/cck_choice_delta_tool_call.py @@ -0,0 +1,136 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_choice_delta_tool_call_function import CCKChoiceDeltaToolCallFunction +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChoiceDeltaToolCall(BaseModel): + """ + CCKChoiceDeltaToolCall + """ # noqa: E501 + index: StrictInt + id: Optional[StrictStr] = None + function: Optional[CCKChoiceDeltaToolCallFunction] = None + type: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["index", "id", "function", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['function']): + raise ValueError("must be one of enum values ('function')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaToolCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of function + if self.function: + _dict['function'] = self.function.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if id (nullable) is None + # and model_fields_set contains the field + if self.id is None and "id" in self.model_fields_set: + _dict['id'] = None + + # set to None if function (nullable) is None + # and model_fields_set contains the field + if self.function is None and "function" in self.model_fields_set: + _dict['function'] = None + + # set to None if type (nullable) is None + # and model_fields_set contains the field + if self.type is None and "type" in self.model_fields_set: + _dict['type'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaToolCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "index": obj.get("index"), + "id": obj.get("id"), + "function": CCKChoiceDeltaToolCallFunction.from_dict(obj["function"]) if obj.get("function") is not None else None, + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_choice_delta_tool_call_function.py b/src/otari/_client/models/cck_choice_delta_tool_call_function.py new file mode 100644 index 0000000..6af39e7 --- /dev/null +++ b/src/otari/_client/models/cck_choice_delta_tool_call_function.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChoiceDeltaToolCallFunction(BaseModel): + """ + CCKChoiceDeltaToolCallFunction + """ # noqa: E501 + arguments: Optional[StrictStr] = None + name: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaToolCallFunction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if arguments (nullable) is None + # and model_fields_set contains the field + if self.arguments is None and "arguments" in self.model_fields_set: + _dict['arguments'] = None + + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChoiceDeltaToolCallFunction from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_choice_logprobs.py b/src/otari/_client/models/cck_choice_logprobs.py new file mode 100644 index 0000000..14832de --- /dev/null +++ b/src/otari/_client/models/cck_choice_logprobs.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_chat_completion_token_logprob import CCKChatCompletionTokenLogprob +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChoiceLogprobs(BaseModel): + """ + Log probability information for the choice. + """ # noqa: E501 + content: Optional[List[CCKChatCompletionTokenLogprob]] = None + refusal: Optional[List[CCKChatCompletionTokenLogprob]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "refusal"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChoiceLogprobs from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in refusal (list) + _items = [] + if self.refusal: + for _item_refusal in self.refusal: + if _item_refusal: + _items.append(_item_refusal.to_dict()) + _dict['refusal'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + # set to None if refusal (nullable) is None + # and model_fields_set contains the field + if self.refusal is None and "refusal" in self.model_fields_set: + _dict['refusal'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChoiceLogprobs from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": [CCKChatCompletionTokenLogprob.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "refusal": [CCKChatCompletionTokenLogprob.from_dict(_item) for _item in obj["refusal"]] if obj.get("refusal") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_chunk_choice.py b/src/otari/_client/models/cck_chunk_choice.py new file mode 100644 index 0000000..167c5ca --- /dev/null +++ b/src/otari/_client/models/cck_chunk_choice.py @@ -0,0 +1,135 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_choice_delta import CCKChoiceDelta +from otari._client.models.cck_choice_logprobs import CCKChoiceLogprobs +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKChunkChoice(BaseModel): + """ + CCKChunkChoice + """ # noqa: E501 + delta: CCKChoiceDelta + finish_reason: Optional[StrictStr] = None + index: StrictInt + logprobs: Optional[CCKChoiceLogprobs] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["delta", "finish_reason", "index", "logprobs"] + + @field_validator('finish_reason') + def finish_reason_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['stop', 'length', 'tool_calls', 'content_filter', 'function_call']): + raise ValueError("must be one of enum values ('stop', 'length', 'tool_calls', 'content_filter', 'function_call')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKChunkChoice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of delta + if self.delta: + _dict['delta'] = self.delta.to_dict() + # override the default output from pydantic by calling `to_dict()` of logprobs + if self.logprobs: + _dict['logprobs'] = self.logprobs.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if finish_reason (nullable) is None + # and model_fields_set contains the field + if self.finish_reason is None and "finish_reason" in self.model_fields_set: + _dict['finish_reason'] = None + + # set to None if logprobs (nullable) is None + # and model_fields_set contains the field + if self.logprobs is None and "logprobs" in self.model_fields_set: + _dict['logprobs'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKChunkChoice from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "delta": CCKChoiceDelta.from_dict(obj["delta"]) if obj.get("delta") is not None else None, + "finish_reason": obj.get("finish_reason"), + "index": obj.get("index"), + "logprobs": CCKChoiceLogprobs.from_dict(obj["logprobs"]) if obj.get("logprobs") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_completion_tokens_details.py b/src/otari/_client/models/cck_completion_tokens_details.py new file mode 100644 index 0000000..32073f9 --- /dev/null +++ b/src/otari/_client/models/cck_completion_tokens_details.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKCompletionTokensDetails(BaseModel): + """ + Breakdown of tokens used in a completion. + """ # noqa: E501 + accepted_prediction_tokens: Optional[StrictInt] = None + audio_tokens: Optional[StrictInt] = None + reasoning_tokens: Optional[StrictInt] = None + rejected_prediction_tokens: Optional[StrictInt] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["accepted_prediction_tokens", "audio_tokens", "reasoning_tokens", "rejected_prediction_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKCompletionTokensDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if accepted_prediction_tokens (nullable) is None + # and model_fields_set contains the field + if self.accepted_prediction_tokens is None and "accepted_prediction_tokens" in self.model_fields_set: + _dict['accepted_prediction_tokens'] = None + + # set to None if audio_tokens (nullable) is None + # and model_fields_set contains the field + if self.audio_tokens is None and "audio_tokens" in self.model_fields_set: + _dict['audio_tokens'] = None + + # set to None if reasoning_tokens (nullable) is None + # and model_fields_set contains the field + if self.reasoning_tokens is None and "reasoning_tokens" in self.model_fields_set: + _dict['reasoning_tokens'] = None + + # set to None if rejected_prediction_tokens (nullable) is None + # and model_fields_set contains the field + if self.rejected_prediction_tokens is None and "rejected_prediction_tokens" in self.model_fields_set: + _dict['rejected_prediction_tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKCompletionTokensDetails from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "accepted_prediction_tokens": obj.get("accepted_prediction_tokens"), + "audio_tokens": obj.get("audio_tokens"), + "reasoning_tokens": obj.get("reasoning_tokens"), + "rejected_prediction_tokens": obj.get("rejected_prediction_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_completion_usage.py b/src/otari/_client/models/cck_completion_usage.py new file mode 100644 index 0000000..a04ee69 --- /dev/null +++ b/src/otari/_client/models/cck_completion_usage.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_completion_tokens_details import CCKCompletionTokensDetails +from otari._client.models.cck_prompt_tokens_details import CCKPromptTokensDetails +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKCompletionUsage(BaseModel): + """ + Usage statistics for the completion request. + """ # noqa: E501 + completion_tokens: StrictInt + prompt_tokens: StrictInt + total_tokens: StrictInt + completion_tokens_details: Optional[CCKCompletionTokensDetails] = None + prompt_tokens_details: Optional[CCKPromptTokensDetails] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["completion_tokens", "prompt_tokens", "total_tokens", "completion_tokens_details", "prompt_tokens_details"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKCompletionUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of completion_tokens_details + if self.completion_tokens_details: + _dict['completion_tokens_details'] = self.completion_tokens_details.to_dict() + # override the default output from pydantic by calling `to_dict()` of prompt_tokens_details + if self.prompt_tokens_details: + _dict['prompt_tokens_details'] = self.prompt_tokens_details.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if completion_tokens_details (nullable) is None + # and model_fields_set contains the field + if self.completion_tokens_details is None and "completion_tokens_details" in self.model_fields_set: + _dict['completion_tokens_details'] = None + + # set to None if prompt_tokens_details (nullable) is None + # and model_fields_set contains the field + if self.prompt_tokens_details is None and "prompt_tokens_details" in self.model_fields_set: + _dict['prompt_tokens_details'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKCompletionUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "completion_tokens": obj.get("completion_tokens"), + "prompt_tokens": obj.get("prompt_tokens"), + "total_tokens": obj.get("total_tokens"), + "completion_tokens_details": CCKCompletionTokensDetails.from_dict(obj["completion_tokens_details"]) if obj.get("completion_tokens_details") is not None else None, + "prompt_tokens_details": CCKPromptTokensDetails.from_dict(obj["prompt_tokens_details"]) if obj.get("prompt_tokens_details") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_prompt_tokens_details.py b/src/otari/_client/models/cck_prompt_tokens_details.py new file mode 100644 index 0000000..9630316 --- /dev/null +++ b/src/otari/_client/models/cck_prompt_tokens_details.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKPromptTokensDetails(BaseModel): + """ + Breakdown of tokens used in the prompt. + """ # noqa: E501 + audio_tokens: Optional[StrictInt] = None + cached_tokens: Optional[StrictInt] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["audio_tokens", "cached_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKPromptTokensDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if audio_tokens (nullable) is None + # and model_fields_set contains the field + if self.audio_tokens is None and "audio_tokens" in self.model_fields_set: + _dict['audio_tokens'] = None + + # set to None if cached_tokens (nullable) is None + # and model_fields_set contains the field + if self.cached_tokens is None and "cached_tokens" in self.model_fields_set: + _dict['cached_tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKPromptTokensDetails from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "audio_tokens": obj.get("audio_tokens"), + "cached_tokens": obj.get("cached_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/cck_reasoning.py b/src/otari/_client/models/cck_reasoning.py new file mode 100644 index 0000000..d58cae3 --- /dev/null +++ b/src/otari/_client/models/cck_reasoning.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKReasoning(BaseModel): + """ + Reasoning content emitted by a model. Serializes as a plain JSON string so that responses are compatible with OpenAI-style clients that expect ``delta.reasoning`` / ``message.reasoning`` to be a string. The Python attribute ``content`` remains available for typed access (e.g. ``message.reasoning.content``). + """ # noqa: E501 + content: StrictStr + __properties: ClassVar[List[str]] = ["content"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKReasoning from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKReasoning from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content") + }) + return _obj + + diff --git a/src/otari/_client/models/cck_top_logprob.py b/src/otari/_client/models/cck_top_logprob.py new file mode 100644 index 0000000..b8173e6 --- /dev/null +++ b/src/otari/_client/models/cck_top_logprob.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CCKTopLogprob(BaseModel): + """ + CCKTopLogprob + """ # noqa: E501 + token: StrictStr + bytes: Optional[List[StrictInt]] = None + logprob: Union[StrictFloat, StrictInt] + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["token", "bytes", "logprob"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CCKTopLogprob from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if bytes (nullable) is None + # and model_fields_set contains the field + if self.bytes is None and "bytes" in self.model_fields_set: + _dict['bytes'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CCKTopLogprob from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "token": obj.get("token"), + "bytes": obj.get("bytes"), + "logprob": obj.get("logprob") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/chat_completion.py b/src/otari/_client/models/chat_completion.py new file mode 100644 index 0000000..5e33613 --- /dev/null +++ b/src/otari/_client/models/chat_completion.py @@ -0,0 +1,149 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cc_choice import CCChoice +from otari._client.models.cc_completion_usage import CCCompletionUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ChatCompletion(BaseModel): + """ + ChatCompletion + """ # noqa: E501 + id: StrictStr + choices: List[CCChoice] + created: StrictInt + model: StrictStr + object: StrictStr + service_tier: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + system_fingerprint: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + usage: Optional[CCCompletionUsage] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "choices", "created", "model", "object", "service_tier", "system_fingerprint", "usage"] + + @field_validator('object') + def object_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['chat.completion']): + raise ValueError("must be one of enum values ('chat.completion')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChatCompletion from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in choices (list) + _items = [] + if self.choices: + for _item_choices in self.choices: + if _item_choices: + _items.append(_item_choices.to_dict()) + _dict['choices'] = _items + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if service_tier (nullable) is None + # and model_fields_set contains the field + if self.service_tier is None and "service_tier" in self.model_fields_set: + _dict['service_tier'] = None + + # set to None if system_fingerprint (nullable) is None + # and model_fields_set contains the field + if self.system_fingerprint is None and "system_fingerprint" in self.model_fields_set: + _dict['system_fingerprint'] = None + + # set to None if usage (nullable) is None + # and model_fields_set contains the field + if self.usage is None and "usage" in self.model_fields_set: + _dict['usage'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChatCompletion from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "choices": [CCChoice.from_dict(_item) for _item in obj["choices"]] if obj.get("choices") is not None else None, + "created": obj.get("created"), + "model": obj.get("model"), + "object": obj.get("object"), + "service_tier": obj.get("service_tier"), + "system_fingerprint": obj.get("system_fingerprint"), + "usage": CCCompletionUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/chat_completion_chunk.py b/src/otari/_client/models/chat_completion_chunk.py new file mode 100644 index 0000000..3b6e819 --- /dev/null +++ b/src/otari/_client/models/chat_completion_chunk.py @@ -0,0 +1,149 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.cck_chunk_choice import CCKChunkChoice +from otari._client.models.cck_completion_usage import CCKCompletionUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ChatCompletionChunk(BaseModel): + """ + ChatCompletionChunk + """ # noqa: E501 + id: StrictStr + choices: List[CCKChunkChoice] + created: StrictInt + model: StrictStr + object: StrictStr + service_tier: Optional[StrictStr] = None + system_fingerprint: Optional[StrictStr] = None + usage: Optional[CCKCompletionUsage] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "choices", "created", "model", "object", "service_tier", "system_fingerprint", "usage"] + + @field_validator('object') + def object_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['chat.completion.chunk']): + raise ValueError("must be one of enum values ('chat.completion.chunk')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChatCompletionChunk from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in choices (list) + _items = [] + if self.choices: + for _item_choices in self.choices: + if _item_choices: + _items.append(_item_choices.to_dict()) + _dict['choices'] = _items + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if service_tier (nullable) is None + # and model_fields_set contains the field + if self.service_tier is None and "service_tier" in self.model_fields_set: + _dict['service_tier'] = None + + # set to None if system_fingerprint (nullable) is None + # and model_fields_set contains the field + if self.system_fingerprint is None and "system_fingerprint" in self.model_fields_set: + _dict['system_fingerprint'] = None + + # set to None if usage (nullable) is None + # and model_fields_set contains the field + if self.usage is None and "usage" in self.model_fields_set: + _dict['usage'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChatCompletionChunk from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "choices": [CCKChunkChoice.from_dict(_item) for _item in obj["choices"]] if obj.get("choices") is not None else None, + "created": obj.get("created"), + "model": obj.get("model"), + "object": obj.get("object"), + "service_tier": obj.get("service_tier"), + "system_fingerprint": obj.get("system_fingerprint"), + "usage": CCKCompletionUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/chat_completion_request.py b/src/otari/_client/models/chat_completion_request.py new file mode 100644 index 0000000..80c0bdf --- /dev/null +++ b/src/otari/_client/models/chat_completion_request.py @@ -0,0 +1,220 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from uuid import UUID +from otari._client.models.chat_message_input import ChatMessageInput +from otari._client.models.guardrail_config import GuardrailConfig +from otari._client.models.mcp_server_config import McpServerConfig +from otari._client.models.tool_choice import ToolChoice +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ChatCompletionRequest(BaseModel): + """ + OpenAI-compatible chat completion request. + """ # noqa: E501 + guardrails: Optional[Annotated[List[GuardrailConfig], Field(max_length=8)]] = None + max_completion_tokens: Optional[StrictInt] = None + max_tokens: Optional[StrictInt] = None + max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None + mcp_server_ids: Optional[List[UUID]] = None + mcp_servers: Optional[List[McpServerConfig]] = None + messages: Annotated[List[ChatMessageInput], Field(min_length=1)] + model: StrictStr + response_format: Optional[Dict[str, Any]] = None + stream: Optional[StrictBool] = False + stream_options: Optional[Dict[str, Any]] = None + temperature: Optional[Union[StrictFloat, StrictInt]] = None + tool_choice: Optional[ToolChoice] = None + tools: Optional[List[Optional[Dict[str, Any]]]] = None + tools_header: Optional[Annotated[str, Field(strict=True, max_length=4000)]] = Field(default=None, description="Optional override for the lead-in that the gateway prepends before the per-tool hint block in the system message. Useful for expressing global tool-selection policy (e.g. 'prefer MCP tools over code_execution'). Falls back to GATEWAY_TOOLS_HEADER env, then to the built-in default.") + top_p: Optional[Union[StrictFloat, StrictInt]] = None + user: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["guardrails", "max_completion_tokens", "max_tokens", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "messages", "model", "response_format", "stream", "stream_options", "temperature", "tool_choice", "tools", "tools_header", "top_p", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChatCompletionRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in guardrails (list) + _items = [] + if self.guardrails: + for _item_guardrails in self.guardrails: + if _item_guardrails: + _items.append(_item_guardrails.to_dict()) + _dict['guardrails'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in mcp_servers (list) + _items = [] + if self.mcp_servers: + for _item_mcp_servers in self.mcp_servers: + if _item_mcp_servers: + _items.append(_item_mcp_servers.to_dict()) + _dict['mcp_servers'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item_messages in self.messages: + if _item_messages: + _items.append(_item_messages.to_dict()) + _dict['messages'] = _items + # override the default output from pydantic by calling `to_dict()` of tool_choice + if self.tool_choice: + _dict['tool_choice'] = self.tool_choice.to_dict() + # set to None if guardrails (nullable) is None + # and model_fields_set contains the field + if self.guardrails is None and "guardrails" in self.model_fields_set: + _dict['guardrails'] = None + + # set to None if max_completion_tokens (nullable) is None + # and model_fields_set contains the field + if self.max_completion_tokens is None and "max_completion_tokens" in self.model_fields_set: + _dict['max_completion_tokens'] = None + + # set to None if max_tokens (nullable) is None + # and model_fields_set contains the field + if self.max_tokens is None and "max_tokens" in self.model_fields_set: + _dict['max_tokens'] = None + + # set to None if max_tool_iterations (nullable) is None + # and model_fields_set contains the field + if self.max_tool_iterations is None and "max_tool_iterations" in self.model_fields_set: + _dict['max_tool_iterations'] = None + + # set to None if mcp_server_ids (nullable) is None + # and model_fields_set contains the field + if self.mcp_server_ids is None and "mcp_server_ids" in self.model_fields_set: + _dict['mcp_server_ids'] = None + + # set to None if mcp_servers (nullable) is None + # and model_fields_set contains the field + if self.mcp_servers is None and "mcp_servers" in self.model_fields_set: + _dict['mcp_servers'] = None + + # set to None if response_format (nullable) is None + # and model_fields_set contains the field + if self.response_format is None and "response_format" in self.model_fields_set: + _dict['response_format'] = None + + # set to None if stream_options (nullable) is None + # and model_fields_set contains the field + if self.stream_options is None and "stream_options" in self.model_fields_set: + _dict['stream_options'] = None + + # set to None if temperature (nullable) is None + # and model_fields_set contains the field + if self.temperature is None and "temperature" in self.model_fields_set: + _dict['temperature'] = None + + # set to None if tool_choice (nullable) is None + # and model_fields_set contains the field + if self.tool_choice is None and "tool_choice" in self.model_fields_set: + _dict['tool_choice'] = None + + # set to None if tools (nullable) is None + # and model_fields_set contains the field + if self.tools is None and "tools" in self.model_fields_set: + _dict['tools'] = None + + # set to None if tools_header (nullable) is None + # and model_fields_set contains the field + if self.tools_header is None and "tools_header" in self.model_fields_set: + _dict['tools_header'] = None + + # set to None if top_p (nullable) is None + # and model_fields_set contains the field + if self.top_p is None and "top_p" in self.model_fields_set: + _dict['top_p'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChatCompletionRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "guardrails": [GuardrailConfig.from_dict(_item) for _item in obj["guardrails"]] if obj.get("guardrails") is not None else None, + "max_completion_tokens": obj.get("max_completion_tokens"), + "max_tokens": obj.get("max_tokens"), + "max_tool_iterations": obj.get("max_tool_iterations"), + "mcp_server_ids": obj.get("mcp_server_ids"), + "mcp_servers": [McpServerConfig.from_dict(_item) for _item in obj["mcp_servers"]] if obj.get("mcp_servers") is not None else None, + "messages": [ChatMessageInput.from_dict(_item) for _item in obj["messages"]] if obj.get("messages") is not None else None, + "model": obj.get("model"), + "response_format": obj.get("response_format"), + "stream": obj.get("stream") if obj.get("stream") is not None else False, + "stream_options": obj.get("stream_options"), + "temperature": obj.get("temperature"), + "tool_choice": ToolChoice.from_dict(obj["tool_choice"]) if obj.get("tool_choice") is not None else None, + "tools": obj.get("tools"), + "tools_header": obj.get("tools_header"), + "top_p": obj.get("top_p"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/chat_message_input.py b/src/otari/_client/models/chat_message_input.py new file mode 100644 index 0000000..0c59fce --- /dev/null +++ b/src/otari/_client/models/chat_message_input.py @@ -0,0 +1,194 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.msg_chat_completion_assistant_message_param import MSGChatCompletionAssistantMessageParam +from otari._client.models.msg_chat_completion_developer_message_param import MSGChatCompletionDeveloperMessageParam +from otari._client.models.msg_chat_completion_function_message_param import MSGChatCompletionFunctionMessageParam +from otari._client.models.msg_chat_completion_system_message_param import MSGChatCompletionSystemMessageParam +from otari._client.models.msg_chat_completion_tool_message_param import MSGChatCompletionToolMessageParam +from otari._client.models.msg_chat_completion_user_message_param import MSGChatCompletionUserMessageParam +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CHATMESSAGEINPUT_ANY_OF_SCHEMAS = ["MSGChatCompletionAssistantMessageParam", "MSGChatCompletionDeveloperMessageParam", "MSGChatCompletionFunctionMessageParam", "MSGChatCompletionSystemMessageParam", "MSGChatCompletionToolMessageParam", "MSGChatCompletionUserMessageParam"] + +class ChatMessageInput(BaseModel): + """ + ChatMessageInput + """ + + # data type: MSGChatCompletionDeveloperMessageParam + anyof_schema_1_validator: Optional[MSGChatCompletionDeveloperMessageParam] = None + # data type: MSGChatCompletionSystemMessageParam + anyof_schema_2_validator: Optional[MSGChatCompletionSystemMessageParam] = None + # data type: MSGChatCompletionUserMessageParam + anyof_schema_3_validator: Optional[MSGChatCompletionUserMessageParam] = None + # data type: MSGChatCompletionAssistantMessageParam + anyof_schema_4_validator: Optional[MSGChatCompletionAssistantMessageParam] = None + # data type: MSGChatCompletionToolMessageParam + anyof_schema_5_validator: Optional[MSGChatCompletionToolMessageParam] = None + # data type: MSGChatCompletionFunctionMessageParam + anyof_schema_6_validator: Optional[MSGChatCompletionFunctionMessageParam] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MSGChatCompletionAssistantMessageParam, MSGChatCompletionDeveloperMessageParam, MSGChatCompletionFunctionMessageParam, MSGChatCompletionSystemMessageParam, MSGChatCompletionToolMessageParam, MSGChatCompletionUserMessageParam]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MSGChatCompletionAssistantMessageParam", "MSGChatCompletionDeveloperMessageParam", "MSGChatCompletionFunctionMessageParam", "MSGChatCompletionSystemMessageParam", "MSGChatCompletionToolMessageParam", "MSGChatCompletionUserMessageParam" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = ChatMessageInput.model_construct() + error_messages = [] + # validate data type: MSGChatCompletionDeveloperMessageParam + if not isinstance(v, MSGChatCompletionDeveloperMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionDeveloperMessageParam`") + else: + return v + + # validate data type: MSGChatCompletionSystemMessageParam + if not isinstance(v, MSGChatCompletionSystemMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionSystemMessageParam`") + else: + return v + + # validate data type: MSGChatCompletionUserMessageParam + if not isinstance(v, MSGChatCompletionUserMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionUserMessageParam`") + else: + return v + + # validate data type: MSGChatCompletionAssistantMessageParam + if not isinstance(v, MSGChatCompletionAssistantMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionAssistantMessageParam`") + else: + return v + + # validate data type: MSGChatCompletionToolMessageParam + if not isinstance(v, MSGChatCompletionToolMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionToolMessageParam`") + else: + return v + + # validate data type: MSGChatCompletionFunctionMessageParam + if not isinstance(v, MSGChatCompletionFunctionMessageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionFunctionMessageParam`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in ChatMessageInput with anyOf schemas: MSGChatCompletionAssistantMessageParam, MSGChatCompletionDeveloperMessageParam, MSGChatCompletionFunctionMessageParam, MSGChatCompletionSystemMessageParam, MSGChatCompletionToolMessageParam, MSGChatCompletionUserMessageParam. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MSGChatCompletionDeveloperMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionDeveloperMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MSGChatCompletionSystemMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionSystemMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MSGChatCompletionUserMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionUserMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MSGChatCompletionAssistantMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionAssistantMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_5_validator: Optional[MSGChatCompletionToolMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionToolMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_6_validator: Optional[MSGChatCompletionFunctionMessageParam] = None + try: + instance.actual_instance = MSGChatCompletionFunctionMessageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into ChatMessageInput with anyOf schemas: MSGChatCompletionAssistantMessageParam, MSGChatCompletionDeveloperMessageParam, MSGChatCompletionFunctionMessageParam, MSGChatCompletionSystemMessageParam, MSGChatCompletionToolMessageParam, MSGChatCompletionUserMessageParam. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MSGChatCompletionAssistantMessageParam, MSGChatCompletionDeveloperMessageParam, MSGChatCompletionFunctionMessageParam, MSGChatCompletionSystemMessageParam, MSGChatCompletionToolMessageParam, MSGChatCompletionUserMessageParam]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content.py b/src/otari/_client/models/content.py new file mode 100644 index 0000000..b03a3aa --- /dev/null +++ b/src/otari/_client/models/content.py @@ -0,0 +1,145 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import List, Optional +from otari._client.models.content_any_of_inner import ContentAnyOfInner +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT_ANY_OF_SCHEMAS = ["List[ContentAnyOfInner]", "str"] + +class Content(BaseModel): + """ + Content + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: List[ContentAnyOfInner] + anyof_schema_2_validator: Optional[List[ContentAnyOfInner]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[ContentAnyOfInner], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[ContentAnyOfInner]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = Content.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[ContentAnyOfInner] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content with anyOf schemas: List[ContentAnyOfInner], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[ContentAnyOfInner] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content with anyOf schemas: List[ContentAnyOfInner], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[ContentAnyOfInner], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content1.py b/src/otari/_client/models/content1.py new file mode 100644 index 0000000..2bd24ef --- /dev/null +++ b/src/otari/_client/models/content1.py @@ -0,0 +1,139 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import List, Optional +from otari._client.models.msg_chat_completion_content_part_text_param import MSGChatCompletionContentPartTextParam +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT1_ANY_OF_SCHEMAS = ["List[MSGChatCompletionContentPartTextParam]", "str"] + +class Content1(BaseModel): + """ + Content1 + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: List[MSGChatCompletionContentPartTextParam] + anyof_schema_2_validator: Optional[List[MSGChatCompletionContentPartTextParam]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[MSGChatCompletionContentPartTextParam], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[MSGChatCompletionContentPartTextParam]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content1.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[MSGChatCompletionContentPartTextParam] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content1 with anyOf schemas: List[MSGChatCompletionContentPartTextParam], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[MSGChatCompletionContentPartTextParam] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content1 with anyOf schemas: List[MSGChatCompletionContentPartTextParam], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[MSGChatCompletionContentPartTextParam], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content2.py b/src/otari/_client/models/content2.py new file mode 100644 index 0000000..b56eebf --- /dev/null +++ b/src/otari/_client/models/content2.py @@ -0,0 +1,139 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import List, Optional +from otari._client.models.content2_any_of_inner import Content2AnyOfInner +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT2_ANY_OF_SCHEMAS = ["List[Content2AnyOfInner]", "str"] + +class Content2(BaseModel): + """ + Content2 + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: List[Content2AnyOfInner] + anyof_schema_2_validator: Optional[List[Content2AnyOfInner]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[Content2AnyOfInner], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[Content2AnyOfInner]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content2.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[Content2AnyOfInner] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content2 with anyOf schemas: List[Content2AnyOfInner], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[Content2AnyOfInner] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content2 with anyOf schemas: List[Content2AnyOfInner], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[Content2AnyOfInner], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content2_any_of_inner.py b/src/otari/_client/models/content2_any_of_inner.py new file mode 100644 index 0000000..40320a0 --- /dev/null +++ b/src/otari/_client/models/content2_any_of_inner.py @@ -0,0 +1,164 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.msg_chat_completion_content_part_image_param import MSGChatCompletionContentPartImageParam +from otari._client.models.msg_chat_completion_content_part_input_audio_param import MSGChatCompletionContentPartInputAudioParam +from otari._client.models.msg_chat_completion_content_part_text_param import MSGChatCompletionContentPartTextParam +from otari._client.models.msg_file import MSGFile +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT2ANYOFINNER_ANY_OF_SCHEMAS = ["MSGChatCompletionContentPartImageParam", "MSGChatCompletionContentPartInputAudioParam", "MSGChatCompletionContentPartTextParam", "MSGFile"] + +class Content2AnyOfInner(BaseModel): + """ + Content2AnyOfInner + """ + + # data type: MSGChatCompletionContentPartTextParam + anyof_schema_1_validator: Optional[MSGChatCompletionContentPartTextParam] = None + # data type: MSGChatCompletionContentPartImageParam + anyof_schema_2_validator: Optional[MSGChatCompletionContentPartImageParam] = None + # data type: MSGChatCompletionContentPartInputAudioParam + anyof_schema_3_validator: Optional[MSGChatCompletionContentPartInputAudioParam] = None + # data type: MSGFile + anyof_schema_4_validator: Optional[MSGFile] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MSGChatCompletionContentPartImageParam, MSGChatCompletionContentPartInputAudioParam, MSGChatCompletionContentPartTextParam, MSGFile]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MSGChatCompletionContentPartImageParam", "MSGChatCompletionContentPartInputAudioParam", "MSGChatCompletionContentPartTextParam", "MSGFile" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content2AnyOfInner.model_construct() + error_messages = [] + # validate data type: MSGChatCompletionContentPartTextParam + if not isinstance(v, MSGChatCompletionContentPartTextParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionContentPartTextParam`") + else: + return v + + # validate data type: MSGChatCompletionContentPartImageParam + if not isinstance(v, MSGChatCompletionContentPartImageParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionContentPartImageParam`") + else: + return v + + # validate data type: MSGChatCompletionContentPartInputAudioParam + if not isinstance(v, MSGChatCompletionContentPartInputAudioParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionContentPartInputAudioParam`") + else: + return v + + # validate data type: MSGFile + if not isinstance(v, MSGFile): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGFile`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content2AnyOfInner with anyOf schemas: MSGChatCompletionContentPartImageParam, MSGChatCompletionContentPartInputAudioParam, MSGChatCompletionContentPartTextParam, MSGFile. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MSGChatCompletionContentPartTextParam] = None + try: + instance.actual_instance = MSGChatCompletionContentPartTextParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MSGChatCompletionContentPartImageParam] = None + try: + instance.actual_instance = MSGChatCompletionContentPartImageParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MSGChatCompletionContentPartInputAudioParam] = None + try: + instance.actual_instance = MSGChatCompletionContentPartInputAudioParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MSGFile] = None + try: + instance.actual_instance = MSGFile.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content2AnyOfInner with anyOf schemas: MSGChatCompletionContentPartImageParam, MSGChatCompletionContentPartInputAudioParam, MSGChatCompletionContentPartTextParam, MSGFile. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MSGChatCompletionContentPartImageParam, MSGChatCompletionContentPartInputAudioParam, MSGChatCompletionContentPartTextParam, MSGFile]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content3.py b/src/otari/_client/models/content3.py new file mode 100644 index 0000000..c684bbe --- /dev/null +++ b/src/otari/_client/models/content3.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_bash_code_execution_result_block import MRBashCodeExecutionResultBlock +from otari._client.models.mr_bash_code_execution_tool_result_error import MRBashCodeExecutionToolResultError +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT3_ANY_OF_SCHEMAS = ["MRBashCodeExecutionResultBlock", "MRBashCodeExecutionToolResultError"] + +class Content3(BaseModel): + """ + Content3 + """ + + # data type: MRBashCodeExecutionToolResultError + anyof_schema_1_validator: Optional[MRBashCodeExecutionToolResultError] = None + # data type: MRBashCodeExecutionResultBlock + anyof_schema_2_validator: Optional[MRBashCodeExecutionResultBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRBashCodeExecutionResultBlock, MRBashCodeExecutionToolResultError]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRBashCodeExecutionResultBlock", "MRBashCodeExecutionToolResultError" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content3.model_construct() + error_messages = [] + # validate data type: MRBashCodeExecutionToolResultError + if not isinstance(v, MRBashCodeExecutionToolResultError): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRBashCodeExecutionToolResultError`") + else: + return v + + # validate data type: MRBashCodeExecutionResultBlock + if not isinstance(v, MRBashCodeExecutionResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRBashCodeExecutionResultBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content3 with anyOf schemas: MRBashCodeExecutionResultBlock, MRBashCodeExecutionToolResultError. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRBashCodeExecutionToolResultError] = None + try: + instance.actual_instance = MRBashCodeExecutionToolResultError.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRBashCodeExecutionResultBlock] = None + try: + instance.actual_instance = MRBashCodeExecutionResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content3 with anyOf schemas: MRBashCodeExecutionResultBlock, MRBashCodeExecutionToolResultError. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRBashCodeExecutionResultBlock, MRBashCodeExecutionToolResultError]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content4.py b/src/otari/_client/models/content4.py new file mode 100644 index 0000000..e1b3b2f --- /dev/null +++ b/src/otari/_client/models/content4.py @@ -0,0 +1,149 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_code_execution_result_block import MRCodeExecutionResultBlock +from otari._client.models.mr_code_execution_tool_result_error import MRCodeExecutionToolResultError +from otari._client.models.mr_encrypted_code_execution_result_block import MREncryptedCodeExecutionResultBlock +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT4_ANY_OF_SCHEMAS = ["MRCodeExecutionResultBlock", "MRCodeExecutionToolResultError", "MREncryptedCodeExecutionResultBlock"] + +class Content4(BaseModel): + """ + Content4 + """ + + # data type: MRCodeExecutionToolResultError + anyof_schema_1_validator: Optional[MRCodeExecutionToolResultError] = None + # data type: MRCodeExecutionResultBlock + anyof_schema_2_validator: Optional[MRCodeExecutionResultBlock] = None + # data type: MREncryptedCodeExecutionResultBlock + anyof_schema_3_validator: Optional[MREncryptedCodeExecutionResultBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRCodeExecutionResultBlock, MRCodeExecutionToolResultError, MREncryptedCodeExecutionResultBlock]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRCodeExecutionResultBlock", "MRCodeExecutionToolResultError", "MREncryptedCodeExecutionResultBlock" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content4.model_construct() + error_messages = [] + # validate data type: MRCodeExecutionToolResultError + if not isinstance(v, MRCodeExecutionToolResultError): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCodeExecutionToolResultError`") + else: + return v + + # validate data type: MRCodeExecutionResultBlock + if not isinstance(v, MRCodeExecutionResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCodeExecutionResultBlock`") + else: + return v + + # validate data type: MREncryptedCodeExecutionResultBlock + if not isinstance(v, MREncryptedCodeExecutionResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MREncryptedCodeExecutionResultBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content4 with anyOf schemas: MRCodeExecutionResultBlock, MRCodeExecutionToolResultError, MREncryptedCodeExecutionResultBlock. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRCodeExecutionToolResultError] = None + try: + instance.actual_instance = MRCodeExecutionToolResultError.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRCodeExecutionResultBlock] = None + try: + instance.actual_instance = MRCodeExecutionResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MREncryptedCodeExecutionResultBlock] = None + try: + instance.actual_instance = MREncryptedCodeExecutionResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content4 with anyOf schemas: MRCodeExecutionResultBlock, MRCodeExecutionToolResultError, MREncryptedCodeExecutionResultBlock. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRCodeExecutionResultBlock, MRCodeExecutionToolResultError, MREncryptedCodeExecutionResultBlock]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content5.py b/src/otari/_client/models/content5.py new file mode 100644 index 0000000..7139a32 --- /dev/null +++ b/src/otari/_client/models/content5.py @@ -0,0 +1,164 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_text_editor_code_execution_create_result_block import MRTextEditorCodeExecutionCreateResultBlock +from otari._client.models.mr_text_editor_code_execution_str_replace_result_block import MRTextEditorCodeExecutionStrReplaceResultBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_error import MRTextEditorCodeExecutionToolResultError +from otari._client.models.mr_text_editor_code_execution_view_result_block import MRTextEditorCodeExecutionViewResultBlock +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT5_ANY_OF_SCHEMAS = ["MRTextEditorCodeExecutionCreateResultBlock", "MRTextEditorCodeExecutionStrReplaceResultBlock", "MRTextEditorCodeExecutionToolResultError", "MRTextEditorCodeExecutionViewResultBlock"] + +class Content5(BaseModel): + """ + Content5 + """ + + # data type: MRTextEditorCodeExecutionToolResultError + anyof_schema_1_validator: Optional[MRTextEditorCodeExecutionToolResultError] = None + # data type: MRTextEditorCodeExecutionViewResultBlock + anyof_schema_2_validator: Optional[MRTextEditorCodeExecutionViewResultBlock] = None + # data type: MRTextEditorCodeExecutionCreateResultBlock + anyof_schema_3_validator: Optional[MRTextEditorCodeExecutionCreateResultBlock] = None + # data type: MRTextEditorCodeExecutionStrReplaceResultBlock + anyof_schema_4_validator: Optional[MRTextEditorCodeExecutionStrReplaceResultBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRTextEditorCodeExecutionCreateResultBlock, MRTextEditorCodeExecutionStrReplaceResultBlock, MRTextEditorCodeExecutionToolResultError, MRTextEditorCodeExecutionViewResultBlock]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRTextEditorCodeExecutionCreateResultBlock", "MRTextEditorCodeExecutionStrReplaceResultBlock", "MRTextEditorCodeExecutionToolResultError", "MRTextEditorCodeExecutionViewResultBlock" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content5.model_construct() + error_messages = [] + # validate data type: MRTextEditorCodeExecutionToolResultError + if not isinstance(v, MRTextEditorCodeExecutionToolResultError): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextEditorCodeExecutionToolResultError`") + else: + return v + + # validate data type: MRTextEditorCodeExecutionViewResultBlock + if not isinstance(v, MRTextEditorCodeExecutionViewResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextEditorCodeExecutionViewResultBlock`") + else: + return v + + # validate data type: MRTextEditorCodeExecutionCreateResultBlock + if not isinstance(v, MRTextEditorCodeExecutionCreateResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextEditorCodeExecutionCreateResultBlock`") + else: + return v + + # validate data type: MRTextEditorCodeExecutionStrReplaceResultBlock + if not isinstance(v, MRTextEditorCodeExecutionStrReplaceResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextEditorCodeExecutionStrReplaceResultBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content5 with anyOf schemas: MRTextEditorCodeExecutionCreateResultBlock, MRTextEditorCodeExecutionStrReplaceResultBlock, MRTextEditorCodeExecutionToolResultError, MRTextEditorCodeExecutionViewResultBlock. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRTextEditorCodeExecutionToolResultError] = None + try: + instance.actual_instance = MRTextEditorCodeExecutionToolResultError.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRTextEditorCodeExecutionViewResultBlock] = None + try: + instance.actual_instance = MRTextEditorCodeExecutionViewResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MRTextEditorCodeExecutionCreateResultBlock] = None + try: + instance.actual_instance = MRTextEditorCodeExecutionCreateResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MRTextEditorCodeExecutionStrReplaceResultBlock] = None + try: + instance.actual_instance = MRTextEditorCodeExecutionStrReplaceResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content5 with anyOf schemas: MRTextEditorCodeExecutionCreateResultBlock, MRTextEditorCodeExecutionStrReplaceResultBlock, MRTextEditorCodeExecutionToolResultError, MRTextEditorCodeExecutionViewResultBlock. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRTextEditorCodeExecutionCreateResultBlock, MRTextEditorCodeExecutionStrReplaceResultBlock, MRTextEditorCodeExecutionToolResultError, MRTextEditorCodeExecutionViewResultBlock]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content6.py b/src/otari/_client/models/content6.py new file mode 100644 index 0000000..9d80fde --- /dev/null +++ b/src/otari/_client/models/content6.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_tool_search_tool_result_error import MRToolSearchToolResultError +from otari._client.models.mr_tool_search_tool_search_result_block import MRToolSearchToolSearchResultBlock +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT6_ANY_OF_SCHEMAS = ["MRToolSearchToolResultError", "MRToolSearchToolSearchResultBlock"] + +class Content6(BaseModel): + """ + Content6 + """ + + # data type: MRToolSearchToolResultError + anyof_schema_1_validator: Optional[MRToolSearchToolResultError] = None + # data type: MRToolSearchToolSearchResultBlock + anyof_schema_2_validator: Optional[MRToolSearchToolSearchResultBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRToolSearchToolResultError, MRToolSearchToolSearchResultBlock]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRToolSearchToolResultError", "MRToolSearchToolSearchResultBlock" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content6.model_construct() + error_messages = [] + # validate data type: MRToolSearchToolResultError + if not isinstance(v, MRToolSearchToolResultError): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRToolSearchToolResultError`") + else: + return v + + # validate data type: MRToolSearchToolSearchResultBlock + if not isinstance(v, MRToolSearchToolSearchResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRToolSearchToolSearchResultBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content6 with anyOf schemas: MRToolSearchToolResultError, MRToolSearchToolSearchResultBlock. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRToolSearchToolResultError] = None + try: + instance.actual_instance = MRToolSearchToolResultError.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRToolSearchToolSearchResultBlock] = None + try: + instance.actual_instance = MRToolSearchToolSearchResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content6 with anyOf schemas: MRToolSearchToolResultError, MRToolSearchToolSearchResultBlock. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRToolSearchToolResultError, MRToolSearchToolSearchResultBlock]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content7.py b/src/otari/_client/models/content7.py new file mode 100644 index 0000000..9d8702a --- /dev/null +++ b/src/otari/_client/models/content7.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_web_fetch_block import MRWebFetchBlock +from otari._client.models.mr_web_fetch_tool_result_error_block import MRWebFetchToolResultErrorBlock +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT7_ANY_OF_SCHEMAS = ["MRWebFetchBlock", "MRWebFetchToolResultErrorBlock"] + +class Content7(BaseModel): + """ + Content7 + """ + + # data type: MRWebFetchToolResultErrorBlock + anyof_schema_1_validator: Optional[MRWebFetchToolResultErrorBlock] = None + # data type: MRWebFetchBlock + anyof_schema_2_validator: Optional[MRWebFetchBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRWebFetchBlock, MRWebFetchToolResultErrorBlock]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRWebFetchBlock", "MRWebFetchToolResultErrorBlock" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content7.model_construct() + error_messages = [] + # validate data type: MRWebFetchToolResultErrorBlock + if not isinstance(v, MRWebFetchToolResultErrorBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRWebFetchToolResultErrorBlock`") + else: + return v + + # validate data type: MRWebFetchBlock + if not isinstance(v, MRWebFetchBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRWebFetchBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content7 with anyOf schemas: MRWebFetchBlock, MRWebFetchToolResultErrorBlock. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRWebFetchToolResultErrorBlock] = None + try: + instance.actual_instance = MRWebFetchToolResultErrorBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRWebFetchBlock] = None + try: + instance.actual_instance = MRWebFetchBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content7 with anyOf schemas: MRWebFetchBlock, MRWebFetchToolResultErrorBlock. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRWebFetchBlock, MRWebFetchToolResultErrorBlock]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content8.py b/src/otari/_client/models/content8.py new file mode 100644 index 0000000..a745767 --- /dev/null +++ b/src/otari/_client/models/content8.py @@ -0,0 +1,137 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import List, Optional +from otari._client.models.mr_web_search_result_block import MRWebSearchResultBlock +from otari._client.models.mr_web_search_tool_result_error import MRWebSearchToolResultError +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT8_ANY_OF_SCHEMAS = ["List[MRWebSearchResultBlock]", "MRWebSearchToolResultError"] + +class Content8(BaseModel): + """ + Content8 + """ + + # data type: MRWebSearchToolResultError + anyof_schema_1_validator: Optional[MRWebSearchToolResultError] = None + # data type: List[MRWebSearchResultBlock] + anyof_schema_2_validator: Optional[List[MRWebSearchResultBlock]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[MRWebSearchResultBlock], MRWebSearchToolResultError]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[MRWebSearchResultBlock]", "MRWebSearchToolResultError" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content8.model_construct() + error_messages = [] + # validate data type: MRWebSearchToolResultError + if not isinstance(v, MRWebSearchToolResultError): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRWebSearchToolResultError`") + else: + return v + + # validate data type: List[MRWebSearchResultBlock] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content8 with anyOf schemas: List[MRWebSearchResultBlock], MRWebSearchToolResultError. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRWebSearchToolResultError] = None + try: + instance.actual_instance = MRWebSearchToolResultError.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[MRWebSearchResultBlock] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content8 with anyOf schemas: List[MRWebSearchResultBlock], MRWebSearchToolResultError. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[MRWebSearchResultBlock], MRWebSearchToolResultError]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content9_inner.py b/src/otari/_client/models/content9_inner.py new file mode 100644 index 0000000..b4fc172 --- /dev/null +++ b/src/otari/_client/models/content9_inner.py @@ -0,0 +1,284 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_bash_code_execution_tool_result_block import MRBashCodeExecutionToolResultBlock +from otari._client.models.mr_code_execution_tool_result_block import MRCodeExecutionToolResultBlock +from otari._client.models.mr_container_upload_block import MRContainerUploadBlock +from otari._client.models.mr_redacted_thinking_block import MRRedactedThinkingBlock +from otari._client.models.mr_server_tool_use_block import MRServerToolUseBlock +from otari._client.models.mr_text_block import MRTextBlock +from otari._client.models.mr_text_editor_code_execution_tool_result_block import MRTextEditorCodeExecutionToolResultBlock +from otari._client.models.mr_thinking_block import MRThinkingBlock +from otari._client.models.mr_tool_search_tool_result_block import MRToolSearchToolResultBlock +from otari._client.models.mr_tool_use_block import MRToolUseBlock +from otari._client.models.mr_web_fetch_tool_result_block import MRWebFetchToolResultBlock +from otari._client.models.mr_web_search_tool_result_block import MRWebSearchToolResultBlock +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENT9INNER_ANY_OF_SCHEMAS = ["MRBashCodeExecutionToolResultBlock", "MRCodeExecutionToolResultBlock", "MRContainerUploadBlock", "MRRedactedThinkingBlock", "MRServerToolUseBlock", "MRTextBlock", "MRTextEditorCodeExecutionToolResultBlock", "MRThinkingBlock", "MRToolSearchToolResultBlock", "MRToolUseBlock", "MRWebFetchToolResultBlock", "MRWebSearchToolResultBlock"] + +class Content9Inner(BaseModel): + """ + Content9Inner + """ + + # data type: MRTextBlock + anyof_schema_1_validator: Optional[MRTextBlock] = None + # data type: MRThinkingBlock + anyof_schema_2_validator: Optional[MRThinkingBlock] = None + # data type: MRRedactedThinkingBlock + anyof_schema_3_validator: Optional[MRRedactedThinkingBlock] = None + # data type: MRToolUseBlock + anyof_schema_4_validator: Optional[MRToolUseBlock] = None + # data type: MRServerToolUseBlock + anyof_schema_5_validator: Optional[MRServerToolUseBlock] = None + # data type: MRWebSearchToolResultBlock + anyof_schema_6_validator: Optional[MRWebSearchToolResultBlock] = None + # data type: MRWebFetchToolResultBlock + anyof_schema_7_validator: Optional[MRWebFetchToolResultBlock] = None + # data type: MRCodeExecutionToolResultBlock + anyof_schema_8_validator: Optional[MRCodeExecutionToolResultBlock] = None + # data type: MRBashCodeExecutionToolResultBlock + anyof_schema_9_validator: Optional[MRBashCodeExecutionToolResultBlock] = None + # data type: MRTextEditorCodeExecutionToolResultBlock + anyof_schema_10_validator: Optional[MRTextEditorCodeExecutionToolResultBlock] = None + # data type: MRToolSearchToolResultBlock + anyof_schema_11_validator: Optional[MRToolSearchToolResultBlock] = None + # data type: MRContainerUploadBlock + anyof_schema_12_validator: Optional[MRContainerUploadBlock] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRBashCodeExecutionToolResultBlock, MRCodeExecutionToolResultBlock, MRContainerUploadBlock, MRRedactedThinkingBlock, MRServerToolUseBlock, MRTextBlock, MRTextEditorCodeExecutionToolResultBlock, MRThinkingBlock, MRToolSearchToolResultBlock, MRToolUseBlock, MRWebFetchToolResultBlock, MRWebSearchToolResultBlock]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRBashCodeExecutionToolResultBlock", "MRCodeExecutionToolResultBlock", "MRContainerUploadBlock", "MRRedactedThinkingBlock", "MRServerToolUseBlock", "MRTextBlock", "MRTextEditorCodeExecutionToolResultBlock", "MRThinkingBlock", "MRToolSearchToolResultBlock", "MRToolUseBlock", "MRWebFetchToolResultBlock", "MRWebSearchToolResultBlock" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Content9Inner.model_construct() + error_messages = [] + # validate data type: MRTextBlock + if not isinstance(v, MRTextBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextBlock`") + else: + return v + + # validate data type: MRThinkingBlock + if not isinstance(v, MRThinkingBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRThinkingBlock`") + else: + return v + + # validate data type: MRRedactedThinkingBlock + if not isinstance(v, MRRedactedThinkingBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRRedactedThinkingBlock`") + else: + return v + + # validate data type: MRToolUseBlock + if not isinstance(v, MRToolUseBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRToolUseBlock`") + else: + return v + + # validate data type: MRServerToolUseBlock + if not isinstance(v, MRServerToolUseBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRServerToolUseBlock`") + else: + return v + + # validate data type: MRWebSearchToolResultBlock + if not isinstance(v, MRWebSearchToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRWebSearchToolResultBlock`") + else: + return v + + # validate data type: MRWebFetchToolResultBlock + if not isinstance(v, MRWebFetchToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRWebFetchToolResultBlock`") + else: + return v + + # validate data type: MRCodeExecutionToolResultBlock + if not isinstance(v, MRCodeExecutionToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCodeExecutionToolResultBlock`") + else: + return v + + # validate data type: MRBashCodeExecutionToolResultBlock + if not isinstance(v, MRBashCodeExecutionToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRBashCodeExecutionToolResultBlock`") + else: + return v + + # validate data type: MRTextEditorCodeExecutionToolResultBlock + if not isinstance(v, MRTextEditorCodeExecutionToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRTextEditorCodeExecutionToolResultBlock`") + else: + return v + + # validate data type: MRToolSearchToolResultBlock + if not isinstance(v, MRToolSearchToolResultBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRToolSearchToolResultBlock`") + else: + return v + + # validate data type: MRContainerUploadBlock + if not isinstance(v, MRContainerUploadBlock): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRContainerUploadBlock`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Content9Inner with anyOf schemas: MRBashCodeExecutionToolResultBlock, MRCodeExecutionToolResultBlock, MRContainerUploadBlock, MRRedactedThinkingBlock, MRServerToolUseBlock, MRTextBlock, MRTextEditorCodeExecutionToolResultBlock, MRThinkingBlock, MRToolSearchToolResultBlock, MRToolUseBlock, MRWebFetchToolResultBlock, MRWebSearchToolResultBlock. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRTextBlock] = None + try: + instance.actual_instance = MRTextBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRThinkingBlock] = None + try: + instance.actual_instance = MRThinkingBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MRRedactedThinkingBlock] = None + try: + instance.actual_instance = MRRedactedThinkingBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MRToolUseBlock] = None + try: + instance.actual_instance = MRToolUseBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_5_validator: Optional[MRServerToolUseBlock] = None + try: + instance.actual_instance = MRServerToolUseBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_6_validator: Optional[MRWebSearchToolResultBlock] = None + try: + instance.actual_instance = MRWebSearchToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_7_validator: Optional[MRWebFetchToolResultBlock] = None + try: + instance.actual_instance = MRWebFetchToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_8_validator: Optional[MRCodeExecutionToolResultBlock] = None + try: + instance.actual_instance = MRCodeExecutionToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_9_validator: Optional[MRBashCodeExecutionToolResultBlock] = None + try: + instance.actual_instance = MRBashCodeExecutionToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_10_validator: Optional[MRTextEditorCodeExecutionToolResultBlock] = None + try: + instance.actual_instance = MRTextEditorCodeExecutionToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_11_validator: Optional[MRToolSearchToolResultBlock] = None + try: + instance.actual_instance = MRToolSearchToolResultBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_12_validator: Optional[MRContainerUploadBlock] = None + try: + instance.actual_instance = MRContainerUploadBlock.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Content9Inner with anyOf schemas: MRBashCodeExecutionToolResultBlock, MRCodeExecutionToolResultBlock, MRContainerUploadBlock, MRRedactedThinkingBlock, MRServerToolUseBlock, MRTextBlock, MRTextEditorCodeExecutionToolResultBlock, MRThinkingBlock, MRToolSearchToolResultBlock, MRToolUseBlock, MRWebFetchToolResultBlock, MRWebSearchToolResultBlock. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRBashCodeExecutionToolResultBlock, MRCodeExecutionToolResultBlock, MRContainerUploadBlock, MRRedactedThinkingBlock, MRServerToolUseBlock, MRTextBlock, MRTextEditorCodeExecutionToolResultBlock, MRThinkingBlock, MRToolSearchToolResultBlock, MRToolUseBlock, MRWebFetchToolResultBlock, MRWebSearchToolResultBlock]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/content_any_of_inner.py b/src/otari/_client/models/content_any_of_inner.py new file mode 100644 index 0000000..d58b39f --- /dev/null +++ b/src/otari/_client/models/content_any_of_inner.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.msg_chat_completion_content_part_refusal_param import MSGChatCompletionContentPartRefusalParam +from otari._client.models.msg_chat_completion_content_part_text_param import MSGChatCompletionContentPartTextParam +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +CONTENTANYOFINNER_ANY_OF_SCHEMAS = ["MSGChatCompletionContentPartRefusalParam", "MSGChatCompletionContentPartTextParam"] + +class ContentAnyOfInner(BaseModel): + """ + ContentAnyOfInner + """ + + # data type: MSGChatCompletionContentPartTextParam + anyof_schema_1_validator: Optional[MSGChatCompletionContentPartTextParam] = None + # data type: MSGChatCompletionContentPartRefusalParam + anyof_schema_2_validator: Optional[MSGChatCompletionContentPartRefusalParam] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MSGChatCompletionContentPartRefusalParam, MSGChatCompletionContentPartTextParam]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MSGChatCompletionContentPartRefusalParam", "MSGChatCompletionContentPartTextParam" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = ContentAnyOfInner.model_construct() + error_messages = [] + # validate data type: MSGChatCompletionContentPartTextParam + if not isinstance(v, MSGChatCompletionContentPartTextParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionContentPartTextParam`") + else: + return v + + # validate data type: MSGChatCompletionContentPartRefusalParam + if not isinstance(v, MSGChatCompletionContentPartRefusalParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionContentPartRefusalParam`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in ContentAnyOfInner with anyOf schemas: MSGChatCompletionContentPartRefusalParam, MSGChatCompletionContentPartTextParam. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MSGChatCompletionContentPartTextParam] = None + try: + instance.actual_instance = MSGChatCompletionContentPartTextParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MSGChatCompletionContentPartRefusalParam] = None + try: + instance.actual_instance = MSGChatCompletionContentPartRefusalParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into ContentAnyOfInner with anyOf schemas: MSGChatCompletionContentPartRefusalParam, MSGChatCompletionContentPartTextParam. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MSGChatCompletionContentPartRefusalParam, MSGChatCompletionContentPartTextParam]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/create_batch_request.py b/src/otari/_client/models/create_batch_request.py new file mode 100644 index 0000000..0a6f3dc --- /dev/null +++ b/src/otari/_client/models/create_batch_request.py @@ -0,0 +1,108 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from otari._client.models.batch_request_item import BatchRequestItem +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateBatchRequest(BaseModel): + """ + CreateBatchRequest + """ # noqa: E501 + completion_window: Optional[StrictStr] = '24h' + metadata: Optional[Dict[str, StrictStr]] = None + model: StrictStr + requests: Annotated[List[BatchRequestItem], Field(min_length=1, max_length=10000)] + __properties: ClassVar[List[str]] = ["completion_window", "metadata", "model", "requests"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateBatchRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in requests (list) + _items = [] + if self.requests: + for _item_requests in self.requests: + if _item_requests: + _items.append(_item_requests.to_dict()) + _dict['requests'] = _items + # set to None if metadata (nullable) is None + # and model_fields_set contains the field + if self.metadata is None and "metadata" in self.model_fields_set: + _dict['metadata'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateBatchRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "completion_window": obj.get("completion_window") if obj.get("completion_window") is not None else '24h', + "metadata": obj.get("metadata"), + "model": obj.get("model"), + "requests": [BatchRequestItem.from_dict(_item) for _item in obj["requests"]] if obj.get("requests") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/create_budget_request.py b/src/otari/_client/models/create_budget_request.py new file mode 100644 index 0000000..e9f8a41 --- /dev/null +++ b/src/otari/_client/models/create_budget_request.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateBudgetRequest(BaseModel): + """ + Request model for creating a new budget. + """ # noqa: E501 + budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)") + max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = Field(default=None, description="Maximum spending limit") + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateBudgetRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if budget_duration_sec (nullable) is None + # and model_fields_set contains the field + if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: + _dict['budget_duration_sec'] = None + + # set to None if max_budget (nullable) is None + # and model_fields_set contains the field + if self.max_budget is None and "max_budget" in self.model_fields_set: + _dict['max_budget'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateBudgetRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "budget_duration_sec": obj.get("budget_duration_sec"), + "max_budget": obj.get("max_budget") + }) + return _obj + + diff --git a/src/otari/_client/models/create_embedding_response.py b/src/otari/_client/models/create_embedding_response.py new file mode 100644 index 0000000..4b1ef54 --- /dev/null +++ b/src/otari/_client/models/create_embedding_response.py @@ -0,0 +1,126 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.emb_embedding import EMBEmbedding +from otari._client.models.emb_usage import EMBUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateEmbeddingResponse(BaseModel): + """ + CreateEmbeddingResponse + """ # noqa: E501 + data: List[EMBEmbedding] + model: StrictStr + object: StrictStr + usage: EMBUsage + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["data", "model", "object", "usage"] + + @field_validator('object') + def object_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['list']): + raise ValueError("must be one of enum values ('list')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateEmbeddingResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in data (list) + _items = [] + if self.data: + for _item_data in self.data: + if _item_data: + _items.append(_item_data.to_dict()) + _dict['data'] = _items + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateEmbeddingResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": [EMBEmbedding.from_dict(_item) for _item in obj["data"]] if obj.get("data") is not None else None, + "model": obj.get("model"), + "object": obj.get("object"), + "usage": EMBUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/create_key_request.py b/src/otari/_client/models/create_key_request.py new file mode 100644 index 0000000..114145f --- /dev/null +++ b/src/otari/_client/models/create_key_request.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateKeyRequest(BaseModel): + """ + Request model for creating a new API key. + """ # noqa: E501 + expires_at: Optional[datetime] = Field(default=None, description="Optional expiration timestamp") + key_name: Optional[StrictStr] = Field(default=None, description="Optional name for the key") + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Optional metadata") + user_id: Optional[StrictStr] = Field(default=None, description="Optional user ID to associate with this key") + __properties: ClassVar[List[str]] = ["expires_at", "key_name", "metadata", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateKeyRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if expires_at (nullable) is None + # and model_fields_set contains the field + if self.expires_at is None and "expires_at" in self.model_fields_set: + _dict['expires_at'] = None + + # set to None if key_name (nullable) is None + # and model_fields_set contains the field + if self.key_name is None and "key_name" in self.model_fields_set: + _dict['key_name'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateKeyRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "expires_at": obj.get("expires_at"), + "key_name": obj.get("key_name"), + "metadata": obj.get("metadata"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/create_key_response.py b/src/otari/_client/models/create_key_response.py new file mode 100644 index 0000000..d279801 --- /dev/null +++ b/src/otari/_client/models/create_key_response.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateKeyResponse(BaseModel): + """ + Response model for creating a new API key. + """ # noqa: E501 + created_at: StrictStr + expires_at: Optional[StrictStr] + id: StrictStr + is_active: StrictBool + key: StrictStr + key_name: Optional[StrictStr] + metadata: Dict[str, Any] + user_id: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["created_at", "expires_at", "id", "is_active", "key", "key_name", "metadata", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateKeyResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if expires_at (nullable) is None + # and model_fields_set contains the field + if self.expires_at is None and "expires_at" in self.model_fields_set: + _dict['expires_at'] = None + + # set to None if key_name (nullable) is None + # and model_fields_set contains the field + if self.key_name is None and "key_name" in self.model_fields_set: + _dict['key_name'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateKeyResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "created_at": obj.get("created_at"), + "expires_at": obj.get("expires_at"), + "id": obj.get("id"), + "is_active": obj.get("is_active"), + "key": obj.get("key"), + "key_name": obj.get("key_name"), + "metadata": obj.get("metadata"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/create_user_request.py b/src/otari/_client/models/create_user_request.py new file mode 100644 index 0000000..1003904 --- /dev/null +++ b/src/otari/_client/models/create_user_request.py @@ -0,0 +1,106 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateUserRequest(BaseModel): + """ + Request model for creating a new user. + """ # noqa: E501 + alias: Optional[StrictStr] = Field(default=None, description="Optional admin-facing alias") + blocked: Optional[StrictBool] = Field(default=False, description="Whether user is blocked") + budget_id: Optional[StrictStr] = Field(default=None, description="Optional budget ID") + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Optional metadata") + user_id: StrictStr = Field(description="Unique user identifier") + __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "metadata", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateUserRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if alias (nullable) is None + # and model_fields_set contains the field + if self.alias is None and "alias" in self.model_fields_set: + _dict['alias'] = None + + # set to None if budget_id (nullable) is None + # and model_fields_set contains the field + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateUserRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "alias": obj.get("alias"), + "blocked": obj.get("blocked") if obj.get("blocked") is not None else False, + "budget_id": obj.get("budget_id"), + "metadata": obj.get("metadata"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/emb_embedding.py b/src/otari/_client/models/emb_embedding.py new file mode 100644 index 0000000..4cef120 --- /dev/null +++ b/src/otari/_client/models/emb_embedding.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class EMBEmbedding(BaseModel): + """ + Represents an embedding vector returned by embedding endpoint. + """ # noqa: E501 + embedding: List[Union[StrictFloat, StrictInt]] + index: StrictInt + object: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["embedding", "index", "object"] + + @field_validator('object') + def object_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['embedding']): + raise ValueError("must be one of enum values ('embedding')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of EMBEmbedding from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EMBEmbedding from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "embedding": obj.get("embedding"), + "index": obj.get("index"), + "object": obj.get("object") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/emb_usage.py b/src/otari/_client/models/emb_usage.py new file mode 100644 index 0000000..4bbc5be --- /dev/null +++ b/src/otari/_client/models/emb_usage.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class EMBUsage(BaseModel): + """ + The usage information for the request. + """ # noqa: E501 + prompt_tokens: StrictInt + total_tokens: StrictInt + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["prompt_tokens", "total_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of EMBUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EMBUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "prompt_tokens": obj.get("prompt_tokens"), + "total_tokens": obj.get("total_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/embedding_request.py b/src/otari/_client/models/embedding_request.py new file mode 100644 index 0000000..4ab6215 --- /dev/null +++ b/src/otari/_client/models/embedding_request.py @@ -0,0 +1,115 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.input import Input +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class EmbeddingRequest(BaseModel): + """ + OpenAI-compatible embedding request. + """ # noqa: E501 + dimensions: Optional[StrictInt] = None + encoding_format: Optional[StrictStr] = None + input: Input + model: StrictStr + user: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["dimensions", "encoding_format", "input", "model", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of EmbeddingRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of input + if self.input: + _dict['input'] = self.input.to_dict() + # set to None if dimensions (nullable) is None + # and model_fields_set contains the field + if self.dimensions is None and "dimensions" in self.model_fields_set: + _dict['dimensions'] = None + + # set to None if encoding_format (nullable) is None + # and model_fields_set contains the field + if self.encoding_format is None and "encoding_format" in self.model_fields_set: + _dict['encoding_format'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EmbeddingRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "dimensions": obj.get("dimensions"), + "encoding_format": obj.get("encoding_format"), + "input": Input.from_dict(obj["input"]) if obj.get("input") is not None else None, + "model": obj.get("model"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/guardrail_config.py b/src/otari/_client/models/guardrail_config.py new file mode 100644 index 0000000..89d663d --- /dev/null +++ b/src/otari/_client/models/guardrail_config.py @@ -0,0 +1,123 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class GuardrailConfig(BaseModel): + """ + A single guardrail check the caller wants the gateway to enforce. URL safety: when ``url`` is supplied it is validated at parse time with the same SSRF guard used for MCP server URLs (loopback allowed by default for same-host sidecars; gated by ``GATEWAY_MCP_ALLOW_LOOPBACK`` / ``GATEWAY_MCP_ALLOW_PRIVATE_HOSTS``). Most deployments omit ``url`` and rely on the operator-set ``GATEWAY_GUARDRAILS_URL`` instead. + """ # noqa: E501 + mode: Optional[StrictStr] = 'monitor' + on: Optional[List[StrictStr]] = None + profile: Annotated[str, Field(min_length=1, strict=True, max_length=128)] + url: Optional[Annotated[str, Field(min_length=1, strict=True)]] = None + validate_kwargs: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["mode", "on", "profile", "url", "validate_kwargs"] + + @field_validator('mode') + def mode_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['block', 'monitor']): + raise ValueError("must be one of enum values ('block', 'monitor')") + return value + + @field_validator('on') + def on_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + for i in value: + if i not in set(['input', 'output']): + raise ValueError("each list item must be one of ('input', 'output')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GuardrailConfig from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if url (nullable) is None + # and model_fields_set contains the field + if self.url is None and "url" in self.model_fields_set: + _dict['url'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GuardrailConfig from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "mode": obj.get("mode") if obj.get("mode") is not None else 'monitor', + "on": obj.get("on"), + "profile": obj.get("profile"), + "url": obj.get("url"), + "validate_kwargs": obj.get("validate_kwargs") + }) + return _obj + + diff --git a/src/otari/_client/models/http_validation_error.py b/src/otari/_client/models/http_validation_error.py new file mode 100644 index 0000000..9adaa01 --- /dev/null +++ b/src/otari/_client/models/http_validation_error.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.validation_error import ValidationError +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class HTTPValidationError(BaseModel): + """ + HTTPValidationError + """ # noqa: E501 + detail: Optional[List[ValidationError]] = None + __properties: ClassVar[List[str]] = ["detail"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of HTTPValidationError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in detail (list) + _items = [] + if self.detail: + for _item_detail in self.detail: + if _item_detail: + _items.append(_item_detail.to_dict()) + _dict['detail'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of HTTPValidationError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "detail": [ValidationError.from_dict(_item) for _item in obj["detail"]] if obj.get("detail") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/image_generation_request.py b/src/otari/_client/models/image_generation_request.py new file mode 100644 index 0000000..7452d9f --- /dev/null +++ b/src/otari/_client/models/image_generation_request.py @@ -0,0 +1,132 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ImageGenerationRequest(BaseModel): + """ + OpenAI-compatible image generation request. + """ # noqa: E501 + model: StrictStr + n: Optional[StrictInt] = None + prompt: StrictStr + quality: Optional[StrictStr] = None + response_format: Optional[StrictStr] = None + size: Optional[StrictStr] = None + style: Optional[StrictStr] = None + user: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["model", "n", "prompt", "quality", "response_format", "size", "style", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ImageGenerationRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if n (nullable) is None + # and model_fields_set contains the field + if self.n is None and "n" in self.model_fields_set: + _dict['n'] = None + + # set to None if quality (nullable) is None + # and model_fields_set contains the field + if self.quality is None and "quality" in self.model_fields_set: + _dict['quality'] = None + + # set to None if response_format (nullable) is None + # and model_fields_set contains the field + if self.response_format is None and "response_format" in self.model_fields_set: + _dict['response_format'] = None + + # set to None if size (nullable) is None + # and model_fields_set contains the field + if self.size is None and "size" in self.model_fields_set: + _dict['size'] = None + + # set to None if style (nullable) is None + # and model_fields_set contains the field + if self.style is None and "style" in self.model_fields_set: + _dict['style'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ImageGenerationRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "model": obj.get("model"), + "n": obj.get("n"), + "prompt": obj.get("prompt"), + "quality": obj.get("quality"), + "response_format": obj.get("response_format"), + "size": obj.get("size"), + "style": obj.get("style"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/input.py b/src/otari/_client/models/input.py new file mode 100644 index 0000000..90b6639 --- /dev/null +++ b/src/otari/_client/models/input.py @@ -0,0 +1,138 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import List, Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +INPUT_ANY_OF_SCHEMAS = ["List[str]", "str"] + +class Input(BaseModel): + """ + Input text to embed + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: List[str] + anyof_schema_2_validator: Optional[List[StrictStr]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[str], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[str]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Input.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[str] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Input with anyOf schemas: List[str], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[str] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Input with anyOf schemas: List[str], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[str], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/input1.py b/src/otari/_client/models/input1.py new file mode 100644 index 0000000..47fa16d --- /dev/null +++ b/src/otari/_client/models/input1.py @@ -0,0 +1,155 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, Dict, List, Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +INPUT1_ANY_OF_SCHEMAS = ["List[Dict[str, object]]", "List[str]", "str"] + +class Input1(BaseModel): + """ + Text, list of texts, or list of content-part dicts to moderate + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + # data type: List[str] + anyof_schema_2_validator: Optional[List[StrictStr]] = None + # data type: List[Dict[str, object]] + anyof_schema_3_validator: Optional[List[Dict[str, Any]]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[Dict[str, object]], List[str], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[Dict[str, object]]", "List[str]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Input1.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[str] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[Dict[str, object]] + try: + instance.anyof_schema_3_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Input1 with anyOf schemas: List[Dict[str, object]], List[str], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[str] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[Dict[str, object]] + try: + # validation + instance.anyof_schema_3_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_3_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Input1 with anyOf schemas: List[Dict[str, object]], List[str], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[Dict[str, object]], List[str], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/key_info.py b/src/otari/_client/models/key_info.py new file mode 100644 index 0000000..e018dd0 --- /dev/null +++ b/src/otari/_client/models/key_info.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class KeyInfo(BaseModel): + """ + Response model for key information. + """ # noqa: E501 + created_at: StrictStr + expires_at: Optional[StrictStr] + id: StrictStr + is_active: StrictBool + key_name: Optional[StrictStr] + last_used_at: Optional[StrictStr] + metadata: Dict[str, Any] + user_id: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["created_at", "expires_at", "id", "is_active", "key_name", "last_used_at", "metadata", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of KeyInfo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if expires_at (nullable) is None + # and model_fields_set contains the field + if self.expires_at is None and "expires_at" in self.model_fields_set: + _dict['expires_at'] = None + + # set to None if key_name (nullable) is None + # and model_fields_set contains the field + if self.key_name is None and "key_name" in self.model_fields_set: + _dict['key_name'] = None + + # set to None if last_used_at (nullable) is None + # and model_fields_set contains the field + if self.last_used_at is None and "last_used_at" in self.model_fields_set: + _dict['last_used_at'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of KeyInfo from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "created_at": obj.get("created_at"), + "expires_at": obj.get("expires_at"), + "id": obj.get("id"), + "is_active": obj.get("is_active"), + "key_name": obj.get("key_name"), + "last_used_at": obj.get("last_used_at"), + "metadata": obj.get("metadata"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/location_inner.py b/src/otari/_client/models/location_inner.py new file mode 100644 index 0000000..502dd3d --- /dev/null +++ b/src/otari/_client/models/location_inner.py @@ -0,0 +1,138 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, ValidationError, field_validator +from typing import Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +LOCATIONINNER_ANY_OF_SCHEMAS = ["int", "str"] + +class LocationInner(BaseModel): + """ + LocationInner + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: int + anyof_schema_2_validator: Optional[StrictInt] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[int, str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "int", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = LocationInner.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: int + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in LocationInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into int + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into LocationInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], int, str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/mcp_server_config.py b/src/otari/_client/models/mcp_server_config.py new file mode 100644 index 0000000..f66ffa0 --- /dev/null +++ b/src/otari/_client/models/mcp_server_config.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class McpServerConfig(BaseModel): + """ + Inline MCP server configuration accepted on the chat completions request. Streamable HTTP transport. The `url` must be reachable from the gateway process. URL safety is enforced at parse time: * SSRF guard rejects private, link-local, and reserved IP ranges. Loopback is allowed by default (sidecars, dev) — set ``GATEWAY_MCP_ALLOW_LOOPBACK=false`` to disable. * Plain ``http://`` is rejected when ``authorization_token`` is set, to keep bearer tokens off the wire in cleartext. + """ # noqa: E501 + allowed_tools: Optional[List[StrictStr]] = None + authorization_token: Optional[StrictStr] = None + name: Annotated[str, Field(min_length=1, strict=True, max_length=128)] + purpose_hint: Optional[Annotated[str, Field(strict=True, max_length=2000)]] = None + url: Annotated[str, Field(min_length=1, strict=True)] + __properties: ClassVar[List[str]] = ["allowed_tools", "authorization_token", "name", "purpose_hint", "url"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of McpServerConfig from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if allowed_tools (nullable) is None + # and model_fields_set contains the field + if self.allowed_tools is None and "allowed_tools" in self.model_fields_set: + _dict['allowed_tools'] = None + + # set to None if authorization_token (nullable) is None + # and model_fields_set contains the field + if self.authorization_token is None and "authorization_token" in self.model_fields_set: + _dict['authorization_token'] = None + + # set to None if purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.purpose_hint is None and "purpose_hint" in self.model_fields_set: + _dict['purpose_hint'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of McpServerConfig from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "allowed_tools": obj.get("allowed_tools"), + "authorization_token": obj.get("authorization_token"), + "name": obj.get("name"), + "purpose_hint": obj.get("purpose_hint"), + "url": obj.get("url") + }) + return _obj + + diff --git a/src/otari/_client/models/message_response.py b/src/otari/_client/models/message_response.py new file mode 100644 index 0000000..b8f2149 --- /dev/null +++ b/src/otari/_client/models/message_response.py @@ -0,0 +1,187 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.content9_inner import Content9Inner +from otari._client.models.model import Model +from otari._client.models.mr_container import MRContainer +from otari._client.models.mr_refusal_stop_details import MRRefusalStopDetails +from otari._client.models.mr_usage import MRUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MessageResponse(BaseModel): + """ + MessageResponse + """ # noqa: E501 + id: StrictStr + container: Optional[MRContainer] = None + content: List[Content9Inner] + model: Model + role: StrictStr + stop_details: Optional[MRRefusalStopDetails] = None + stop_reason: Optional[StrictStr] = None + stop_sequence: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + type: StrictStr + usage: MRUsage + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "container", "content", "model", "role", "stop_details", "stop_reason", "stop_sequence", "type", "usage"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['assistant']): + raise ValueError("must be one of enum values ('assistant')") + return value + + @field_validator('stop_reason') + def stop_reason_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['end_turn', 'max_tokens', 'stop_sequence', 'tool_use', 'pause_turn', 'refusal']): + raise ValueError("must be one of enum values ('end_turn', 'max_tokens', 'stop_sequence', 'tool_use', 'pause_turn', 'refusal')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['message']): + raise ValueError("must be one of enum values ('message')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MessageResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of container + if self.container: + _dict['container'] = self.container.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # override the default output from pydantic by calling `to_dict()` of model + if self.model: + _dict['model'] = self.model.to_dict() + # override the default output from pydantic by calling `to_dict()` of stop_details + if self.stop_details: + _dict['stop_details'] = self.stop_details.to_dict() + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if container (nullable) is None + # and model_fields_set contains the field + if self.container is None and "container" in self.model_fields_set: + _dict['container'] = None + + # set to None if stop_details (nullable) is None + # and model_fields_set contains the field + if self.stop_details is None and "stop_details" in self.model_fields_set: + _dict['stop_details'] = None + + # set to None if stop_reason (nullable) is None + # and model_fields_set contains the field + if self.stop_reason is None and "stop_reason" in self.model_fields_set: + _dict['stop_reason'] = None + + # set to None if stop_sequence (nullable) is None + # and model_fields_set contains the field + if self.stop_sequence is None and "stop_sequence" in self.model_fields_set: + _dict['stop_sequence'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MessageResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "container": MRContainer.from_dict(obj["container"]) if obj.get("container") is not None else None, + "content": [Content9Inner.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "model": Model.from_dict(obj["model"]) if obj.get("model") is not None else None, + "role": obj.get("role"), + "stop_details": MRRefusalStopDetails.from_dict(obj["stop_details"]) if obj.get("stop_details") is not None else None, + "stop_reason": obj.get("stop_reason"), + "stop_sequence": obj.get("stop_sequence"), + "type": obj.get("type"), + "usage": MRUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/messages_request.py b/src/otari/_client/models/messages_request.py new file mode 100644 index 0000000..8f9b4c8 --- /dev/null +++ b/src/otari/_client/models/messages_request.py @@ -0,0 +1,221 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from uuid import UUID +from otari._client.models.guardrail_config import GuardrailConfig +from otari._client.models.mcp_server_config import McpServerConfig +from otari._client.models.system import System +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MessagesRequest(BaseModel): + """ + Anthropic Messages API-compatible request. Gateway-internal fields (``mcp_servers``, ``mcp_server_ids``, ``guardrails``, ``tools_header``, ``max_tool_iterations``) opt the request into gateway-managed MCP / sandbox / web_search / guardrails without changing the upstream wire shape. They're stripped before the request is forwarded. + """ # noqa: E501 + cache_control: Optional[Dict[str, Any]] = None + guardrails: Optional[Annotated[List[GuardrailConfig], Field(max_length=8)]] = None + max_tokens: StrictInt + max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None + mcp_server_ids: Optional[List[UUID]] = None + mcp_servers: Optional[List[McpServerConfig]] = None + messages: Annotated[List[Optional[Dict[str, Any]]], Field(min_length=1)] + metadata: Optional[Dict[str, Any]] = None + model: StrictStr + stop_sequences: Optional[List[StrictStr]] = None + stream: Optional[StrictBool] = False + system: Optional[System] = None + temperature: Optional[Union[StrictFloat, StrictInt]] = None + thinking: Optional[Dict[str, Any]] = None + tool_choice: Optional[Dict[str, Any]] = None + tools: Optional[List[Dict[str, Any]]] = None + tools_header: Optional[StrictStr] = None + top_k: Optional[StrictInt] = None + top_p: Optional[Union[StrictFloat, StrictInt]] = None + __properties: ClassVar[List[str]] = ["cache_control", "guardrails", "max_tokens", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "messages", "metadata", "model", "stop_sequences", "stream", "system", "temperature", "thinking", "tool_choice", "tools", "tools_header", "top_k", "top_p"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MessagesRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in guardrails (list) + _items = [] + if self.guardrails: + for _item_guardrails in self.guardrails: + if _item_guardrails: + _items.append(_item_guardrails.to_dict()) + _dict['guardrails'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in mcp_servers (list) + _items = [] + if self.mcp_servers: + for _item_mcp_servers in self.mcp_servers: + if _item_mcp_servers: + _items.append(_item_mcp_servers.to_dict()) + _dict['mcp_servers'] = _items + # override the default output from pydantic by calling `to_dict()` of system + if self.system: + _dict['system'] = self.system.to_dict() + # set to None if cache_control (nullable) is None + # and model_fields_set contains the field + if self.cache_control is None and "cache_control" in self.model_fields_set: + _dict['cache_control'] = None + + # set to None if guardrails (nullable) is None + # and model_fields_set contains the field + if self.guardrails is None and "guardrails" in self.model_fields_set: + _dict['guardrails'] = None + + # set to None if max_tool_iterations (nullable) is None + # and model_fields_set contains the field + if self.max_tool_iterations is None and "max_tool_iterations" in self.model_fields_set: + _dict['max_tool_iterations'] = None + + # set to None if mcp_server_ids (nullable) is None + # and model_fields_set contains the field + if self.mcp_server_ids is None and "mcp_server_ids" in self.model_fields_set: + _dict['mcp_server_ids'] = None + + # set to None if mcp_servers (nullable) is None + # and model_fields_set contains the field + if self.mcp_servers is None and "mcp_servers" in self.model_fields_set: + _dict['mcp_servers'] = None + + # set to None if metadata (nullable) is None + # and model_fields_set contains the field + if self.metadata is None and "metadata" in self.model_fields_set: + _dict['metadata'] = None + + # set to None if stop_sequences (nullable) is None + # and model_fields_set contains the field + if self.stop_sequences is None and "stop_sequences" in self.model_fields_set: + _dict['stop_sequences'] = None + + # set to None if system (nullable) is None + # and model_fields_set contains the field + if self.system is None and "system" in self.model_fields_set: + _dict['system'] = None + + # set to None if temperature (nullable) is None + # and model_fields_set contains the field + if self.temperature is None and "temperature" in self.model_fields_set: + _dict['temperature'] = None + + # set to None if thinking (nullable) is None + # and model_fields_set contains the field + if self.thinking is None and "thinking" in self.model_fields_set: + _dict['thinking'] = None + + # set to None if tool_choice (nullable) is None + # and model_fields_set contains the field + if self.tool_choice is None and "tool_choice" in self.model_fields_set: + _dict['tool_choice'] = None + + # set to None if tools (nullable) is None + # and model_fields_set contains the field + if self.tools is None and "tools" in self.model_fields_set: + _dict['tools'] = None + + # set to None if tools_header (nullable) is None + # and model_fields_set contains the field + if self.tools_header is None and "tools_header" in self.model_fields_set: + _dict['tools_header'] = None + + # set to None if top_k (nullable) is None + # and model_fields_set contains the field + if self.top_k is None and "top_k" in self.model_fields_set: + _dict['top_k'] = None + + # set to None if top_p (nullable) is None + # and model_fields_set contains the field + if self.top_p is None and "top_p" in self.model_fields_set: + _dict['top_p'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MessagesRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cache_control": obj.get("cache_control"), + "guardrails": [GuardrailConfig.from_dict(_item) for _item in obj["guardrails"]] if obj.get("guardrails") is not None else None, + "max_tokens": obj.get("max_tokens"), + "max_tool_iterations": obj.get("max_tool_iterations"), + "mcp_server_ids": obj.get("mcp_server_ids"), + "mcp_servers": [McpServerConfig.from_dict(_item) for _item in obj["mcp_servers"]] if obj.get("mcp_servers") is not None else None, + "messages": obj.get("messages"), + "metadata": obj.get("metadata"), + "model": obj.get("model"), + "stop_sequences": obj.get("stop_sequences"), + "stream": obj.get("stream") if obj.get("stream") is not None else False, + "system": System.from_dict(obj["system"]) if obj.get("system") is not None else None, + "temperature": obj.get("temperature"), + "thinking": obj.get("thinking"), + "tool_choice": obj.get("tool_choice"), + "tools": obj.get("tools"), + "tools_header": obj.get("tools_header"), + "top_k": obj.get("top_k"), + "top_p": obj.get("top_p") + }) + return _obj + + diff --git a/src/otari/_client/models/model.py b/src/otari/_client/models/model.py new file mode 100644 index 0000000..86ca45a --- /dev/null +++ b/src/otari/_client/models/model.py @@ -0,0 +1,138 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +MODEL_ANY_OF_SCHEMAS = ["str"] + +class Model(BaseModel): + """ + Model + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = None + # data type: str + anyof_schema_2_validator: Optional[StrictStr] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Model.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: str + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Model with anyOf schemas: str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into str + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Model with anyOf schemas: str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/model_list_response.py b/src/otari/_client/models/model_list_response.py new file mode 100644 index 0000000..8c8dedb --- /dev/null +++ b/src/otari/_client/models/model_list_response.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.model_object import ModelObject +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModelListResponse(BaseModel): + """ + OpenAI-compatible model list response. + """ # noqa: E501 + data: List[ModelObject] + object: Optional[StrictStr] = 'list' + __properties: ClassVar[List[str]] = ["data", "object"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModelListResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in data (list) + _items = [] + if self.data: + for _item_data in self.data: + if _item_data: + _items.append(_item_data.to_dict()) + _dict['data'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModelListResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": [ModelObject.from_dict(_item) for _item in obj["data"]] if obj.get("data") is not None else None, + "object": obj.get("object") if obj.get("object") is not None else 'list' + }) + return _obj + + diff --git a/src/otari/_client/models/model_object.py b/src/otari/_client/models/model_object.py new file mode 100644 index 0000000..6c58a63 --- /dev/null +++ b/src/otari/_client/models/model_object.py @@ -0,0 +1,105 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.model_pricing_info import ModelPricingInfo +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModelObject(BaseModel): + """ + OpenAI-compatible model object. + """ # noqa: E501 + created: StrictInt + id: StrictStr + object: Optional[StrictStr] = 'model' + owned_by: StrictStr + pricing: Optional[ModelPricingInfo] = None + __properties: ClassVar[List[str]] = ["created", "id", "object", "owned_by", "pricing"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModelObject from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of pricing + if self.pricing: + _dict['pricing'] = self.pricing.to_dict() + # set to None if pricing (nullable) is None + # and model_fields_set contains the field + if self.pricing is None and "pricing" in self.model_fields_set: + _dict['pricing'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModelObject from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "created": obj.get("created"), + "id": obj.get("id"), + "object": obj.get("object") if obj.get("object") is not None else 'model', + "owned_by": obj.get("owned_by"), + "pricing": ModelPricingInfo.from_dict(obj["pricing"]) if obj.get("pricing") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/model_pricing_info.py b/src/otari/_client/models/model_pricing_info.py new file mode 100644 index 0000000..53b91c6 --- /dev/null +++ b/src/otari/_client/models/model_pricing_info.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt +from typing import Any, ClassVar, Dict, List, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModelPricingInfo(BaseModel): + """ + Pricing information for a model. + """ # noqa: E501 + input_price_per_million: Union[StrictFloat, StrictInt] + output_price_per_million: Union[StrictFloat, StrictInt] + __properties: ClassVar[List[str]] = ["input_price_per_million", "output_price_per_million"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModelPricingInfo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModelPricingInfo from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input_price_per_million": obj.get("input_price_per_million"), + "output_price_per_million": obj.get("output_price_per_million") + }) + return _obj + + diff --git a/src/otari/_client/models/moderation_request.py b/src/otari/_client/models/moderation_request.py new file mode 100644 index 0000000..f88e3e0 --- /dev/null +++ b/src/otari/_client/models/moderation_request.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.input1 import Input1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModerationRequest(BaseModel): + """ + OpenAI-compatible moderation request. + """ # noqa: E501 + input: Input1 + model: StrictStr + user: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["input", "model", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModerationRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of input + if self.input: + _dict['input'] = self.input.to_dict() + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModerationRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input": Input1.from_dict(obj["input"]) if obj.get("input") is not None else None, + "model": obj.get("model"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/moderation_response.py b/src/otari/_client/models/moderation_response.py new file mode 100644 index 0000000..1e1e198 --- /dev/null +++ b/src/otari/_client/models/moderation_response.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from otari._client.models.moderation_result import ModerationResult +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModerationResponse(BaseModel): + """ + Normalized moderation response across providers. + """ # noqa: E501 + id: StrictStr + model: StrictStr + results: List[ModerationResult] + __properties: ClassVar[List[str]] = ["id", "model", "results"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModerationResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict['results'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModerationResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "model": obj.get("model"), + "results": [ModerationResult.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/moderation_result.py b/src/otari/_client/models/moderation_result.py new file mode 100644 index 0000000..228785d --- /dev/null +++ b/src/otari/_client/models/moderation_result.py @@ -0,0 +1,106 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModerationResult(BaseModel): + """ + A single moderation decision, typically one per input item. + """ # noqa: E501 + categories: Optional[Dict[str, StrictBool]] = None + category_applied_input_types: Optional[Dict[str, List[StrictStr]]] = None + category_scores: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = None + flagged: StrictBool + provider_raw: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["categories", "category_applied_input_types", "category_scores", "flagged", "provider_raw"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ModerationResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if category_applied_input_types (nullable) is None + # and model_fields_set contains the field + if self.category_applied_input_types is None and "category_applied_input_types" in self.model_fields_set: + _dict['category_applied_input_types'] = None + + # set to None if provider_raw (nullable) is None + # and model_fields_set contains the field + if self.provider_raw is None and "provider_raw" in self.model_fields_set: + _dict['provider_raw'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModerationResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "categories": obj.get("categories"), + "category_applied_input_types": obj.get("category_applied_input_types"), + "category_scores": obj.get("category_scores"), + "flagged": obj.get("flagged"), + "provider_raw": obj.get("provider_raw") + }) + return _obj + + diff --git a/src/otari/_client/models/mr_base64_pdf_source.py b/src/otari/_client/models/mr_base64_pdf_source.py new file mode 100644 index 0000000..1a75703 --- /dev/null +++ b/src/otari/_client/models/mr_base64_pdf_source.py @@ -0,0 +1,119 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRBase64PDFSource(BaseModel): + """ + MRBase64PDFSource + """ # noqa: E501 + data: StrictStr + media_type: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["data", "media_type", "type"] + + @field_validator('media_type') + def media_type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['application/pdf']): + raise ValueError("must be one of enum values ('application/pdf')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['base64']): + raise ValueError("must be one of enum values ('base64')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRBase64PDFSource from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRBase64PDFSource from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": obj.get("data"), + "media_type": obj.get("media_type"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_bash_code_execution_output_block.py b/src/otari/_client/models/mr_bash_code_execution_output_block.py new file mode 100644 index 0000000..de705c2 --- /dev/null +++ b/src/otari/_client/models/mr_bash_code_execution_output_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRBashCodeExecutionOutputBlock(BaseModel): + """ + MRBashCodeExecutionOutputBlock + """ # noqa: E501 + file_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["file_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['bash_code_execution_output']): + raise ValueError("must be one of enum values ('bash_code_execution_output')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionOutputBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionOutputBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "file_id": obj.get("file_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_bash_code_execution_result_block.py b/src/otari/_client/models/mr_bash_code_execution_result_block.py new file mode 100644 index 0000000..6f0284e --- /dev/null +++ b/src/otari/_client/models/mr_bash_code_execution_result_block.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.mr_bash_code_execution_output_block import MRBashCodeExecutionOutputBlock +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRBashCodeExecutionResultBlock(BaseModel): + """ + MRBashCodeExecutionResultBlock + """ # noqa: E501 + content: List[MRBashCodeExecutionOutputBlock] + return_code: StrictInt + stderr: StrictStr + stdout: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "return_code", "stderr", "stdout", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['bash_code_execution_result']): + raise ValueError("must be one of enum values ('bash_code_execution_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": [MRBashCodeExecutionOutputBlock.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "return_code": obj.get("return_code"), + "stderr": obj.get("stderr"), + "stdout": obj.get("stdout"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_bash_code_execution_tool_result_block.py b/src/otari/_client/models/mr_bash_code_execution_tool_result_block.py new file mode 100644 index 0000000..2c81ae0 --- /dev/null +++ b/src/otari/_client/models/mr_bash_code_execution_tool_result_block.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.content3 import Content3 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRBashCodeExecutionToolResultBlock(BaseModel): + """ + MRBashCodeExecutionToolResultBlock + """ # noqa: E501 + content: Content3 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['bash_code_execution_tool_result']): + raise ValueError("must be one of enum values ('bash_code_execution_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content3.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_bash_code_execution_tool_result_error.py b/src/otari/_client/models/mr_bash_code_execution_tool_result_error.py new file mode 100644 index 0000000..1e778a3 --- /dev/null +++ b/src/otari/_client/models/mr_bash_code_execution_tool_result_error.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRBashCodeExecutionToolResultError(BaseModel): + """ + MRBashCodeExecutionToolResultError + """ # noqa: E501 + error_code: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded', 'output_file_too_large']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded', 'output_file_too_large')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['bash_code_execution_tool_result_error']): + raise ValueError("must be one of enum values ('bash_code_execution_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionToolResultError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRBashCodeExecutionToolResultError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_cache_creation.py b/src/otari/_client/models/mr_cache_creation.py new file mode 100644 index 0000000..72cf31a --- /dev/null +++ b/src/otari/_client/models/mr_cache_creation.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCacheCreation(BaseModel): + """ + MRCacheCreation + """ # noqa: E501 + ephemeral_1h_input_tokens: StrictInt + ephemeral_5m_input_tokens: StrictInt + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["ephemeral_1h_input_tokens", "ephemeral_5m_input_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCacheCreation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCacheCreation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "ephemeral_1h_input_tokens": obj.get("ephemeral_1h_input_tokens"), + "ephemeral_5m_input_tokens": obj.get("ephemeral_5m_input_tokens") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citation_char_location.py b/src/otari/_client/models/mr_citation_char_location.py new file mode 100644 index 0000000..e89c000 --- /dev/null +++ b/src/otari/_client/models/mr_citation_char_location.py @@ -0,0 +1,130 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationCharLocation(BaseModel): + """ + MRCitationCharLocation + """ # noqa: E501 + cited_text: StrictStr + document_index: StrictInt + document_title: Optional[StrictStr] = None + end_char_index: StrictInt + file_id: Optional[StrictStr] = None + start_char_index: StrictInt + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cited_text", "document_index", "document_title", "end_char_index", "file_id", "start_char_index", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['char_location']): + raise ValueError("must be one of enum values ('char_location')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationCharLocation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if document_title (nullable) is None + # and model_fields_set contains the field + if self.document_title is None and "document_title" in self.model_fields_set: + _dict['document_title'] = None + + # set to None if file_id (nullable) is None + # and model_fields_set contains the field + if self.file_id is None and "file_id" in self.model_fields_set: + _dict['file_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationCharLocation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cited_text": obj.get("cited_text"), + "document_index": obj.get("document_index"), + "document_title": obj.get("document_title"), + "end_char_index": obj.get("end_char_index"), + "file_id": obj.get("file_id"), + "start_char_index": obj.get("start_char_index"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citation_content_block_location.py b/src/otari/_client/models/mr_citation_content_block_location.py new file mode 100644 index 0000000..44eb0ef --- /dev/null +++ b/src/otari/_client/models/mr_citation_content_block_location.py @@ -0,0 +1,130 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationContentBlockLocation(BaseModel): + """ + MRCitationContentBlockLocation + """ # noqa: E501 + cited_text: StrictStr + document_index: StrictInt + document_title: Optional[StrictStr] = None + end_block_index: StrictInt + file_id: Optional[StrictStr] = None + start_block_index: StrictInt + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cited_text", "document_index", "document_title", "end_block_index", "file_id", "start_block_index", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['content_block_location']): + raise ValueError("must be one of enum values ('content_block_location')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationContentBlockLocation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if document_title (nullable) is None + # and model_fields_set contains the field + if self.document_title is None and "document_title" in self.model_fields_set: + _dict['document_title'] = None + + # set to None if file_id (nullable) is None + # and model_fields_set contains the field + if self.file_id is None and "file_id" in self.model_fields_set: + _dict['file_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationContentBlockLocation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cited_text": obj.get("cited_text"), + "document_index": obj.get("document_index"), + "document_title": obj.get("document_title"), + "end_block_index": obj.get("end_block_index"), + "file_id": obj.get("file_id"), + "start_block_index": obj.get("start_block_index"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citation_page_location.py b/src/otari/_client/models/mr_citation_page_location.py new file mode 100644 index 0000000..f25af13 --- /dev/null +++ b/src/otari/_client/models/mr_citation_page_location.py @@ -0,0 +1,130 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationPageLocation(BaseModel): + """ + MRCitationPageLocation + """ # noqa: E501 + cited_text: StrictStr + document_index: StrictInt + document_title: Optional[StrictStr] = None + end_page_number: StrictInt + file_id: Optional[StrictStr] = None + start_page_number: StrictInt + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cited_text", "document_index", "document_title", "end_page_number", "file_id", "start_page_number", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['page_location']): + raise ValueError("must be one of enum values ('page_location')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationPageLocation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if document_title (nullable) is None + # and model_fields_set contains the field + if self.document_title is None and "document_title" in self.model_fields_set: + _dict['document_title'] = None + + # set to None if file_id (nullable) is None + # and model_fields_set contains the field + if self.file_id is None and "file_id" in self.model_fields_set: + _dict['file_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationPageLocation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cited_text": obj.get("cited_text"), + "document_index": obj.get("document_index"), + "document_title": obj.get("document_title"), + "end_page_number": obj.get("end_page_number"), + "file_id": obj.get("file_id"), + "start_page_number": obj.get("start_page_number"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citations_config.py b/src/otari/_client/models/mr_citations_config.py new file mode 100644 index 0000000..d28a098 --- /dev/null +++ b/src/otari/_client/models/mr_citations_config.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationsConfig(BaseModel): + """ + MRCitationsConfig + """ # noqa: E501 + enabled: StrictBool + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["enabled"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationsConfig from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationsConfig from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "enabled": obj.get("enabled") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citations_search_result_location.py b/src/otari/_client/models/mr_citations_search_result_location.py new file mode 100644 index 0000000..d4c7b24 --- /dev/null +++ b/src/otari/_client/models/mr_citations_search_result_location.py @@ -0,0 +1,125 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationsSearchResultLocation(BaseModel): + """ + MRCitationsSearchResultLocation + """ # noqa: E501 + cited_text: StrictStr + end_block_index: StrictInt + search_result_index: StrictInt + source: StrictStr + start_block_index: StrictInt + title: Optional[StrictStr] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cited_text", "end_block_index", "search_result_index", "source", "start_block_index", "title", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['search_result_location']): + raise ValueError("must be one of enum values ('search_result_location')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationsSearchResultLocation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if title (nullable) is None + # and model_fields_set contains the field + if self.title is None and "title" in self.model_fields_set: + _dict['title'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationsSearchResultLocation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cited_text": obj.get("cited_text"), + "end_block_index": obj.get("end_block_index"), + "search_result_index": obj.get("search_result_index"), + "source": obj.get("source"), + "start_block_index": obj.get("start_block_index"), + "title": obj.get("title"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_citations_web_search_result_location.py b/src/otari/_client/models/mr_citations_web_search_result_location.py new file mode 100644 index 0000000..0cac01d --- /dev/null +++ b/src/otari/_client/models/mr_citations_web_search_result_location.py @@ -0,0 +1,121 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCitationsWebSearchResultLocation(BaseModel): + """ + MRCitationsWebSearchResultLocation + """ # noqa: E501 + cited_text: StrictStr + encrypted_index: StrictStr + title: Optional[StrictStr] = None + type: StrictStr + url: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cited_text", "encrypted_index", "title", "type", "url"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search_result_location']): + raise ValueError("must be one of enum values ('web_search_result_location')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCitationsWebSearchResultLocation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if title (nullable) is None + # and model_fields_set contains the field + if self.title is None and "title" in self.model_fields_set: + _dict['title'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCitationsWebSearchResultLocation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cited_text": obj.get("cited_text"), + "encrypted_index": obj.get("encrypted_index"), + "title": obj.get("title"), + "type": obj.get("type"), + "url": obj.get("url") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_code_execution_output_block.py b/src/otari/_client/models/mr_code_execution_output_block.py new file mode 100644 index 0000000..f7ec443 --- /dev/null +++ b/src/otari/_client/models/mr_code_execution_output_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCodeExecutionOutputBlock(BaseModel): + """ + MRCodeExecutionOutputBlock + """ # noqa: E501 + file_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["file_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_output']): + raise ValueError("must be one of enum values ('code_execution_output')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCodeExecutionOutputBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCodeExecutionOutputBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "file_id": obj.get("file_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_code_execution_result_block.py b/src/otari/_client/models/mr_code_execution_result_block.py new file mode 100644 index 0000000..d806e2a --- /dev/null +++ b/src/otari/_client/models/mr_code_execution_result_block.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.mr_code_execution_output_block import MRCodeExecutionOutputBlock +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCodeExecutionResultBlock(BaseModel): + """ + MRCodeExecutionResultBlock + """ # noqa: E501 + content: List[MRCodeExecutionOutputBlock] + return_code: StrictInt + stderr: StrictStr + stdout: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "return_code", "stderr", "stdout", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_result']): + raise ValueError("must be one of enum values ('code_execution_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCodeExecutionResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCodeExecutionResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": [MRCodeExecutionOutputBlock.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "return_code": obj.get("return_code"), + "stderr": obj.get("stderr"), + "stdout": obj.get("stdout"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_code_execution_tool_result_block.py b/src/otari/_client/models/mr_code_execution_tool_result_block.py new file mode 100644 index 0000000..4425e2c --- /dev/null +++ b/src/otari/_client/models/mr_code_execution_tool_result_block.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.content4 import Content4 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCodeExecutionToolResultBlock(BaseModel): + """ + MRCodeExecutionToolResultBlock + """ # noqa: E501 + content: Content4 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_tool_result']): + raise ValueError("must be one of enum values ('code_execution_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCodeExecutionToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCodeExecutionToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content4.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_code_execution_tool_result_error.py b/src/otari/_client/models/mr_code_execution_tool_result_error.py new file mode 100644 index 0000000..9607d88 --- /dev/null +++ b/src/otari/_client/models/mr_code_execution_tool_result_error.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRCodeExecutionToolResultError(BaseModel): + """ + MRCodeExecutionToolResultError + """ # noqa: E501 + error_code: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_tool_result_error']): + raise ValueError("must be one of enum values ('code_execution_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRCodeExecutionToolResultError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRCodeExecutionToolResultError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_container.py b/src/otari/_client/models/mr_container.py new file mode 100644 index 0000000..f6138a1 --- /dev/null +++ b/src/otari/_client/models/mr_container.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRContainer(BaseModel): + """ + Information about the container used in the request (for the code execution tool) + """ # noqa: E501 + id: StrictStr + expires_at: datetime + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "expires_at"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRContainer from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRContainer from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "expires_at": obj.get("expires_at") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_container_upload_block.py b/src/otari/_client/models/mr_container_upload_block.py new file mode 100644 index 0000000..71c88b7 --- /dev/null +++ b/src/otari/_client/models/mr_container_upload_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRContainerUploadBlock(BaseModel): + """ + Response model for a file uploaded to the container. + """ # noqa: E501 + file_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["file_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['container_upload']): + raise ValueError("must be one of enum values ('container_upload')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRContainerUploadBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRContainerUploadBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "file_id": obj.get("file_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_direct_caller.py b/src/otari/_client/models/mr_direct_caller.py new file mode 100644 index 0000000..89402a7 --- /dev/null +++ b/src/otari/_client/models/mr_direct_caller.py @@ -0,0 +1,108 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRDirectCaller(BaseModel): + """ + Tool invocation directly from the model. + """ # noqa: E501 + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['direct']): + raise ValueError("must be one of enum values ('direct')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRDirectCaller from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRDirectCaller from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_document_block.py b/src/otari/_client/models/mr_document_block.py new file mode 100644 index 0000000..659ffe3 --- /dev/null +++ b/src/otari/_client/models/mr_document_block.py @@ -0,0 +1,132 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.mr_citations_config import MRCitationsConfig +from otari._client.models.source import Source +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRDocumentBlock(BaseModel): + """ + MRDocumentBlock + """ # noqa: E501 + citations: Optional[MRCitationsConfig] = None + source: Source + title: Optional[StrictStr] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["citations", "source", "title", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['document']): + raise ValueError("must be one of enum values ('document')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRDocumentBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of citations + if self.citations: + _dict['citations'] = self.citations.to_dict() + # override the default output from pydantic by calling `to_dict()` of source + if self.source: + _dict['source'] = self.source.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if citations (nullable) is None + # and model_fields_set contains the field + if self.citations is None and "citations" in self.model_fields_set: + _dict['citations'] = None + + # set to None if title (nullable) is None + # and model_fields_set contains the field + if self.title is None and "title" in self.model_fields_set: + _dict['title'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRDocumentBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "citations": MRCitationsConfig.from_dict(obj["citations"]) if obj.get("citations") is not None else None, + "source": Source.from_dict(obj["source"]) if obj.get("source") is not None else None, + "title": obj.get("title"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_encrypted_code_execution_result_block.py b/src/otari/_client/models/mr_encrypted_code_execution_result_block.py new file mode 100644 index 0000000..3b19632 --- /dev/null +++ b/src/otari/_client/models/mr_encrypted_code_execution_result_block.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.mr_code_execution_output_block import MRCodeExecutionOutputBlock +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MREncryptedCodeExecutionResultBlock(BaseModel): + """ + Code execution result with encrypted stdout for PFC + web_search results. + """ # noqa: E501 + content: List[MRCodeExecutionOutputBlock] + encrypted_stdout: StrictStr + return_code: StrictInt + stderr: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "encrypted_stdout", "return_code", "stderr", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['encrypted_code_execution_result']): + raise ValueError("must be one of enum values ('encrypted_code_execution_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MREncryptedCodeExecutionResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in content (list) + _items = [] + if self.content: + for _item_content in self.content: + if _item_content: + _items.append(_item_content.to_dict()) + _dict['content'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MREncryptedCodeExecutionResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": [MRCodeExecutionOutputBlock.from_dict(_item) for _item in obj["content"]] if obj.get("content") is not None else None, + "encrypted_stdout": obj.get("encrypted_stdout"), + "return_code": obj.get("return_code"), + "stderr": obj.get("stderr"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_plain_text_source.py b/src/otari/_client/models/mr_plain_text_source.py new file mode 100644 index 0000000..0f8c0cf --- /dev/null +++ b/src/otari/_client/models/mr_plain_text_source.py @@ -0,0 +1,119 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRPlainTextSource(BaseModel): + """ + MRPlainTextSource + """ # noqa: E501 + data: StrictStr + media_type: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["data", "media_type", "type"] + + @field_validator('media_type') + def media_type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text/plain']): + raise ValueError("must be one of enum values ('text/plain')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text']): + raise ValueError("must be one of enum values ('text')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRPlainTextSource from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRPlainTextSource from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": obj.get("data"), + "media_type": obj.get("media_type"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_redacted_thinking_block.py b/src/otari/_client/models/mr_redacted_thinking_block.py new file mode 100644 index 0000000..d7f9321 --- /dev/null +++ b/src/otari/_client/models/mr_redacted_thinking_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRRedactedThinkingBlock(BaseModel): + """ + MRRedactedThinkingBlock + """ # noqa: E501 + data: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["data", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['redacted_thinking']): + raise ValueError("must be one of enum values ('redacted_thinking')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRRedactedThinkingBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRRedactedThinkingBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": obj.get("data"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_refusal_stop_details.py b/src/otari/_client/models/mr_refusal_stop_details.py new file mode 100644 index 0000000..aa50caf --- /dev/null +++ b/src/otari/_client/models/mr_refusal_stop_details.py @@ -0,0 +1,132 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRRefusalStopDetails(BaseModel): + """ + Structured information about a refusal. + """ # noqa: E501 + category: Optional[StrictStr] = None + explanation: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["category", "explanation", "type"] + + @field_validator('category') + def category_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['cyber', 'bio']): + raise ValueError("must be one of enum values ('cyber', 'bio')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['refusal']): + raise ValueError("must be one of enum values ('refusal')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRRefusalStopDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if category (nullable) is None + # and model_fields_set contains the field + if self.category is None and "category" in self.model_fields_set: + _dict['category'] = None + + # set to None if explanation (nullable) is None + # and model_fields_set contains the field + if self.explanation is None and "explanation" in self.model_fields_set: + _dict['explanation'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRRefusalStopDetails from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "category": obj.get("category"), + "explanation": obj.get("explanation"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_server_tool_caller.py b/src/otari/_client/models/mr_server_tool_caller.py new file mode 100644 index 0000000..7d7c1c2 --- /dev/null +++ b/src/otari/_client/models/mr_server_tool_caller.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRServerToolCaller(BaseModel): + """ + Tool invocation generated by a server-side tool. + """ # noqa: E501 + tool_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["tool_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_20250825']): + raise ValueError("must be one of enum values ('code_execution_20250825')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRServerToolCaller from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRServerToolCaller from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "tool_id": obj.get("tool_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_server_tool_caller20260120.py b/src/otari/_client/models/mr_server_tool_caller20260120.py new file mode 100644 index 0000000..32cefc1 --- /dev/null +++ b/src/otari/_client/models/mr_server_tool_caller20260120.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRServerToolCaller20260120(BaseModel): + """ + MRServerToolCaller20260120 + """ # noqa: E501 + tool_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["tool_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['code_execution_20260120']): + raise ValueError("must be one of enum values ('code_execution_20260120')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRServerToolCaller20260120 from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRServerToolCaller20260120 from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "tool_id": obj.get("tool_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_server_tool_usage.py b/src/otari/_client/models/mr_server_tool_usage.py new file mode 100644 index 0000000..33e9b68 --- /dev/null +++ b/src/otari/_client/models/mr_server_tool_usage.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRServerToolUsage(BaseModel): + """ + MRServerToolUsage + """ # noqa: E501 + web_fetch_requests: StrictInt + web_search_requests: StrictInt + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["web_fetch_requests", "web_search_requests"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRServerToolUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRServerToolUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "web_fetch_requests": obj.get("web_fetch_requests"), + "web_search_requests": obj.get("web_search_requests") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_server_tool_use_block.py b/src/otari/_client/models/mr_server_tool_use_block.py new file mode 100644 index 0000000..85e3bb8 --- /dev/null +++ b/src/otari/_client/models/mr_server_tool_use_block.py @@ -0,0 +1,132 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.caller import Caller +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRServerToolUseBlock(BaseModel): + """ + MRServerToolUseBlock + """ # noqa: E501 + id: StrictStr + caller: Optional[Caller] = None + input: Dict[str, Any] + name: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "caller", "input", "name", "type"] + + @field_validator('name') + def name_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search', 'web_fetch', 'code_execution', 'bash_code_execution', 'text_editor_code_execution', 'tool_search_tool_regex', 'tool_search_tool_bm25']): + raise ValueError("must be one of enum values ('web_search', 'web_fetch', 'code_execution', 'bash_code_execution', 'text_editor_code_execution', 'tool_search_tool_regex', 'tool_search_tool_bm25')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['server_tool_use']): + raise ValueError("must be one of enum values ('server_tool_use')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRServerToolUseBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of caller + if self.caller: + _dict['caller'] = self.caller.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if caller (nullable) is None + # and model_fields_set contains the field + if self.caller is None and "caller" in self.model_fields_set: + _dict['caller'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRServerToolUseBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "caller": Caller.from_dict(obj["caller"]) if obj.get("caller") is not None else None, + "input": obj.get("input"), + "name": obj.get("name"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_block.py b/src/otari/_client/models/mr_text_block.py new file mode 100644 index 0000000..68f23d3 --- /dev/null +++ b/src/otari/_client/models/mr_text_block.py @@ -0,0 +1,125 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.mr_text_block_citations_inner import MRTextBlockCitationsInner +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextBlock(BaseModel): + """ + MRTextBlock + """ # noqa: E501 + citations: Optional[List[MRTextBlockCitationsInner]] = None + text: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["citations", "text", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text']): + raise ValueError("must be one of enum values ('text')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in citations (list) + _items = [] + if self.citations: + for _item_citations in self.citations: + if _item_citations: + _items.append(_item_citations.to_dict()) + _dict['citations'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if citations (nullable) is None + # and model_fields_set contains the field + if self.citations is None and "citations" in self.model_fields_set: + _dict['citations'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "citations": [MRTextBlockCitationsInner.from_dict(_item) for _item in obj["citations"]] if obj.get("citations") is not None else None, + "text": obj.get("text"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_block_citations_inner.py b/src/otari/_client/models/mr_text_block_citations_inner.py new file mode 100644 index 0000000..0f9c048 --- /dev/null +++ b/src/otari/_client/models/mr_text_block_citations_inner.py @@ -0,0 +1,179 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_citation_char_location import MRCitationCharLocation +from otari._client.models.mr_citation_content_block_location import MRCitationContentBlockLocation +from otari._client.models.mr_citation_page_location import MRCitationPageLocation +from otari._client.models.mr_citations_search_result_location import MRCitationsSearchResultLocation +from otari._client.models.mr_citations_web_search_result_location import MRCitationsWebSearchResultLocation +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +MRTEXTBLOCKCITATIONSINNER_ANY_OF_SCHEMAS = ["MRCitationCharLocation", "MRCitationContentBlockLocation", "MRCitationPageLocation", "MRCitationsSearchResultLocation", "MRCitationsWebSearchResultLocation"] + +class MRTextBlockCitationsInner(BaseModel): + """ + MRTextBlockCitationsInner + """ + + # data type: MRCitationCharLocation + anyof_schema_1_validator: Optional[MRCitationCharLocation] = None + # data type: MRCitationPageLocation + anyof_schema_2_validator: Optional[MRCitationPageLocation] = None + # data type: MRCitationContentBlockLocation + anyof_schema_3_validator: Optional[MRCitationContentBlockLocation] = None + # data type: MRCitationsWebSearchResultLocation + anyof_schema_4_validator: Optional[MRCitationsWebSearchResultLocation] = None + # data type: MRCitationsSearchResultLocation + anyof_schema_5_validator: Optional[MRCitationsSearchResultLocation] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRCitationCharLocation, MRCitationContentBlockLocation, MRCitationPageLocation, MRCitationsSearchResultLocation, MRCitationsWebSearchResultLocation]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRCitationCharLocation", "MRCitationContentBlockLocation", "MRCitationPageLocation", "MRCitationsSearchResultLocation", "MRCitationsWebSearchResultLocation" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = MRTextBlockCitationsInner.model_construct() + error_messages = [] + # validate data type: MRCitationCharLocation + if not isinstance(v, MRCitationCharLocation): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCitationCharLocation`") + else: + return v + + # validate data type: MRCitationPageLocation + if not isinstance(v, MRCitationPageLocation): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCitationPageLocation`") + else: + return v + + # validate data type: MRCitationContentBlockLocation + if not isinstance(v, MRCitationContentBlockLocation): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCitationContentBlockLocation`") + else: + return v + + # validate data type: MRCitationsWebSearchResultLocation + if not isinstance(v, MRCitationsWebSearchResultLocation): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCitationsWebSearchResultLocation`") + else: + return v + + # validate data type: MRCitationsSearchResultLocation + if not isinstance(v, MRCitationsSearchResultLocation): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRCitationsSearchResultLocation`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in MRTextBlockCitationsInner with anyOf schemas: MRCitationCharLocation, MRCitationContentBlockLocation, MRCitationPageLocation, MRCitationsSearchResultLocation, MRCitationsWebSearchResultLocation. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRCitationCharLocation] = None + try: + instance.actual_instance = MRCitationCharLocation.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRCitationPageLocation] = None + try: + instance.actual_instance = MRCitationPageLocation.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MRCitationContentBlockLocation] = None + try: + instance.actual_instance = MRCitationContentBlockLocation.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MRCitationsWebSearchResultLocation] = None + try: + instance.actual_instance = MRCitationsWebSearchResultLocation.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_5_validator: Optional[MRCitationsSearchResultLocation] = None + try: + instance.actual_instance = MRCitationsSearchResultLocation.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into MRTextBlockCitationsInner with anyOf schemas: MRCitationCharLocation, MRCitationContentBlockLocation, MRCitationPageLocation, MRCitationsSearchResultLocation, MRCitationsWebSearchResultLocation. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRCitationCharLocation, MRCitationContentBlockLocation, MRCitationPageLocation, MRCitationsSearchResultLocation, MRCitationsWebSearchResultLocation]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/mr_text_editor_code_execution_create_result_block.py b/src/otari/_client/models/mr_text_editor_code_execution_create_result_block.py new file mode 100644 index 0000000..aff6721 --- /dev/null +++ b/src/otari/_client/models/mr_text_editor_code_execution_create_result_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextEditorCodeExecutionCreateResultBlock(BaseModel): + """ + MRTextEditorCodeExecutionCreateResultBlock + """ # noqa: E501 + is_file_update: StrictBool + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["is_file_update", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text_editor_code_execution_create_result']): + raise ValueError("must be one of enum values ('text_editor_code_execution_create_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionCreateResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionCreateResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "is_file_update": obj.get("is_file_update"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_editor_code_execution_str_replace_result_block.py b/src/otari/_client/models/mr_text_editor_code_execution_str_replace_result_block.py new file mode 100644 index 0000000..c87747a --- /dev/null +++ b/src/otari/_client/models/mr_text_editor_code_execution_str_replace_result_block.py @@ -0,0 +1,143 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextEditorCodeExecutionStrReplaceResultBlock(BaseModel): + """ + MRTextEditorCodeExecutionStrReplaceResultBlock + """ # noqa: E501 + lines: Optional[List[StrictStr]] = None + new_lines: Optional[StrictInt] = None + new_start: Optional[StrictInt] = None + old_lines: Optional[StrictInt] = None + old_start: Optional[StrictInt] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["lines", "new_lines", "new_start", "old_lines", "old_start", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text_editor_code_execution_str_replace_result']): + raise ValueError("must be one of enum values ('text_editor_code_execution_str_replace_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionStrReplaceResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if lines (nullable) is None + # and model_fields_set contains the field + if self.lines is None and "lines" in self.model_fields_set: + _dict['lines'] = None + + # set to None if new_lines (nullable) is None + # and model_fields_set contains the field + if self.new_lines is None and "new_lines" in self.model_fields_set: + _dict['new_lines'] = None + + # set to None if new_start (nullable) is None + # and model_fields_set contains the field + if self.new_start is None and "new_start" in self.model_fields_set: + _dict['new_start'] = None + + # set to None if old_lines (nullable) is None + # and model_fields_set contains the field + if self.old_lines is None and "old_lines" in self.model_fields_set: + _dict['old_lines'] = None + + # set to None if old_start (nullable) is None + # and model_fields_set contains the field + if self.old_start is None and "old_start" in self.model_fields_set: + _dict['old_start'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionStrReplaceResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "lines": obj.get("lines"), + "new_lines": obj.get("new_lines"), + "new_start": obj.get("new_start"), + "old_lines": obj.get("old_lines"), + "old_start": obj.get("old_start"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_editor_code_execution_tool_result_block.py b/src/otari/_client/models/mr_text_editor_code_execution_tool_result_block.py new file mode 100644 index 0000000..df4a3b9 --- /dev/null +++ b/src/otari/_client/models/mr_text_editor_code_execution_tool_result_block.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.content5 import Content5 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextEditorCodeExecutionToolResultBlock(BaseModel): + """ + MRTextEditorCodeExecutionToolResultBlock + """ # noqa: E501 + content: Content5 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text_editor_code_execution_tool_result']): + raise ValueError("must be one of enum values ('text_editor_code_execution_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content5.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_editor_code_execution_tool_result_error.py b/src/otari/_client/models/mr_text_editor_code_execution_tool_result_error.py new file mode 100644 index 0000000..835e761 --- /dev/null +++ b/src/otari/_client/models/mr_text_editor_code_execution_tool_result_error.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextEditorCodeExecutionToolResultError(BaseModel): + """ + MRTextEditorCodeExecutionToolResultError + """ # noqa: E501 + error_code: StrictStr + error_message: Optional[StrictStr] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "error_message", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded', 'file_not_found']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded', 'file_not_found')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text_editor_code_execution_tool_result_error']): + raise ValueError("must be one of enum values ('text_editor_code_execution_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionToolResultError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict['error_message'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionToolResultError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "error_message": obj.get("error_message"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_text_editor_code_execution_view_result_block.py b/src/otari/_client/models/mr_text_editor_code_execution_view_result_block.py new file mode 100644 index 0000000..cb3dfa1 --- /dev/null +++ b/src/otari/_client/models/mr_text_editor_code_execution_view_result_block.py @@ -0,0 +1,140 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRTextEditorCodeExecutionViewResultBlock(BaseModel): + """ + MRTextEditorCodeExecutionViewResultBlock + """ # noqa: E501 + content: StrictStr + file_type: StrictStr + num_lines: Optional[StrictInt] = None + start_line: Optional[StrictInt] = None + total_lines: Optional[StrictInt] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "file_type", "num_lines", "start_line", "total_lines", "type"] + + @field_validator('file_type') + def file_type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text', 'image', 'pdf']): + raise ValueError("must be one of enum values ('text', 'image', 'pdf')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text_editor_code_execution_view_result']): + raise ValueError("must be one of enum values ('text_editor_code_execution_view_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionViewResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if num_lines (nullable) is None + # and model_fields_set contains the field + if self.num_lines is None and "num_lines" in self.model_fields_set: + _dict['num_lines'] = None + + # set to None if start_line (nullable) is None + # and model_fields_set contains the field + if self.start_line is None and "start_line" in self.model_fields_set: + _dict['start_line'] = None + + # set to None if total_lines (nullable) is None + # and model_fields_set contains the field + if self.total_lines is None and "total_lines" in self.model_fields_set: + _dict['total_lines'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRTextEditorCodeExecutionViewResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content"), + "file_type": obj.get("file_type"), + "num_lines": obj.get("num_lines"), + "start_line": obj.get("start_line"), + "total_lines": obj.get("total_lines"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_thinking_block.py b/src/otari/_client/models/mr_thinking_block.py new file mode 100644 index 0000000..a0596bd --- /dev/null +++ b/src/otari/_client/models/mr_thinking_block.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRThinkingBlock(BaseModel): + """ + MRThinkingBlock + """ # noqa: E501 + signature: StrictStr + thinking: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["signature", "thinking", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['thinking']): + raise ValueError("must be one of enum values ('thinking')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRThinkingBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRThinkingBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "signature": obj.get("signature"), + "thinking": obj.get("thinking"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_tool_reference_block.py b/src/otari/_client/models/mr_tool_reference_block.py new file mode 100644 index 0000000..0f9190c --- /dev/null +++ b/src/otari/_client/models/mr_tool_reference_block.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRToolReferenceBlock(BaseModel): + """ + MRToolReferenceBlock + """ # noqa: E501 + tool_name: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["tool_name", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool_reference']): + raise ValueError("must be one of enum values ('tool_reference')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRToolReferenceBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRToolReferenceBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "tool_name": obj.get("tool_name"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_tool_search_tool_result_block.py b/src/otari/_client/models/mr_tool_search_tool_result_block.py new file mode 100644 index 0000000..ba42f16 --- /dev/null +++ b/src/otari/_client/models/mr_tool_search_tool_result_block.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.content6 import Content6 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRToolSearchToolResultBlock(BaseModel): + """ + MRToolSearchToolResultBlock + """ # noqa: E501 + content: Content6 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool_search_tool_result']): + raise ValueError("must be one of enum values ('tool_search_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRToolSearchToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRToolSearchToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content6.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_tool_search_tool_result_error.py b/src/otari/_client/models/mr_tool_search_tool_result_error.py new file mode 100644 index 0000000..9d456e6 --- /dev/null +++ b/src/otari/_client/models/mr_tool_search_tool_result_error.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRToolSearchToolResultError(BaseModel): + """ + MRToolSearchToolResultError + """ # noqa: E501 + error_code: StrictStr + error_message: Optional[StrictStr] = None + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "error_message", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'unavailable', 'too_many_requests', 'execution_time_exceeded')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool_search_tool_result_error']): + raise ValueError("must be one of enum values ('tool_search_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRToolSearchToolResultError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict['error_message'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRToolSearchToolResultError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "error_message": obj.get("error_message"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_tool_search_tool_search_result_block.py b/src/otari/_client/models/mr_tool_search_tool_search_result_block.py new file mode 100644 index 0000000..7e6ec0d --- /dev/null +++ b/src/otari/_client/models/mr_tool_search_tool_search_result_block.py @@ -0,0 +1,118 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.mr_tool_reference_block import MRToolReferenceBlock +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRToolSearchToolSearchResultBlock(BaseModel): + """ + MRToolSearchToolSearchResultBlock + """ # noqa: E501 + tool_references: List[MRToolReferenceBlock] + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["tool_references", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool_search_tool_search_result']): + raise ValueError("must be one of enum values ('tool_search_tool_search_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRToolSearchToolSearchResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in tool_references (list) + _items = [] + if self.tool_references: + for _item_tool_references in self.tool_references: + if _item_tool_references: + _items.append(_item_tool_references.to_dict()) + _dict['tool_references'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRToolSearchToolSearchResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "tool_references": [MRToolReferenceBlock.from_dict(_item) for _item in obj["tool_references"]] if obj.get("tool_references") is not None else None, + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_tool_use_block.py b/src/otari/_client/models/mr_tool_use_block.py new file mode 100644 index 0000000..f291389 --- /dev/null +++ b/src/otari/_client/models/mr_tool_use_block.py @@ -0,0 +1,125 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.caller import Caller +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRToolUseBlock(BaseModel): + """ + MRToolUseBlock + """ # noqa: E501 + id: StrictStr + caller: Optional[Caller] = None + input: Dict[str, Any] + name: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "caller", "input", "name", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool_use']): + raise ValueError("must be one of enum values ('tool_use')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRToolUseBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of caller + if self.caller: + _dict['caller'] = self.caller.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if caller (nullable) is None + # and model_fields_set contains the field + if self.caller is None and "caller" in self.model_fields_set: + _dict['caller'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRToolUseBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "caller": Caller.from_dict(obj["caller"]) if obj.get("caller") is not None else None, + "input": obj.get("input"), + "name": obj.get("name"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_usage.py b/src/otari/_client/models/mr_usage.py new file mode 100644 index 0000000..d9f799c --- /dev/null +++ b/src/otari/_client/models/mr_usage.py @@ -0,0 +1,163 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.mr_cache_creation import MRCacheCreation +from otari._client.models.mr_server_tool_usage import MRServerToolUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRUsage(BaseModel): + """ + MRUsage + """ # noqa: E501 + cache_creation: Optional[MRCacheCreation] = None + cache_creation_input_tokens: Optional[StrictInt] = None + cache_read_input_tokens: Optional[StrictInt] = None + inference_geo: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + input_tokens: StrictInt + output_tokens: StrictInt + server_tool_use: Optional[MRServerToolUsage] = None + service_tier: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cache_creation", "cache_creation_input_tokens", "cache_read_input_tokens", "inference_geo", "input_tokens", "output_tokens", "server_tool_use", "service_tier"] + + @field_validator('service_tier') + def service_tier_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['standard', 'priority', 'batch']): + raise ValueError("must be one of enum values ('standard', 'priority', 'batch')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of cache_creation + if self.cache_creation: + _dict['cache_creation'] = self.cache_creation.to_dict() + # override the default output from pydantic by calling `to_dict()` of server_tool_use + if self.server_tool_use: + _dict['server_tool_use'] = self.server_tool_use.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if cache_creation (nullable) is None + # and model_fields_set contains the field + if self.cache_creation is None and "cache_creation" in self.model_fields_set: + _dict['cache_creation'] = None + + # set to None if cache_creation_input_tokens (nullable) is None + # and model_fields_set contains the field + if self.cache_creation_input_tokens is None and "cache_creation_input_tokens" in self.model_fields_set: + _dict['cache_creation_input_tokens'] = None + + # set to None if cache_read_input_tokens (nullable) is None + # and model_fields_set contains the field + if self.cache_read_input_tokens is None and "cache_read_input_tokens" in self.model_fields_set: + _dict['cache_read_input_tokens'] = None + + # set to None if inference_geo (nullable) is None + # and model_fields_set contains the field + if self.inference_geo is None and "inference_geo" in self.model_fields_set: + _dict['inference_geo'] = None + + # set to None if server_tool_use (nullable) is None + # and model_fields_set contains the field + if self.server_tool_use is None and "server_tool_use" in self.model_fields_set: + _dict['server_tool_use'] = None + + # set to None if service_tier (nullable) is None + # and model_fields_set contains the field + if self.service_tier is None and "service_tier" in self.model_fields_set: + _dict['service_tier'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cache_creation": MRCacheCreation.from_dict(obj["cache_creation"]) if obj.get("cache_creation") is not None else None, + "cache_creation_input_tokens": obj.get("cache_creation_input_tokens"), + "cache_read_input_tokens": obj.get("cache_read_input_tokens"), + "inference_geo": obj.get("inference_geo"), + "input_tokens": obj.get("input_tokens"), + "output_tokens": obj.get("output_tokens"), + "server_tool_use": MRServerToolUsage.from_dict(obj["server_tool_use"]) if obj.get("server_tool_use") is not None else None, + "service_tier": obj.get("service_tier") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_fetch_block.py b/src/otari/_client/models/mr_web_fetch_block.py new file mode 100644 index 0000000..9008b44 --- /dev/null +++ b/src/otari/_client/models/mr_web_fetch_block.py @@ -0,0 +1,123 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.mr_document_block import MRDocumentBlock +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebFetchBlock(BaseModel): + """ + MRWebFetchBlock + """ # noqa: E501 + content: MRDocumentBlock + retrieved_at: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + type: StrictStr + url: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["content", "retrieved_at", "type", "url"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_fetch_result']): + raise ValueError("must be one of enum values ('web_fetch_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebFetchBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if retrieved_at (nullable) is None + # and model_fields_set contains the field + if self.retrieved_at is None and "retrieved_at" in self.model_fields_set: + _dict['retrieved_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebFetchBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": MRDocumentBlock.from_dict(obj["content"]) if obj.get("content") is not None else None, + "retrieved_at": obj.get("retrieved_at"), + "type": obj.get("type"), + "url": obj.get("url") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_fetch_tool_result_block.py b/src/otari/_client/models/mr_web_fetch_tool_result_block.py new file mode 100644 index 0000000..be167d8 --- /dev/null +++ b/src/otari/_client/models/mr_web_fetch_tool_result_block.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.caller import Caller +from otari._client.models.content7 import Content7 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebFetchToolResultBlock(BaseModel): + """ + MRWebFetchToolResultBlock + """ # noqa: E501 + caller: Optional[Caller] = None + content: Content7 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["caller", "content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_fetch_tool_result']): + raise ValueError("must be one of enum values ('web_fetch_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebFetchToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of caller + if self.caller: + _dict['caller'] = self.caller.to_dict() + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if caller (nullable) is None + # and model_fields_set contains the field + if self.caller is None and "caller" in self.model_fields_set: + _dict['caller'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebFetchToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "caller": Caller.from_dict(obj["caller"]) if obj.get("caller") is not None else None, + "content": Content7.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_fetch_tool_result_error_block.py b/src/otari/_client/models/mr_web_fetch_tool_result_error_block.py new file mode 100644 index 0000000..ae3c349 --- /dev/null +++ b/src/otari/_client/models/mr_web_fetch_tool_result_error_block.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebFetchToolResultErrorBlock(BaseModel): + """ + MRWebFetchToolResultErrorBlock + """ # noqa: E501 + error_code: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'url_too_long', 'url_not_allowed', 'url_not_accessible', 'unsupported_content_type', 'too_many_requests', 'max_uses_exceeded', 'unavailable']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'url_too_long', 'url_not_allowed', 'url_not_accessible', 'unsupported_content_type', 'too_many_requests', 'max_uses_exceeded', 'unavailable')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_fetch_tool_result_error']): + raise ValueError("must be one of enum values ('web_fetch_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebFetchToolResultErrorBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebFetchToolResultErrorBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_search_result_block.py b/src/otari/_client/models/mr_web_search_result_block.py new file mode 100644 index 0000000..7aea46b --- /dev/null +++ b/src/otari/_client/models/mr_web_search_result_block.py @@ -0,0 +1,121 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebSearchResultBlock(BaseModel): + """ + MRWebSearchResultBlock + """ # noqa: E501 + encrypted_content: StrictStr + page_age: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + title: StrictStr + type: StrictStr + url: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["encrypted_content", "page_age", "title", "type", "url"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search_result']): + raise ValueError("must be one of enum values ('web_search_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebSearchResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if page_age (nullable) is None + # and model_fields_set contains the field + if self.page_age is None and "page_age" in self.model_fields_set: + _dict['page_age'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebSearchResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "encrypted_content": obj.get("encrypted_content"), + "page_age": obj.get("page_age"), + "title": obj.get("title"), + "type": obj.get("type"), + "url": obj.get("url") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_search_tool_result_block.py b/src/otari/_client/models/mr_web_search_tool_result_block.py new file mode 100644 index 0000000..a50cf76 --- /dev/null +++ b/src/otari/_client/models/mr_web_search_tool_result_block.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.caller import Caller +from otari._client.models.content8 import Content8 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebSearchToolResultBlock(BaseModel): + """ + MRWebSearchToolResultBlock + """ # noqa: E501 + caller: Optional[Caller] = None + content: Content8 + tool_use_id: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["caller", "content", "tool_use_id", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search_tool_result']): + raise ValueError("must be one of enum values ('web_search_tool_result')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebSearchToolResultBlock from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of caller + if self.caller: + _dict['caller'] = self.caller.to_dict() + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if caller (nullable) is None + # and model_fields_set contains the field + if self.caller is None and "caller" in self.model_fields_set: + _dict['caller'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebSearchToolResultBlock from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "caller": Caller.from_dict(obj["caller"]) if obj.get("caller") is not None else None, + "content": Content8.from_dict(obj["content"]) if obj.get("content") is not None else None, + "tool_use_id": obj.get("tool_use_id"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/mr_web_search_tool_result_error.py b/src/otari/_client/models/mr_web_search_tool_result_error.py new file mode 100644 index 0000000..85797c0 --- /dev/null +++ b/src/otari/_client/models/mr_web_search_tool_result_error.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MRWebSearchToolResultError(BaseModel): + """ + MRWebSearchToolResultError + """ # noqa: E501 + error_code: StrictStr + type: StrictStr + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["error_code", "type"] + + @field_validator('error_code') + def error_code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['invalid_tool_input', 'unavailable', 'max_uses_exceeded', 'too_many_requests', 'query_too_long', 'request_too_large']): + raise ValueError("must be one of enum values ('invalid_tool_input', 'unavailable', 'max_uses_exceeded', 'too_many_requests', 'query_too_long', 'request_too_large')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search_tool_result_error']): + raise ValueError("must be one of enum values ('web_search_tool_result_error')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MRWebSearchToolResultError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MRWebSearchToolResultError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error_code": obj.get("error_code"), + "type": obj.get("type") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/msg_audio.py b/src/otari/_client/models/msg_audio.py new file mode 100644 index 0000000..ae38f46 --- /dev/null +++ b/src/otari/_client/models/msg_audio.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGAudio(BaseModel): + """ + Data about a previous audio response from the model. [Learn more](https://platform.openai.com/docs/guides/audio). + """ # noqa: E501 + id: StrictStr + __properties: ClassVar[List[str]] = ["id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGAudio from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGAudio from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_assistant_message_param.py b/src/otari/_client/models/msg_chat_completion_assistant_message_param.py new file mode 100644 index 0000000..c00d128 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_assistant_message_param.py @@ -0,0 +1,147 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.content import Content +from otari._client.models.msg_audio import MSGAudio +from otari._client.models.msg_function_call import MSGFunctionCall +from otari._client.models.tool_calls_inner import ToolCallsInner +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionAssistantMessageParam(BaseModel): + """ + Messages sent by the model in response to user messages. + """ # noqa: E501 + role: StrictStr + audio: Optional[MSGAudio] = None + content: Optional[Content] = None + function_call: Optional[MSGFunctionCall] = None + name: Optional[StrictStr] = None + refusal: Optional[StrictStr] = None + tool_calls: Optional[List[ToolCallsInner]] = None + __properties: ClassVar[List[str]] = ["role", "audio", "content", "function_call", "name", "refusal", "tool_calls"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['assistant']): + raise ValueError("must be one of enum values ('assistant')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionAssistantMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of audio + if self.audio: + _dict['audio'] = self.audio.to_dict() + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + # override the default output from pydantic by calling `to_dict()` of function_call + if self.function_call: + _dict['function_call'] = self.function_call.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in tool_calls (list) + _items = [] + if self.tool_calls: + for _item_tool_calls in self.tool_calls: + if _item_tool_calls: + _items.append(_item_tool_calls.to_dict()) + _dict['tool_calls'] = _items + # set to None if audio (nullable) is None + # and model_fields_set contains the field + if self.audio is None and "audio" in self.model_fields_set: + _dict['audio'] = None + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + # set to None if function_call (nullable) is None + # and model_fields_set contains the field + if self.function_call is None and "function_call" in self.model_fields_set: + _dict['function_call'] = None + + # set to None if refusal (nullable) is None + # and model_fields_set contains the field + if self.refusal is None and "refusal" in self.model_fields_set: + _dict['refusal'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionAssistantMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "role": obj.get("role"), + "audio": MSGAudio.from_dict(obj["audio"]) if obj.get("audio") is not None else None, + "content": Content.from_dict(obj["content"]) if obj.get("content") is not None else None, + "function_call": MSGFunctionCall.from_dict(obj["function_call"]) if obj.get("function_call") is not None else None, + "name": obj.get("name"), + "refusal": obj.get("refusal"), + "tool_calls": [ToolCallsInner.from_dict(_item) for _item in obj["tool_calls"]] if obj.get("tool_calls") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_content_part_image_param.py b/src/otari/_client/models/msg_chat_completion_content_part_image_param.py new file mode 100644 index 0000000..5efe5de --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_content_part_image_param.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.msg_image_url import MSGImageURL +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionContentPartImageParam(BaseModel): + """ + Learn about [image inputs](https://platform.openai.com/docs/guides/vision). + """ # noqa: E501 + image_url: MSGImageURL + type: StrictStr + __properties: ClassVar[List[str]] = ["image_url", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['image_url']): + raise ValueError("must be one of enum values ('image_url')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartImageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of image_url + if self.image_url: + _dict['image_url'] = self.image_url.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartImageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "image_url": MSGImageURL.from_dict(obj["image_url"]) if obj.get("image_url") is not None else None, + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_content_part_input_audio_param.py b/src/otari/_client/models/msg_chat_completion_content_part_input_audio_param.py new file mode 100644 index 0000000..6ea1b92 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_content_part_input_audio_param.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.msg_input_audio import MSGInputAudio +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionContentPartInputAudioParam(BaseModel): + """ + Learn about [audio inputs](https://platform.openai.com/docs/guides/audio). + """ # noqa: E501 + input_audio: MSGInputAudio + type: StrictStr + __properties: ClassVar[List[str]] = ["input_audio", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['input_audio']): + raise ValueError("must be one of enum values ('input_audio')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartInputAudioParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of input_audio + if self.input_audio: + _dict['input_audio'] = self.input_audio.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartInputAudioParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input_audio": MSGInputAudio.from_dict(obj["input_audio"]) if obj.get("input_audio") is not None else None, + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_content_part_refusal_param.py b/src/otari/_client/models/msg_chat_completion_content_part_refusal_param.py new file mode 100644 index 0000000..05eaf05 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_content_part_refusal_param.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionContentPartRefusalParam(BaseModel): + """ + MSGChatCompletionContentPartRefusalParam + """ # noqa: E501 + refusal: StrictStr + type: StrictStr + __properties: ClassVar[List[str]] = ["refusal", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['refusal']): + raise ValueError("must be one of enum values ('refusal')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartRefusalParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartRefusalParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "refusal": obj.get("refusal"), + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_content_part_text_param.py b/src/otari/_client/models/msg_chat_completion_content_part_text_param.py new file mode 100644 index 0000000..77092fc --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_content_part_text_param.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionContentPartTextParam(BaseModel): + """ + Learn about [text inputs](https://platform.openai.com/docs/guides/text-generation). + """ # noqa: E501 + text: StrictStr + type: StrictStr + __properties: ClassVar[List[str]] = ["text", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['text']): + raise ValueError("must be one of enum values ('text')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartTextParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionContentPartTextParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "text": obj.get("text"), + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_developer_message_param.py b/src/otari/_client/models/msg_chat_completion_developer_message_param.py new file mode 100644 index 0000000..26a85c7 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_developer_message_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.content1 import Content1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionDeveloperMessageParam(BaseModel): + """ + Developer-provided instructions that the model should follow, regardless of messages sent by the user. With o1 models and newer, `developer` messages replace the previous `system` messages. + """ # noqa: E501 + content: Content1 + role: StrictStr + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["content", "role", "name"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['developer']): + raise ValueError("must be one of enum values ('developer')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionDeveloperMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionDeveloperMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content1.from_dict(obj["content"]) if obj.get("content") is not None else None, + "role": obj.get("role"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_function_message_param.py b/src/otari/_client/models/msg_chat_completion_function_message_param.py new file mode 100644 index 0000000..25dc541 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_function_message_param.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionFunctionMessageParam(BaseModel): + """ + MSGChatCompletionFunctionMessageParam + """ # noqa: E501 + content: Optional[StrictStr] + name: StrictStr + role: StrictStr + __properties: ClassVar[List[str]] = ["content", "name", "role"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['function']): + raise ValueError("must be one of enum values ('function')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionFunctionMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict['content'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionFunctionMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": obj.get("content"), + "name": obj.get("name"), + "role": obj.get("role") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_message_custom_tool_call_param.py b/src/otari/_client/models/msg_chat_completion_message_custom_tool_call_param.py new file mode 100644 index 0000000..668e929 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_message_custom_tool_call_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.msg_custom import MSGCustom +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionMessageCustomToolCallParam(BaseModel): + """ + A call to a custom tool created by the model. + """ # noqa: E501 + id: StrictStr + custom: MSGCustom + type: StrictStr + __properties: ClassVar[List[str]] = ["id", "custom", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['custom']): + raise ValueError("must be one of enum values ('custom')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionMessageCustomToolCallParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of custom + if self.custom: + _dict['custom'] = self.custom.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionMessageCustomToolCallParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "custom": MSGCustom.from_dict(obj["custom"]) if obj.get("custom") is not None else None, + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_message_function_tool_call_param.py b/src/otari/_client/models/msg_chat_completion_message_function_tool_call_param.py new file mode 100644 index 0000000..e3bfea3 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_message_function_tool_call_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.msg_function import MSGFunction +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionMessageFunctionToolCallParam(BaseModel): + """ + A call to a function tool created by the model. + """ # noqa: E501 + id: StrictStr + function: MSGFunction + type: StrictStr + __properties: ClassVar[List[str]] = ["id", "function", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['function']): + raise ValueError("must be one of enum values ('function')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionMessageFunctionToolCallParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of function + if self.function: + _dict['function'] = self.function.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionMessageFunctionToolCallParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "function": MSGFunction.from_dict(obj["function"]) if obj.get("function") is not None else None, + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_system_message_param.py b/src/otari/_client/models/msg_chat_completion_system_message_param.py new file mode 100644 index 0000000..8545409 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_system_message_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.content1 import Content1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionSystemMessageParam(BaseModel): + """ + Developer-provided instructions that the model should follow, regardless of messages sent by the user. With o1 models and newer, use `developer` messages for this purpose instead. + """ # noqa: E501 + content: Content1 + role: StrictStr + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["content", "role", "name"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['system']): + raise ValueError("must be one of enum values ('system')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionSystemMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionSystemMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content1.from_dict(obj["content"]) if obj.get("content") is not None else None, + "role": obj.get("role"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_tool_message_param.py b/src/otari/_client/models/msg_chat_completion_tool_message_param.py new file mode 100644 index 0000000..05c7cb7 --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_tool_message_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.content1 import Content1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionToolMessageParam(BaseModel): + """ + MSGChatCompletionToolMessageParam + """ # noqa: E501 + content: Content1 + role: StrictStr + tool_call_id: StrictStr + __properties: ClassVar[List[str]] = ["content", "role", "tool_call_id"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['tool']): + raise ValueError("must be one of enum values ('tool')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionToolMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionToolMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content1.from_dict(obj["content"]) if obj.get("content") is not None else None, + "role": obj.get("role"), + "tool_call_id": obj.get("tool_call_id") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_chat_completion_user_message_param.py b/src/otari/_client/models/msg_chat_completion_user_message_param.py new file mode 100644 index 0000000..22a41bc --- /dev/null +++ b/src/otari/_client/models/msg_chat_completion_user_message_param.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.content2 import Content2 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGChatCompletionUserMessageParam(BaseModel): + """ + Messages sent by an end user, containing prompts or additional context information. + """ # noqa: E501 + content: Content2 + role: StrictStr + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["content", "role", "name"] + + @field_validator('role') + def role_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['user']): + raise ValueError("must be one of enum values ('user')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGChatCompletionUserMessageParam from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of content + if self.content: + _dict['content'] = self.content.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGChatCompletionUserMessageParam from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "content": Content2.from_dict(obj["content"]) if obj.get("content") is not None else None, + "role": obj.get("role"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_custom.py b/src/otari/_client/models/msg_custom.py new file mode 100644 index 0000000..745476c --- /dev/null +++ b/src/otari/_client/models/msg_custom.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGCustom(BaseModel): + """ + The custom tool that the model called. + """ # noqa: E501 + input: StrictStr + name: StrictStr + __properties: ClassVar[List[str]] = ["input", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGCustom from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGCustom from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "input": obj.get("input"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_file.py b/src/otari/_client/models/msg_file.py new file mode 100644 index 0000000..a2a2bb0 --- /dev/null +++ b/src/otari/_client/models/msg_file.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.msg_file_file import MSGFileFile +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGFile(BaseModel): + """ + Learn about [file inputs](https://platform.openai.com/docs/guides/text) for text generation. + """ # noqa: E501 + file: MSGFileFile + type: StrictStr + __properties: ClassVar[List[str]] = ["file", "type"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['file']): + raise ValueError("must be one of enum values ('file')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGFile from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of file + if self.file: + _dict['file'] = self.file.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGFile from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "file": MSGFileFile.from_dict(obj["file"]) if obj.get("file") is not None else None, + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_file_file.py b/src/otari/_client/models/msg_file_file.py new file mode 100644 index 0000000..22d968d --- /dev/null +++ b/src/otari/_client/models/msg_file_file.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGFileFile(BaseModel): + """ + MSGFileFile + """ # noqa: E501 + file_data: Optional[StrictStr] = None + file_id: Optional[StrictStr] = None + filename: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["file_data", "file_id", "filename"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGFileFile from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGFileFile from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "file_data": obj.get("file_data"), + "file_id": obj.get("file_id"), + "filename": obj.get("filename") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_function.py b/src/otari/_client/models/msg_function.py new file mode 100644 index 0000000..819d208 --- /dev/null +++ b/src/otari/_client/models/msg_function.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGFunction(BaseModel): + """ + The function that the model called. + """ # noqa: E501 + arguments: StrictStr + name: StrictStr + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGFunction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGFunction from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_function_call.py b/src/otari/_client/models/msg_function_call.py new file mode 100644 index 0000000..4ffa450 --- /dev/null +++ b/src/otari/_client/models/msg_function_call.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGFunctionCall(BaseModel): + """ + Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + """ # noqa: E501 + arguments: StrictStr + name: StrictStr + __properties: ClassVar[List[str]] = ["arguments", "name"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGFunctionCall from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGFunctionCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "arguments": obj.get("arguments"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_image_url.py b/src/otari/_client/models/msg_image_url.py new file mode 100644 index 0000000..12b3dec --- /dev/null +++ b/src/otari/_client/models/msg_image_url.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGImageURL(BaseModel): + """ + MSGImageURL + """ # noqa: E501 + url: StrictStr + detail: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["url", "detail"] + + @field_validator('detail') + def detail_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['auto', 'low', 'high']): + raise ValueError("must be one of enum values ('auto', 'low', 'high')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGImageURL from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGImageURL from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "url": obj.get("url"), + "detail": obj.get("detail") + }) + return _obj + + diff --git a/src/otari/_client/models/msg_input_audio.py b/src/otari/_client/models/msg_input_audio.py new file mode 100644 index 0000000..7f70699 --- /dev/null +++ b/src/otari/_client/models/msg_input_audio.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class MSGInputAudio(BaseModel): + """ + MSGInputAudio + """ # noqa: E501 + data: StrictStr + format: StrictStr + __properties: ClassVar[List[str]] = ["data", "format"] + + @field_validator('format') + def format_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['wav', 'mp3']): + raise ValueError("must be one of enum values ('wav', 'mp3')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MSGInputAudio from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MSGInputAudio from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": obj.get("data"), + "format": obj.get("format") + }) + return _obj + + diff --git a/src/otari/_client/models/pricing_response.py b/src/otari/_client/models/pricing_response.py new file mode 100644 index 0000000..cee74a5 --- /dev/null +++ b/src/otari/_client/models/pricing_response.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class PricingResponse(BaseModel): + """ + Response model for model pricing. + """ # noqa: E501 + created_at: StrictStr + effective_at: StrictStr + input_price_per_million: Union[StrictFloat, StrictInt] + model_key: StrictStr + output_price_per_million: Union[StrictFloat, StrictInt] + updated_at: StrictStr + __properties: ClassVar[List[str]] = ["created_at", "effective_at", "input_price_per_million", "model_key", "output_price_per_million", "updated_at"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of PricingResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of PricingResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "created_at": obj.get("created_at"), + "effective_at": obj.get("effective_at"), + "input_price_per_million": obj.get("input_price_per_million"), + "model_key": obj.get("model_key"), + "output_price_per_million": obj.get("output_price_per_million"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/src/otari/_client/models/rerank_request.py b/src/otari/_client/models/rerank_request.py new file mode 100644 index 0000000..3e210cf --- /dev/null +++ b/src/otari/_client/models/rerank_request.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RerankRequest(BaseModel): + """ + Rerank request. + """ # noqa: E501 + documents: Annotated[List[StrictStr], Field(min_length=1)] = Field(description="List of document strings to rerank") + max_tokens_per_doc: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Per-document truncation limit") + model: StrictStr = Field(description="Provider-prefixed model ID, e.g. 'cohere:rerank-v3.5'") + query: StrictStr = Field(description="The search query to rerank documents against") + top_n: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Maximum number of results to return") + user: Optional[StrictStr] = Field(default=None, description="User ID for usage attribution") + __properties: ClassVar[List[str]] = ["documents", "max_tokens_per_doc", "model", "query", "top_n", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RerankRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if max_tokens_per_doc (nullable) is None + # and model_fields_set contains the field + if self.max_tokens_per_doc is None and "max_tokens_per_doc" in self.model_fields_set: + _dict['max_tokens_per_doc'] = None + + # set to None if top_n (nullable) is None + # and model_fields_set contains the field + if self.top_n is None and "top_n" in self.model_fields_set: + _dict['top_n'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RerankRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "documents": obj.get("documents"), + "max_tokens_per_doc": obj.get("max_tokens_per_doc"), + "model": obj.get("model"), + "query": obj.get("query"), + "top_n": obj.get("top_n"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/rerank_response.py b/src/otari/_client/models/rerank_response.py new file mode 100644 index 0000000..0d78070 --- /dev/null +++ b/src/otari/_client/models/rerank_response.py @@ -0,0 +1,125 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.rr_rerank_meta import RRRerankMeta +from otari._client.models.rr_rerank_result import RRRerankResult +from otari._client.models.rr_rerank_usage import RRRerankUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RerankResponse(BaseModel): + """ + Normalized rerank response, provider-agnostic. + """ # noqa: E501 + id: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + results: List[RRRerankResult] = Field(description="Results sorted by relevance_score descending") + meta: Optional[RRRerankMeta] = None + usage: Optional[RRRerankUsage] = None + __properties: ClassVar[List[str]] = ["id", "results", "meta", "usage"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RerankResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict['results'] = _items + # override the default output from pydantic by calling `to_dict()` of meta + if self.meta: + _dict['meta'] = self.meta.to_dict() + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + # set to None if id (nullable) is None + # and model_fields_set contains the field + if self.id is None and "id" in self.model_fields_set: + _dict['id'] = None + + # set to None if meta (nullable) is None + # and model_fields_set contains the field + if self.meta is None and "meta" in self.model_fields_set: + _dict['meta'] = None + + # set to None if usage (nullable) is None + # and model_fields_set contains the field + if self.usage is None and "usage" in self.model_fields_set: + _dict['usage'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RerankResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "results": [RRRerankResult.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None, + "meta": RRRerankMeta.from_dict(obj["meta"]) if obj.get("meta") is not None else None, + "usage": RRRerankUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/responses_request.py b/src/otari/_client/models/responses_request.py new file mode 100644 index 0000000..881440a --- /dev/null +++ b/src/otari/_client/models/responses_request.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from uuid import UUID +from otari._client.models.guardrail_config import GuardrailConfig +from otari._client.models.mcp_server_config import McpServerConfig +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ResponsesRequest(BaseModel): + """ + OpenAI Responses API-compatible request. Gateway-internal fields (``mcp_servers``, ``mcp_server_ids``, ``guardrails``, ``tools_header``, ``max_tool_iterations``) opt the request into gateway-managed MCP / sandbox / web_search / guardrails without changing the upstream wire shape. They're stripped before the request is forwarded. + """ # noqa: E501 + guardrails: Optional[Annotated[List[GuardrailConfig], Field(max_length=8)]] = None + input: Optional[Any] + max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None + mcp_server_ids: Optional[List[UUID]] = None + mcp_servers: Optional[List[McpServerConfig]] = None + model: StrictStr + stream: Optional[StrictBool] = False + tools: Optional[List[Dict[str, Any]]] = None + tools_header: Optional[StrictStr] = None + user: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["guardrails", "input", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "model", "stream", "tools", "tools_header", "user"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ResponsesRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in guardrails (list) + _items = [] + if self.guardrails: + for _item_guardrails in self.guardrails: + if _item_guardrails: + _items.append(_item_guardrails.to_dict()) + _dict['guardrails'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in mcp_servers (list) + _items = [] + if self.mcp_servers: + for _item_mcp_servers in self.mcp_servers: + if _item_mcp_servers: + _items.append(_item_mcp_servers.to_dict()) + _dict['mcp_servers'] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if guardrails (nullable) is None + # and model_fields_set contains the field + if self.guardrails is None and "guardrails" in self.model_fields_set: + _dict['guardrails'] = None + + # set to None if input (nullable) is None + # and model_fields_set contains the field + if self.input is None and "input" in self.model_fields_set: + _dict['input'] = None + + # set to None if max_tool_iterations (nullable) is None + # and model_fields_set contains the field + if self.max_tool_iterations is None and "max_tool_iterations" in self.model_fields_set: + _dict['max_tool_iterations'] = None + + # set to None if mcp_server_ids (nullable) is None + # and model_fields_set contains the field + if self.mcp_server_ids is None and "mcp_server_ids" in self.model_fields_set: + _dict['mcp_server_ids'] = None + + # set to None if mcp_servers (nullable) is None + # and model_fields_set contains the field + if self.mcp_servers is None and "mcp_servers" in self.model_fields_set: + _dict['mcp_servers'] = None + + # set to None if tools (nullable) is None + # and model_fields_set contains the field + if self.tools is None and "tools" in self.model_fields_set: + _dict['tools'] = None + + # set to None if tools_header (nullable) is None + # and model_fields_set contains the field + if self.tools_header is None and "tools_header" in self.model_fields_set: + _dict['tools_header'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ResponsesRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "guardrails": [GuardrailConfig.from_dict(_item) for _item in obj["guardrails"]] if obj.get("guardrails") is not None else None, + "input": obj.get("input"), + "max_tool_iterations": obj.get("max_tool_iterations"), + "mcp_server_ids": obj.get("mcp_server_ids"), + "mcp_servers": [McpServerConfig.from_dict(_item) for _item in obj["mcp_servers"]] if obj.get("mcp_servers") is not None else None, + "model": obj.get("model"), + "stream": obj.get("stream") if obj.get("stream") is not None else False, + "tools": obj.get("tools"), + "tools_header": obj.get("tools_header"), + "user": obj.get("user") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/rr_rerank_meta.py b/src/otari/_client/models/rr_rerank_meta.py new file mode 100644 index 0000000..865c2a7 --- /dev/null +++ b/src/otari/_client/models/rr_rerank_meta.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RRRerankMeta(BaseModel): + """ + Provider-specific billing metadata (optional, preserved as-is). + """ # noqa: E501 + billed_units: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = None + tokens: Optional[Dict[str, StrictInt]] = None + __properties: ClassVar[List[str]] = ["billed_units", "tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RRRerankMeta from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if billed_units (nullable) is None + # and model_fields_set contains the field + if self.billed_units is None and "billed_units" in self.model_fields_set: + _dict['billed_units'] = None + + # set to None if tokens (nullable) is None + # and model_fields_set contains the field + if self.tokens is None and "tokens" in self.model_fields_set: + _dict['tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RRRerankMeta from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "billed_units": obj.get("billed_units"), + "tokens": obj.get("tokens") + }) + return _obj + + diff --git a/src/otari/_client/models/rr_rerank_result.py b/src/otari/_client/models/rr_rerank_result.py new file mode 100644 index 0000000..9aad3e9 --- /dev/null +++ b/src/otari/_client/models/rr_rerank_result.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt +from typing import Any, ClassVar, Dict, List, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RRRerankResult(BaseModel): + """ + A single document's relevance score. + """ # noqa: E501 + index: StrictInt = Field(description="Zero-based index into the original documents list") + relevance_score: Union[StrictFloat, StrictInt] = Field(description="Relevance score, higher is more relevant") + __properties: ClassVar[List[str]] = ["index", "relevance_score"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RRRerankResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RRRerankResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "index": obj.get("index"), + "relevance_score": obj.get("relevance_score") + }) + return _obj + + diff --git a/src/otari/_client/models/rr_rerank_usage.py b/src/otari/_client/models/rr_rerank_usage.py new file mode 100644 index 0000000..d4bd875 --- /dev/null +++ b/src/otari/_client/models/rr_rerank_usage.py @@ -0,0 +1,93 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RRRerankUsage(BaseModel): + """ + Normalized token usage for gateway logging. + """ # noqa: E501 + total_tokens: Optional[StrictInt] = None + __properties: ClassVar[List[str]] = ["total_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RRRerankUsage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if total_tokens (nullable) is None + # and model_fields_set contains the field + if self.total_tokens is None and "total_tokens" in self.model_fields_set: + _dict['total_tokens'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RRRerankUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "total_tokens": obj.get("total_tokens") + }) + return _obj + + diff --git a/src/otari/_client/models/set_pricing_request.py b/src/otari/_client/models/set_pricing_request.py new file mode 100644 index 0000000..567e9ef --- /dev/null +++ b/src/otari/_client/models/set_pricing_request.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class SetPricingRequest(BaseModel): + """ + Request model for setting model pricing. + """ # noqa: E501 + effective_at: Optional[datetime] = Field(default=None, description="ISO 8601 datetime from which this price applies. Defaults to now if omitted.") + input_price_per_million: Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]] = Field(description="Price per 1M input tokens") + model_key: StrictStr = Field(description="Model identifier in format 'provider:model'") + output_price_per_million: Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]] = Field(description="Price per 1M output tokens") + __properties: ClassVar[List[str]] = ["effective_at", "input_price_per_million", "model_key", "output_price_per_million"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SetPricingRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if effective_at (nullable) is None + # and model_fields_set contains the field + if self.effective_at is None and "effective_at" in self.model_fields_set: + _dict['effective_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SetPricingRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "effective_at": obj.get("effective_at"), + "input_price_per_million": obj.get("input_price_per_million"), + "model_key": obj.get("model_key"), + "output_price_per_million": obj.get("output_price_per_million") + }) + return _obj + + diff --git a/src/otari/_client/models/source.py b/src/otari/_client/models/source.py new file mode 100644 index 0000000..33f951b --- /dev/null +++ b/src/otari/_client/models/source.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.mr_base64_pdf_source import MRBase64PDFSource +from otari._client.models.mr_plain_text_source import MRPlainTextSource +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +SOURCE_ANY_OF_SCHEMAS = ["MRBase64PDFSource", "MRPlainTextSource"] + +class Source(BaseModel): + """ + Source + """ + + # data type: MRBase64PDFSource + anyof_schema_1_validator: Optional[MRBase64PDFSource] = None + # data type: MRPlainTextSource + anyof_schema_2_validator: Optional[MRPlainTextSource] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MRBase64PDFSource, MRPlainTextSource]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MRBase64PDFSource", "MRPlainTextSource" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Source.model_construct() + error_messages = [] + # validate data type: MRBase64PDFSource + if not isinstance(v, MRBase64PDFSource): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRBase64PDFSource`") + else: + return v + + # validate data type: MRPlainTextSource + if not isinstance(v, MRPlainTextSource): + error_messages.append(f"Error! Input type `{type(v)}` is not `MRPlainTextSource`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Source with anyOf schemas: MRBase64PDFSource, MRPlainTextSource. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MRBase64PDFSource] = None + try: + instance.actual_instance = MRBase64PDFSource.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MRPlainTextSource] = None + try: + instance.actual_instance = MRPlainTextSource.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Source with anyOf schemas: MRBase64PDFSource, MRPlainTextSource. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MRBase64PDFSource, MRPlainTextSource]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/system.py b/src/otari/_client/models/system.py new file mode 100644 index 0000000..80d4e22 --- /dev/null +++ b/src/otari/_client/models/system.py @@ -0,0 +1,144 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, Dict, List, Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +SYSTEM_ANY_OF_SCHEMAS = ["List[Dict[str, object]]", "str"] + +class System(BaseModel): + """ + System + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + # data type: List[Dict[str, object]] + anyof_schema_2_validator: Optional[List[Dict[str, Any]]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[Dict[str, object]], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[Dict[str, object]]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = System.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[Dict[str, object]] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in System with anyOf schemas: List[Dict[str, object]], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[Dict[str, object]] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into System with anyOf schemas: List[Dict[str, object]], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[Dict[str, object]], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/tool_calls_inner.py b/src/otari/_client/models/tool_calls_inner.py new file mode 100644 index 0000000..0136089 --- /dev/null +++ b/src/otari/_client/models/tool_calls_inner.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Optional +from otari._client.models.msg_chat_completion_message_custom_tool_call_param import MSGChatCompletionMessageCustomToolCallParam +from otari._client.models.msg_chat_completion_message_function_tool_call_param import MSGChatCompletionMessageFunctionToolCallParam +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +TOOLCALLSINNER_ANY_OF_SCHEMAS = ["MSGChatCompletionMessageCustomToolCallParam", "MSGChatCompletionMessageFunctionToolCallParam"] + +class ToolCallsInner(BaseModel): + """ + ToolCallsInner + """ + + # data type: MSGChatCompletionMessageFunctionToolCallParam + anyof_schema_1_validator: Optional[MSGChatCompletionMessageFunctionToolCallParam] = None + # data type: MSGChatCompletionMessageCustomToolCallParam + anyof_schema_2_validator: Optional[MSGChatCompletionMessageCustomToolCallParam] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[MSGChatCompletionMessageCustomToolCallParam, MSGChatCompletionMessageFunctionToolCallParam]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "MSGChatCompletionMessageCustomToolCallParam", "MSGChatCompletionMessageFunctionToolCallParam" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = ToolCallsInner.model_construct() + error_messages = [] + # validate data type: MSGChatCompletionMessageFunctionToolCallParam + if not isinstance(v, MSGChatCompletionMessageFunctionToolCallParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionMessageFunctionToolCallParam`") + else: + return v + + # validate data type: MSGChatCompletionMessageCustomToolCallParam + if not isinstance(v, MSGChatCompletionMessageCustomToolCallParam): + error_messages.append(f"Error! Input type `{type(v)}` is not `MSGChatCompletionMessageCustomToolCallParam`") + else: + return v + + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in ToolCallsInner with anyOf schemas: MSGChatCompletionMessageCustomToolCallParam, MSGChatCompletionMessageFunctionToolCallParam. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[MSGChatCompletionMessageFunctionToolCallParam] = None + try: + instance.actual_instance = MSGChatCompletionMessageFunctionToolCallParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MSGChatCompletionMessageCustomToolCallParam] = None + try: + instance.actual_instance = MSGChatCompletionMessageCustomToolCallParam.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into ToolCallsInner with anyOf schemas: MSGChatCompletionMessageCustomToolCallParam, MSGChatCompletionMessageFunctionToolCallParam. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], MSGChatCompletionMessageCustomToolCallParam, MSGChatCompletionMessageFunctionToolCallParam]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/tool_choice.py b/src/otari/_client/models/tool_choice.py new file mode 100644 index 0000000..107d6c6 --- /dev/null +++ b/src/otari/_client/models/tool_choice.py @@ -0,0 +1,144 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, Dict, Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +TOOLCHOICE_ANY_OF_SCHEMAS = ["Dict[str, object]", "str"] + +class ToolChoice(BaseModel): + """ + ToolChoice + """ + + # data type: str + anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + # data type: Dict[str, object] + anyof_schema_2_validator: Optional[Dict[str, Any]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[Dict[str, object], str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "Dict[str, object]", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = ToolChoice.model_construct() + error_messages = [] + # validate data type: str + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: Dict[str, object] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in ToolChoice with anyOf schemas: Dict[str, object], str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # deserialize data into str + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into Dict[str, object] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into ToolChoice with anyOf schemas: Dict[str, object], str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], Dict[str, object], str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/update_budget_request.py b/src/otari/_client/models/update_budget_request.py new file mode 100644 index 0000000..8fe3968 --- /dev/null +++ b/src/otari/_client/models/update_budget_request.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateBudgetRequest(BaseModel): + """ + Request model for updating a budget. + """ # noqa: E501 + budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = None + max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UpdateBudgetRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if budget_duration_sec (nullable) is None + # and model_fields_set contains the field + if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: + _dict['budget_duration_sec'] = None + + # set to None if max_budget (nullable) is None + # and model_fields_set contains the field + if self.max_budget is None and "max_budget" in self.model_fields_set: + _dict['max_budget'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateBudgetRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "budget_duration_sec": obj.get("budget_duration_sec"), + "max_budget": obj.get("max_budget") + }) + return _obj + + diff --git a/src/otari/_client/models/update_key_request.py b/src/otari/_client/models/update_key_request.py new file mode 100644 index 0000000..bf773cb --- /dev/null +++ b/src/otari/_client/models/update_key_request.py @@ -0,0 +1,115 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateKeyRequest(BaseModel): + """ + Request model for updating a key. + """ # noqa: E501 + expires_at: Optional[datetime] = None + is_active: Optional[StrictBool] = None + key_name: Optional[StrictStr] = None + metadata: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["expires_at", "is_active", "key_name", "metadata"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UpdateKeyRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if expires_at (nullable) is None + # and model_fields_set contains the field + if self.expires_at is None and "expires_at" in self.model_fields_set: + _dict['expires_at'] = None + + # set to None if is_active (nullable) is None + # and model_fields_set contains the field + if self.is_active is None and "is_active" in self.model_fields_set: + _dict['is_active'] = None + + # set to None if key_name (nullable) is None + # and model_fields_set contains the field + if self.key_name is None and "key_name" in self.model_fields_set: + _dict['key_name'] = None + + # set to None if metadata (nullable) is None + # and model_fields_set contains the field + if self.metadata is None and "metadata" in self.model_fields_set: + _dict['metadata'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateKeyRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "expires_at": obj.get("expires_at"), + "is_active": obj.get("is_active"), + "key_name": obj.get("key_name"), + "metadata": obj.get("metadata") + }) + return _obj + + diff --git a/src/otari/_client/models/update_user_request.py b/src/otari/_client/models/update_user_request.py new file mode 100644 index 0000000..cd3fe41 --- /dev/null +++ b/src/otari/_client/models/update_user_request.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateUserRequest(BaseModel): + """ + Request model for updating a user. + """ # noqa: E501 + alias: Optional[StrictStr] = None + blocked: Optional[StrictBool] = None + budget_id: Optional[StrictStr] = None + metadata: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "metadata"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UpdateUserRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if alias (nullable) is None + # and model_fields_set contains the field + if self.alias is None and "alias" in self.model_fields_set: + _dict['alias'] = None + + # set to None if blocked (nullable) is None + # and model_fields_set contains the field + if self.blocked is None and "blocked" in self.model_fields_set: + _dict['blocked'] = None + + # set to None if budget_id (nullable) is None + # and model_fields_set contains the field + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None + + # set to None if metadata (nullable) is None + # and model_fields_set contains the field + if self.metadata is None and "metadata" in self.model_fields_set: + _dict['metadata'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateUserRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "alias": obj.get("alias"), + "blocked": obj.get("blocked"), + "budget_id": obj.get("budget_id"), + "metadata": obj.get("metadata") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_entry.py b/src/otari/_client/models/usage_entry.py new file mode 100644 index 0000000..6164329 --- /dev/null +++ b/src/otari/_client/models/usage_entry.py @@ -0,0 +1,152 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageEntry(BaseModel): + """ + A single usage log entry. + """ # noqa: E501 + api_key_id: Optional[StrictStr] + completion_tokens: Optional[StrictInt] + cost: Optional[Union[StrictFloat, StrictInt]] + endpoint: StrictStr + error_message: Optional[StrictStr] + id: StrictStr + model: StrictStr + prompt_tokens: Optional[StrictInt] + provider: Optional[StrictStr] + status: StrictStr + timestamp: StrictStr + total_tokens: Optional[StrictInt] + user_id: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["api_key_id", "completion_tokens", "cost", "endpoint", "error_message", "id", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageEntry from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_key_id (nullable) is None + # and model_fields_set contains the field + if self.api_key_id is None and "api_key_id" in self.model_fields_set: + _dict['api_key_id'] = None + + # set to None if completion_tokens (nullable) is None + # and model_fields_set contains the field + if self.completion_tokens is None and "completion_tokens" in self.model_fields_set: + _dict['completion_tokens'] = None + + # set to None if cost (nullable) is None + # and model_fields_set contains the field + if self.cost is None and "cost" in self.model_fields_set: + _dict['cost'] = None + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict['error_message'] = None + + # set to None if prompt_tokens (nullable) is None + # and model_fields_set contains the field + if self.prompt_tokens is None and "prompt_tokens" in self.model_fields_set: + _dict['prompt_tokens'] = None + + # set to None if provider (nullable) is None + # and model_fields_set contains the field + if self.provider is None and "provider" in self.model_fields_set: + _dict['provider'] = None + + # set to None if total_tokens (nullable) is None + # and model_fields_set contains the field + if self.total_tokens is None and "total_tokens" in self.model_fields_set: + _dict['total_tokens'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UsageEntry from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_key_id": obj.get("api_key_id"), + "completion_tokens": obj.get("completion_tokens"), + "cost": obj.get("cost"), + "endpoint": obj.get("endpoint"), + "error_message": obj.get("error_message"), + "id": obj.get("id"), + "model": obj.get("model"), + "prompt_tokens": obj.get("prompt_tokens"), + "provider": obj.get("provider"), + "status": obj.get("status"), + "timestamp": obj.get("timestamp"), + "total_tokens": obj.get("total_tokens"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_log_response.py b/src/otari/_client/models/usage_log_response.py new file mode 100644 index 0000000..e09b186 --- /dev/null +++ b/src/otari/_client/models/usage_log_response.py @@ -0,0 +1,152 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageLogResponse(BaseModel): + """ + Response model for usage log. + """ # noqa: E501 + api_key_id: Optional[StrictStr] + completion_tokens: Optional[StrictInt] + cost: Optional[Union[StrictFloat, StrictInt]] + endpoint: StrictStr + error_message: Optional[StrictStr] + id: StrictStr + model: StrictStr + prompt_tokens: Optional[StrictInt] + provider: Optional[StrictStr] + status: StrictStr + timestamp: StrictStr + total_tokens: Optional[StrictInt] + user_id: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["api_key_id", "completion_tokens", "cost", "endpoint", "error_message", "id", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageLogResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_key_id (nullable) is None + # and model_fields_set contains the field + if self.api_key_id is None and "api_key_id" in self.model_fields_set: + _dict['api_key_id'] = None + + # set to None if completion_tokens (nullable) is None + # and model_fields_set contains the field + if self.completion_tokens is None and "completion_tokens" in self.model_fields_set: + _dict['completion_tokens'] = None + + # set to None if cost (nullable) is None + # and model_fields_set contains the field + if self.cost is None and "cost" in self.model_fields_set: + _dict['cost'] = None + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict['error_message'] = None + + # set to None if prompt_tokens (nullable) is None + # and model_fields_set contains the field + if self.prompt_tokens is None and "prompt_tokens" in self.model_fields_set: + _dict['prompt_tokens'] = None + + # set to None if provider (nullable) is None + # and model_fields_set contains the field + if self.provider is None and "provider" in self.model_fields_set: + _dict['provider'] = None + + # set to None if total_tokens (nullable) is None + # and model_fields_set contains the field + if self.total_tokens is None and "total_tokens" in self.model_fields_set: + _dict['total_tokens'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UsageLogResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_key_id": obj.get("api_key_id"), + "completion_tokens": obj.get("completion_tokens"), + "cost": obj.get("cost"), + "endpoint": obj.get("endpoint"), + "error_message": obj.get("error_message"), + "id": obj.get("id"), + "model": obj.get("model"), + "prompt_tokens": obj.get("prompt_tokens"), + "provider": obj.get("provider"), + "status": obj.get("status"), + "timestamp": obj.get("timestamp"), + "total_tokens": obj.get("total_tokens"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/user_response.py b/src/otari/_client/models/user_response.py new file mode 100644 index 0000000..b065d87 --- /dev/null +++ b/src/otari/_client/models/user_response.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UserResponse(BaseModel): + """ + Response model for user information. + """ # noqa: E501 + alias: Optional[StrictStr] + blocked: StrictBool + budget_id: Optional[StrictStr] + budget_started_at: Optional[StrictStr] + created_at: StrictStr + metadata: Dict[str, Any] + next_budget_reset_at: Optional[StrictStr] + reserved: Union[StrictFloat, StrictInt] + spend: Union[StrictFloat, StrictInt] + updated_at: StrictStr + user_id: StrictStr + __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "budget_started_at", "created_at", "metadata", "next_budget_reset_at", "reserved", "spend", "updated_at", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UserResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if alias (nullable) is None + # and model_fields_set contains the field + if self.alias is None and "alias" in self.model_fields_set: + _dict['alias'] = None + + # set to None if budget_id (nullable) is None + # and model_fields_set contains the field + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None + + # set to None if budget_started_at (nullable) is None + # and model_fields_set contains the field + if self.budget_started_at is None and "budget_started_at" in self.model_fields_set: + _dict['budget_started_at'] = None + + # set to None if next_budget_reset_at (nullable) is None + # and model_fields_set contains the field + if self.next_budget_reset_at is None and "next_budget_reset_at" in self.model_fields_set: + _dict['next_budget_reset_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UserResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "alias": obj.get("alias"), + "blocked": obj.get("blocked"), + "budget_id": obj.get("budget_id"), + "budget_started_at": obj.get("budget_started_at"), + "created_at": obj.get("created_at"), + "metadata": obj.get("metadata"), + "next_budget_reset_at": obj.get("next_budget_reset_at"), + "reserved": obj.get("reserved"), + "spend": obj.get("spend"), + "updated_at": obj.get("updated_at"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/validation_error.py b/src/otari/_client/models/validation_error.py new file mode 100644 index 0000000..cd002e7 --- /dev/null +++ b/src/otari/_client/models/validation_error.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.location_inner import LocationInner +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ValidationError(BaseModel): + """ + ValidationError + """ # noqa: E501 + ctx: Optional[Dict[str, Any]] = None + input: Optional[Any] = None + loc: List[LocationInner] + msg: StrictStr + type: StrictStr + __properties: ClassVar[List[str]] = ["ctx", "input", "loc", "msg", "type"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ValidationError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in loc (list) + _items = [] + if self.loc: + for _item_loc in self.loc: + if _item_loc: + _items.append(_item_loc.to_dict()) + _dict['loc'] = _items + # set to None if input (nullable) is None + # and model_fields_set contains the field + if self.input is None and "input" in self.model_fields_set: + _dict['input'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ValidationError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "ctx": obj.get("ctx"), + "input": obj.get("input"), + "loc": [LocationInner.from_dict(_item) for _item in obj["loc"]] if obj.get("loc") is not None else None, + "msg": obj.get("msg"), + "type": obj.get("type") + }) + return _obj + + diff --git a/src/otari/_client/py.typed b/src/otari/_client/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/otari/_client/rest.py b/src/otari/_client/rest.py new file mode 100644 index 0000000..c9ab7a9 --- /dev/null +++ b/src/otari/_client/rest.py @@ -0,0 +1,263 @@ +# coding: utf-8 + +""" + otari-gateway + + A clean FastAPI gateway for otari with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import io +import json +import re +import ssl + +import urllib3 + +from otari._client.exceptions import ApiException, ApiValueError + +SUPPORTED_SOCKS_PROXIES = {"socks5", "socks5h", "socks4", "socks4a"} +RESTResponseType = urllib3.HTTPResponse + + +def is_socks_proxy_url(url): + if url is None: + return False + split_section = url.split("://") + if len(split_section) < 2: + return False + else: + return split_section[0].lower() in SUPPORTED_SOCKS_PROXIES + + +class RESTResponse(io.IOBase): + + def __init__(self, resp) -> None: + self.response = resp + self.status = resp.status + self.reason = resp.reason + self.data = None + + def read(self): + if self.data is None: + self.data = self.response.data + return self.data + + @property + def headers(self): + """Returns a dictionary of response headers.""" + return self.response.headers + + def getheaders(self): + """Returns a dictionary of the response headers; use ``headers`` instead.""" + return self.response.headers + + def getheader(self, name, default=None): + """Returns a given response header; use ``headers.get()`` instead.""" + return self.response.headers.get(name, default) + + +class RESTClientObject: + + def __init__(self, configuration) -> None: + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + pool_args = { + "cert_reqs": cert_reqs, + "ca_certs": configuration.ssl_ca_cert, + "cert_file": configuration.cert_file, + "key_file": configuration.key_file, + "ca_cert_data": configuration.ca_cert_data, + } + if configuration.assert_hostname is not None: + pool_args['assert_hostname'] = ( + configuration.assert_hostname + ) + + if configuration.retries is not None: + pool_args['retries'] = configuration.retries + + if configuration.tls_server_name: + pool_args['server_hostname'] = configuration.tls_server_name + + + if configuration.socket_options is not None: + pool_args['socket_options'] = configuration.socket_options + + if configuration.connection_pool_maxsize is not None: + pool_args['maxsize'] = configuration.connection_pool_maxsize + + # https pool manager + self.pool_manager: urllib3.PoolManager + + if configuration.proxy: + if is_socks_proxy_url(configuration.proxy): + from urllib3.contrib.socks import SOCKSProxyManager + pool_args["proxy_url"] = configuration.proxy + pool_args["headers"] = configuration.proxy_headers + self.pool_manager = SOCKSProxyManager(**pool_args) + else: + pool_args["proxy_url"] = configuration.proxy + pool_args["proxy_headers"] = configuration.proxy_headers + self.pool_manager = urllib3.ProxyManager(**pool_args) + else: + self.pool_manager = urllib3.PoolManager(**pool_args) + + def request( + self, + method, + url, + headers=None, + body=None, + post_params=None, + _request_timeout=None + ): + """Perform requests. + + :param method: http request method + :param url: http request url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in [ + 'GET', + 'HEAD', + 'DELETE', + 'POST', + 'PUT', + 'PATCH', + 'OPTIONS' + ] + + if post_params and body: + raise ApiValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, (int, float)): + timeout = urllib3.Timeout(total=_request_timeout) + elif ( + isinstance(_request_timeout, tuple) + and len(_request_timeout) == 2 + ): + timeout = urllib3.Timeout( + connect=_request_timeout[0], + read=_request_timeout[1] + ) + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + + # no content type provided or payload is json + content_type = headers.get('Content-Type') + if ( + not content_type + or re.search('json', content_type, re.IGNORECASE) + ): + request_body = None + if body is not None: + request_body = json.dumps(body) + r = self.pool_manager.request( + method, + url, + body=request_body, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif content_type == 'application/x-www-form-urlencoded': + r = self.pool_manager.request( + method, + url, + fields=post_params, + encode_multipart=False, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif content_type == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + # Ensures that dict objects are serialized + post_params = [(a, json.dumps(b)) if isinstance(b, dict) else (a,b) for a, b in post_params] + r = self.pool_manager.request( + method, + url, + fields=post_params, + encode_multipart=True, + timeout=timeout, + headers=headers, + preload_content=False + ) + # Pass a `string` parameter directly in the body to support + # other content types than JSON when `body` argument is + # provided in serialized form. + elif isinstance(body, str) or isinstance(body, bytes): + r = self.pool_manager.request( + method, + url, + body=body, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif headers['Content-Type'].startswith('text/') and isinstance(body, bool): + request_body = "true" if body else "false" + r = self.pool_manager.request( + method, + url, + body=request_body, + preload_content=False, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request( + method, + url, + fields={}, + timeout=timeout, + headers=headers, + preload_content=False + ) + except urllib3.exceptions.SSLError as e: + msg = "\n".join([type(e).__name__, str(e)]) + raise ApiException(status=0, reason=msg) + + return RESTResponse(r) diff --git a/src/otari/_streaming.py b/src/otari/_streaming.py new file mode 100644 index 0000000..a081e33 --- /dev/null +++ b/src/otari/_streaming.py @@ -0,0 +1,107 @@ +"""Server-Sent-Events (SSE) streaming shim for the otari gateway clients. + +The OpenAPI-generated core in :mod:`otari._client` buffers the full HTTP +response before deserializing, so it *cannot* stream. (This is a known upstream +OpenAPI Generator limitation.) For ``stream=True`` on chat, responses, and +messages, the SDK hand-writes the stream here: a raw streaming POST via +``httpx`` that parses ``text/event-stream`` framing and yields typed chunks. + +Wire format (gateway emits the OpenAI / Anthropic SSE convention): + + data: {"id": "...", ...}\\n + \\n + data: {"id": "...", ...}\\n + \\n + data: [DONE]\\n + \\n + +Each event is ``data: ``; a blank line terminates an event; the +sentinel ``data: [DONE]`` ends the stream. ``event:``/``id:``/``:``-comment +lines are ignored (the gateway does not use named events for chat). + +``parse_chunk`` decides the yielded type per endpoint: + +- chat -> typed :class:`otari._client.models.ChatCompletionChunk` +- responses / messages -> the parsed JSON ``dict`` (no single typed chunk model + exists for these provider-shaped event streams; callers get the raw event). +""" + +from __future__ import annotations + +import json +from typing import TYPE_CHECKING, Any, Literal + +from otari._client.models.chat_completion_chunk import ChatCompletionChunk + +if TYPE_CHECKING: + from collections.abc import AsyncIterator, Iterator + + import httpx + +StreamKind = Literal["chat", "responses", "messages"] + +_DONE = "[DONE]" +_DATA_PREFIX = "data:" + + +def parse_chunk(kind: StreamKind, payload: str) -> Any: + """Parse one SSE ``data:`` payload into the chunk type for ``kind``. + + Chat yields a typed :class:`ChatCompletionChunk`; responses/messages yield + the parsed JSON ``dict`` (their event streams have no single typed model). + """ + if kind == "chat": + chunk = ChatCompletionChunk.from_json(payload) + if chunk is None: # pragma: no cover - from_json only returns None for empty input + msg = "received empty chat completion chunk payload" + raise ValueError(msg) + return chunk + return json.loads(payload) + + +def _iter_data_lines(line: str) -> str | None: + """Return the ``data:`` payload of an SSE line, or ``None`` to skip it. + + Returns the sentinel string ``"[DONE]"`` unchanged so the caller can stop. + """ + stripped = line.rstrip("\n").rstrip("\r") + if not stripped or stripped.startswith(":"): + return None + if not stripped.startswith(_DATA_PREFIX): + # event:/id:/retry: framing lines carry no chunk data for our streams. + return None + return stripped[len(_DATA_PREFIX) :].strip() + + +def iter_sse( + response: httpx.Response, + kind: StreamKind, +) -> Iterator[Any]: + """Yield parsed chunks from a *synchronous* streaming httpx response. + + Stops on the ``data: [DONE]`` sentinel and on end-of-stream. + """ + for line in response.iter_lines(): + payload = _iter_data_lines(line) + if payload is None: + continue + if payload == _DONE: + return + yield parse_chunk(kind, payload) + + +async def aiter_sse( + response: httpx.Response, + kind: StreamKind, +) -> AsyncIterator[Any]: + """Yield parsed chunks from an *asynchronous* streaming httpx response. + + Stops on the ``data: [DONE]`` sentinel and on end-of-stream. + """ + async for line in response.aiter_lines(): + payload = _iter_data_lines(line) + if payload is None: + continue + if payload == _DONE: + return + yield parse_chunk(kind, payload) diff --git a/src/otari/async_client.py b/src/otari/async_client.py index c171f5a..04dd821 100644 --- a/src/otari/async_client.py +++ b/src/otari/async_client.py @@ -1,8 +1,11 @@ """AsyncOtariClient: asynchronous Python client for the otari gateway. -Wraps the OpenAI Python SDK (``AsyncOpenAI``), adding gateway-specific auth -handling and error mapping for platform mode. Extracted from the -``GatewayProvider`` in `any-llm `_. +Option C: a thin async shell over the OpenAPI-generated core in +:mod:`otari._client`. The generated core is synchronous (urllib3-based), so +non-streaming calls are dispatched to a worker thread via ``asyncio.to_thread``; +streaming is natively async over ``httpx.AsyncClient`` and the SSE shim in +:mod:`otari._streaming`. Generated ``ApiException``\\s are mapped to the typed +errors in :mod:`otari.errors`. Example:: @@ -22,25 +25,42 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, overload +import asyncio +from functools import cached_property +from typing import TYPE_CHECKING, Any, cast, overload import httpx -from openai import AsyncOpenAI -from otari._base import _BaseOtariClient, _url_encode +from otari._base import _BaseOtariClient, build_request +from otari._client import ApiClient, Configuration +from otari._client.api.batches_api import BatchesApi +from otari._client.api.chat_api import ChatApi +from otari._client.api.embeddings_api import EmbeddingsApi +from otari._client.api.messages_api import MessagesApi +from otari._client.api.models_api import ModelsApi +from otari._client.api.moderations_api import ModerationsApi +from otari._client.api.rerank_api import RerankApi +from otari._client.api.responses_api import ResponsesApi +from otari._client.exceptions import ApiException +from otari._client.models.chat_completion_request import ChatCompletionRequest +from otari._client.models.create_batch_request import CreateBatchRequest +from otari._client.models.embedding_request import EmbeddingRequest +from otari._client.models.messages_request import MessagesRequest +from otari._client.models.moderation_request import ModerationRequest +from otari._client.models.rerank_request import RerankRequest +from otari._streaming import aiter_sse +from otari.control_plane import ControlPlane +from otari.errors import OtariError if TYPE_CHECKING: - from openai import AsyncStream - from openai.types import CreateEmbeddingResponse, Model - from openai.types.chat import ( - ChatCompletion, - ChatCompletionChunk, - ) - from openai.types.responses import ( - Response, - ResponseStreamEvent, - ) - + from collections.abc import AsyncIterator, Callable + + from otari._client.models.chat_completion import ChatCompletion + from otari._client.models.chat_completion_chunk import ChatCompletionChunk + from otari._client.models.create_embedding_response import CreateEmbeddingResponse + from otari._client.models.model_object import ModelObject + from otari._client.models.moderation_response import ModerationResponse + from otari._client.models.rerank_response import RerankResponse from otari.types import ( BatchResult, CreateBatchParams, @@ -51,69 +71,75 @@ class AsyncOtariClient(_BaseOtariClient): """Asynchronous client for the otari gateway. - Supports two authentication modes (mirroring the TypeScript SDK and - the Python ``GatewayProvider``): + Supports the same two authentication modes as + :class:`~otari.client.OtariClient`: - - **Platform mode**: A Bearer token is sent in the standard Authorization - header. Errors are mapped to typed otari exceptions. - - **Non-platform mode**: An API key is sent via a custom ``Otari-Key`` - header. Errors from the OpenAI SDK pass through unmodified. + - **Platform mode**: Bearer token in the ``Authorization`` header. + - **Non-platform mode**: API key in the custom ``Otari-Key`` header. - Args: - api_base: Base URL of the gateway (e.g. ``"http://localhost:8000"``). - Falls back to the ``GATEWAY_API_BASE`` environment variable. In - platform mode it defaults to the hosted gateway at - ``https://api.otari.ai`` when neither is supplied. - api_key: API key for non-platform mode. - Falls back to ``GATEWAY_API_KEY`` env var. - platform_token: Platform token for platform mode. - Falls back to the canonical ``OTARI_AI_TOKEN`` env var (or the - legacy ``GATEWAY_PLATFORM_TOKEN`` alias). - default_headers: Additional default headers to send with every request. - openai_options: Extra keyword arguments forwarded to the underlying - ``AsyncOpenAI`` constructor. - - Example:: - - client = AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_xxx", - ) + The generated core is synchronous; non-streaming calls run in a worker + thread (``asyncio.to_thread``) while streaming is natively async. - response = await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "Hello!"}], - ) - print(response.choices[0].message.content) + Args: + api_base: Base URL of the gateway. Falls back to ``GATEWAY_API_BASE``; + in platform mode defaults to ``https://api.otari.ai``. + api_key: API key for non-platform mode (``GATEWAY_API_KEY``). + platform_token: Platform token (``OTARI_AI_TOKEN`` / legacy + ``GATEWAY_PLATFORM_TOKEN``). + admin_key: Master/admin key for the control-plane (``GATEWAY_ADMIN_KEY``). + default_headers: Additional default headers sent with every request. + timeout: Per-request timeout (seconds) for the streaming shim. """ - openai: AsyncOpenAI - """The underlying OpenAI client instance.""" - def __init__( self, api_base: str | None = None, *, api_key: str | None = None, platform_token: str | None = None, + admin_key: str | None = None, default_headers: dict[str, str] | None = None, - openai_options: dict[str, Any] | None = None, + timeout: float | None = None, ) -> None: super().__init__( api_base, api_key=api_key, platform_token=platform_token, + admin_key=admin_key, default_headers=default_headers, - openai_options=openai_options, - ) - self.openai = AsyncOpenAI( - api_key=self._openai_api_key, - base_url=self._openai_base_url, - default_headers=self._openai_default_headers, - **self._openai_extra_kwargs, ) - # httpx client for raw HTTP calls (batch, etc.) - self._http = httpx.AsyncClient() + self._timeout = timeout + config = Configuration(host=self._gateway_root_url) + self._api = ApiClient(config) + # set_default_header is generated (untyped); seed the per-mode auth header. + api_any = cast("Any", self._api) + for name, value in self._default_headers.items(): + api_any.set_default_header(name, value) + self._http = httpx.AsyncClient(timeout=timeout) + + self._chat = ChatApi(self._api) + self._responses = ResponsesApi(self._api) + self._embeddings = EmbeddingsApi(self._api) + self._moderations = ModerationsApi(self._api) + self._rerank = RerankApi(self._api) + self._messages = MessagesApi(self._api) + self._models = ModelsApi(self._api) + self._batches = BatchesApi(self._api) + + @cached_property + def control_plane(self) -> ControlPlane: + """Typed client for the management endpoints (keys, users, budgets, pricing, usage). + + Requires an admin credential: pass ``admin_key`` (the gateway master key), + set ``GATEWAY_ADMIN_KEY``, or use ``platform_token``. + """ + if not self._admin_token: + msg = ( + "control-plane management requires an admin credential; pass " + "admin_key=... (the gateway master key) or use platform_token=..." + ) + raise OtariError(msg) + return ControlPlane(self._gateway_root_url, self._admin_token) # -- Chat completions --------------------------------------------------- @@ -133,9 +159,9 @@ async def completion( *, model: str, messages: list[dict[str, Any]], - stream: bool = ..., + stream: bool, **kwargs: Any, - ) -> ChatCompletion | AsyncStream[ChatCompletionChunk]: ... + ) -> ChatCompletion | AsyncIterator[ChatCompletionChunk]: ... async def completion( self, @@ -147,25 +173,17 @@ async def completion( ) -> Any: """Create a chat completion. - When ``stream=True`` is set, returns an async iterable of chunks. - - Args: - model: Model identifier (e.g. ``"openai:gpt-4o-mini"``). - messages: List of message dicts with ``role`` and ``content``. - stream: Whether to stream the response. - **kwargs: Additional parameters forwarded to the OpenAI API. - - Returns: - A ``ChatCompletion`` or an async stream of ``ChatCompletionChunk``. + When ``stream=True``, returns an async iterator of typed + ``ChatCompletionChunk``; otherwise a typed ``ChatCompletion``. """ - try: - params: dict[str, Any] = {"model": model, "messages": messages, **kwargs} - if stream is not None: - params["stream"] = stream - return await self.openai.chat.completions.create(**params) - except Exception as exc: - self._handle_error(exc) - raise + body = {"model": model, "messages": messages, **kwargs} + if stream: + body["stream"] = True + return self._stream("/chat/completions", body, "chat") + request = build_request(ChatCompletionRequest, body) + return await self._call( + lambda: self._chat.chat_completions_v1_chat_completions_post(request) + ) # -- Responses API ------------------------------------------------------ @@ -176,28 +194,42 @@ async def response( input: Any, # noqa: A002 stream: bool | None = None, **kwargs: Any, - ) -> Response | AsyncStream[ResponseStreamEvent]: - """Create a response using the OpenAI Responses API. + ) -> Any: + """Create a response via the OpenAI-style Responses API. + + When ``stream=True``, returns an async iterator of raw event dicts; + otherwise the parsed response object. + """ + body = {"model": model, "input": input, **kwargs} + if stream: + body["stream"] = True + return self._stream("/responses", body, "responses") + return await self._call( + lambda: self._responses.create_response_v1_responses_post(body) # type: ignore[arg-type] + ) + + # -- Messages API (Anthropic-shaped /messages) -------------------------- - Args: - model: Model identifier (e.g. ``"openai:gpt-4o-mini"``). - input: The input for the response. - stream: Whether to stream the response. - **kwargs: Additional parameters forwarded to the OpenAI API. + async def message( + self, + *, + model: str, + messages: list[dict[str, Any]], + max_tokens: int, + stream: bool | None = None, + **kwargs: Any, + ) -> Any: + """Create an Anthropic-style message via the gateway ``/messages`` endpoint. - Returns: - A ``Response`` or an async stream of ``ResponseStreamEvent``. + When ``stream=True``, returns an async iterator of raw event dicts; + otherwise a typed ``MessageResponse``. """ - try: - params: dict[str, Any] = {"model": model, "input": input, **kwargs} - if stream is not None: - params["stream"] = stream - result: Response | AsyncStream[ResponseStreamEvent] = await self.openai.responses.create(**params) - except Exception as exc: - self._handle_error(exc) - raise - else: - return result + body = {"model": model, "messages": messages, "max_tokens": max_tokens, **kwargs} + if stream: + body["stream"] = True + return self._stream("/messages", body, "messages") + request = build_request(MessagesRequest, body) + return await self._call(lambda: self._messages.create_message_v1_messages_post(request)) # -- Embeddings --------------------------------------------------------- @@ -208,177 +240,144 @@ async def embedding( input: str | list[str], # noqa: A002 **kwargs: Any, ) -> CreateEmbeddingResponse: - """Create embeddings for the given input. - - Args: - model: Model identifier (e.g. ``"openai:text-embedding-3-small"``). - input: Text or list of texts to embed. - **kwargs: Additional parameters forwarded to the OpenAI API. - - Returns: - An ``CreateEmbeddingResponse``. - """ - try: - return await self.openai.embeddings.create(model=model, input=input, **kwargs) - except Exception as exc: - self._handle_error(exc) - raise - - # -- Models ------------------------------------------------------------- + """Create embeddings for the given input.""" + request = build_request(EmbeddingRequest, {"model": model, "input": input, **kwargs}) + result = await self._call( + lambda: self._embeddings.create_embedding_v1_embeddings_post(request) + ) + return cast("CreateEmbeddingResponse", result) - async def list_models(self) -> list[Model]: - """List available models from the gateway. + # -- Moderations -------------------------------------------------------- - Returns: - A list of ``Model`` objects. - """ - try: - page = await self.openai.models.list() - except Exception as exc: - self._handle_error(exc) - raise - else: - return [model async for model in page] + async def moderation( + self, + *, + model: str, + input: str | list[str], # noqa: A002 + **kwargs: Any, + ) -> ModerationResponse: + """Classify text against the gateway moderation endpoint.""" + request = build_request(ModerationRequest, {"model": model, "input": input, **kwargs}) + result = await self._call( + lambda: self._moderations.create_moderation_v1_moderations_post(request) + ) + return cast("ModerationResponse", result) - # -- Batch operations --------------------------------------------------- + # -- Rerank ------------------------------------------------------------- - async def create_batch(self, params: CreateBatchParams) -> dict[str, Any]: - """Create a batch job. + async def rerank( + self, + *, + model: str, + query: str, + documents: list[str], + **kwargs: Any, + ) -> RerankResponse: + """Rerank ``documents`` by relevance to ``query``.""" + request = build_request( + RerankRequest, {"model": model, "query": query, "documents": documents, **kwargs} + ) + result = await self._call(lambda: self._rerank.create_rerank_v1_rerank_post(request)) + return cast("RerankResponse", result) - Args: - params: Batch creation parameters including model and requests array. + # -- Models ------------------------------------------------------------- - Returns: - The created batch object. - """ - return await self._batch_request("POST", "/batches", body=dict(params)) + async def list_models(self) -> list[ModelObject]: + """List available models from the gateway.""" + result = await self._call(self._models.list_models_v1_models_get) + return list(result.data) - async def retrieve_batch(self, batch_id: str, provider: str) -> dict[str, Any]: - """Retrieve the status of a batch job. + # -- Batch operations --------------------------------------------------- - Args: - batch_id: The ID of the batch to retrieve. - provider: The provider name (e.g. ``"openai"``). + async def create_batch(self, params: CreateBatchParams) -> Any: + """Create a batch job.""" + request = build_request(CreateBatchRequest, dict(params)) + return await self._call(lambda: self._batches.create_batch_v1_batches_post(request)) - Returns: - The batch object with current status. - """ - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - return await self._batch_request( - "GET", - f"{encoded_id}?provider={_url_encode(provider)}", + async def retrieve_batch(self, batch_id: str, provider: str) -> Any: + """Retrieve the status of a batch job.""" + return await self._call( + lambda: self._batches.retrieve_batch_v1_batches_batch_id_get(batch_id, provider) ) - async def cancel_batch(self, batch_id: str, provider: str) -> dict[str, Any]: - """Cancel a batch job. - - Args: - batch_id: The ID of the batch to cancel. - provider: The provider name (e.g. ``"openai"``). - - Returns: - The batch object with updated status. - """ - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - return await self._batch_request( - "POST", - f"{encoded_id}/cancel?provider={_url_encode(provider)}", + async def cancel_batch(self, batch_id: str, provider: str) -> Any: + """Cancel a batch job.""" + return await self._call( + lambda: self._batches.cancel_batch_v1_batches_batch_id_cancel_post(batch_id, provider) ) async def list_batches( self, provider: str, options: ListBatchesOptions | None = None, - ) -> list[dict[str, Any]]: - """List batch jobs for a provider. - - Args: - provider: The provider name (e.g. ``"openai"``). - options: Optional pagination parameters. + ) -> list[Any]: + """List batch jobs for a provider.""" + options = options or {} + result = await self._call( + lambda: self._batches.list_batches_v1_batches_get( + provider, + after=options.get("after"), + limit=options.get("limit"), + ) + ) + data = result.get("data", []) if isinstance(result, dict) else [] + return list(data) - Returns: - List of batch objects. - """ - params_parts = [f"provider={_url_encode(provider)}"] - if options: - if "after" in options: - params_parts.append(f"after={_url_encode(options['after'])}") - if "limit" in options: - params_parts.append(f"limit={options['limit']}") - query = "&".join(params_parts) - response = await self._batch_request("GET", f"/batches?{query}") - data: list[dict[str, Any]] = response.get("data", []) - return data - - async def retrieve_batch_results( - self, - batch_id: str, - provider: str, - ) -> BatchResult: + async def retrieve_batch_results(self, batch_id: str, provider: str) -> BatchResult: """Retrieve the results of a completed batch job. - Args: - batch_id: The ID of the batch. - provider: The provider name (e.g. ``"openai"``). - - Returns: - The batch results containing per-request outcomes. - Raises: - BatchNotCompleteError: If the batch is not yet complete. + BatchNotCompleteError: If the batch is not yet complete (HTTP 409). """ from otari.types import BatchResult as BatchResultType # noqa: PLC0415 from otari.types import BatchResultItem # noqa: PLC0415 - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - data = await self._batch_request( - "GET", - f"{encoded_id}/results?provider={_url_encode(provider)}", + data = await self._call( + lambda: self._batches.retrieve_batch_results_v1_batches_batch_id_results_get( + batch_id, provider + ) ) + results = data.get("results", []) if isinstance(data, dict) else [] items = [ BatchResultItem( custom_id=entry["custom_id"], result=entry.get("result"), error=entry.get("error"), ) - for entry in data.get("results", []) + for entry in results ] return BatchResultType(results=items) - # -- Batch HTTP helpers ------------------------------------------------- + # -- Internal helpers --------------------------------------------------- - async def _batch_request( - self, - method: str, - path: str, - *, - body: dict[str, Any] | None = None, - ) -> dict[str, Any]: - """Make a direct HTTP request for batch operations. + async def _call(self, fn: Callable[[], Any]) -> Any: + """Run a synchronous generated call off-thread, mapping its errors.""" + try: + return await asyncio.to_thread(fn) + except ApiException as exc: + raise self._map_api_exception(exc) from exc - Unlike completion/embedding which use ``self.openai``, batch methods - use direct HTTP because the gateway batch API has a custom JSON format. - """ + async def _stream(self, path: str, body: dict[str, Any], kind: Any) -> AsyncIterator[Any]: + """Open a raw async streaming POST and yield parsed SSE chunks.""" url = f"{self._base_url}{path}" - response = await self._http.request( - method, - url, - headers=self._build_batch_headers(), - json=body if body is not None else None, - ) - - if not response.is_success: - self._map_batch_error(response) - - result: dict[str, Any] = response.json() - return result + headers = { + "Content-Type": "application/json", + "Accept": "text/event-stream", + **self._default_headers, + } + async with self._http.stream("POST", url, json=body, headers=headers) as response: + if response.status_code >= 400: + raw = await response.aread() + raise self._map_streaming_response(response, raw) + async for chunk in aiter_sse(response, kind): + yield chunk # -- Cleanup ------------------------------------------------------------ async def close(self) -> None: """Close the underlying HTTP clients.""" await self._http.aclose() - await self.openai.close() + await asyncio.to_thread(cast("Any", self._api).__exit__, None, None, None) async def __aenter__(self) -> AsyncOtariClient: return self diff --git a/src/otari/client.py b/src/otari/client.py index c8f4da5..d64ed1b 100644 --- a/src/otari/client.py +++ b/src/otari/client.py @@ -1,8 +1,12 @@ """OtariClient: synchronous Python client for the otari gateway. -Wraps the OpenAI Python SDK (``OpenAI``), adding gateway-specific auth handling -and error mapping for platform mode. For an asynchronous client, see -:class:`~otari.async_client.AsyncOtariClient`. +Option C: a thin, ergonomic shell over the OpenAPI-generated core in +:mod:`otari._client`. Non-streaming calls go through the generated typed API +classes (returning typed models such as ``ChatCompletion``); streaming calls go +through the hand-written SSE shim in :mod:`otari._streaming`; generated +``ApiException``\\s are mapped to the typed errors in :mod:`otari.errors`. + +For an asynchronous client, see :class:`~otari.async_client.AsyncOtariClient`. Example:: @@ -22,25 +26,41 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, overload +from functools import cached_property +from typing import TYPE_CHECKING, Any, cast, overload import httpx -from openai import OpenAI -from otari._base import _BaseOtariClient, _url_encode +from otari._base import _BaseOtariClient, build_request +from otari._client import ApiClient, Configuration +from otari._client.api.batches_api import BatchesApi +from otari._client.api.chat_api import ChatApi +from otari._client.api.embeddings_api import EmbeddingsApi +from otari._client.api.messages_api import MessagesApi +from otari._client.api.models_api import ModelsApi +from otari._client.api.moderations_api import ModerationsApi +from otari._client.api.rerank_api import RerankApi +from otari._client.api.responses_api import ResponsesApi +from otari._client.exceptions import ApiException +from otari._client.models.chat_completion_request import ChatCompletionRequest +from otari._client.models.create_batch_request import CreateBatchRequest +from otari._client.models.embedding_request import EmbeddingRequest +from otari._client.models.messages_request import MessagesRequest +from otari._client.models.moderation_request import ModerationRequest +from otari._client.models.rerank_request import RerankRequest +from otari._streaming import iter_sse +from otari.control_plane import ControlPlane +from otari.errors import OtariError if TYPE_CHECKING: - from openai import Stream - from openai.types import CreateEmbeddingResponse, Model - from openai.types.chat import ( - ChatCompletion, - ChatCompletionChunk, - ) - from openai.types.responses import ( - Response, - ResponseStreamEvent, - ) - + from collections.abc import Callable, Iterator + + from otari._client.models.chat_completion import ChatCompletion + from otari._client.models.chat_completion_chunk import ChatCompletionChunk + from otari._client.models.create_embedding_response import CreateEmbeddingResponse + from otari._client.models.model_object import ModelObject + from otari._client.models.moderation_response import ModerationResponse + from otari._client.models.rerank_response import RerankResponse from otari.types import ( BatchResult, CreateBatchParams, @@ -51,71 +71,82 @@ class OtariClient(_BaseOtariClient): """Synchronous client for the otari gateway. - Supports two authentication modes (mirroring the TypeScript SDK and - the Python ``GatewayProvider``): + Supports two authentication modes (mirroring the TypeScript SDK and the + Python ``GatewayProvider``): - - **Platform mode**: A Bearer token is sent in the standard Authorization - header. Errors are mapped to typed otari exceptions. - - **Non-platform mode**: An API key is sent via a custom ``Otari-Key`` - header. Errors from the OpenAI SDK pass through unmodified. + - **Platform mode**: a Bearer token is sent in the standard ``Authorization`` + header (activated by ``platform_token`` / ``OTARI_AI_TOKEN``). + - **Non-platform mode**: an API key is sent via the custom ``Otari-Key`` + header (``api_key`` / ``GATEWAY_API_KEY``). - For asynchronous usage, see :class:`~otari.async_client.AsyncOtariClient`. + In both modes, gateway errors are mapped to the typed exceptions in + :mod:`otari.errors`. Args: api_base: Base URL of the gateway (e.g. ``"http://localhost:8000"``). - Falls back to the ``GATEWAY_API_BASE`` environment variable. In - platform mode it defaults to the hosted gateway at - ``https://api.otari.ai`` when neither is supplied. - api_key: API key for non-platform mode. - Falls back to ``GATEWAY_API_KEY`` env var. - platform_token: Platform token for platform mode. - Falls back to the canonical ``OTARI_AI_TOKEN`` env var (or the - legacy ``GATEWAY_PLATFORM_TOKEN`` alias). - default_headers: Additional default headers to send with every request. - openai_options: Extra keyword arguments forwarded to the underlying - ``OpenAI`` constructor. - - Example:: - - client = OtariClient( - api_base="http://localhost:8000", - platform_token="tk_xxx", - ) - - response = client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "Hello!"}], - ) - print(response.choices[0].message.content) + Falls back to ``GATEWAY_API_BASE``. In platform mode it defaults to + the hosted gateway at ``https://api.otari.ai`` when neither is set. + api_key: API key for non-platform mode. Falls back to ``GATEWAY_API_KEY``. + platform_token: Platform token for platform mode. Falls back to the + canonical ``OTARI_AI_TOKEN`` (or legacy ``GATEWAY_PLATFORM_TOKEN``). + admin_key: Master/admin key for the control-plane endpoints. Falls back + to ``GATEWAY_ADMIN_KEY`` (or the platform token in platform mode). + default_headers: Additional default headers sent with every request. + timeout: Per-request timeout (seconds) for the streaming shim. """ - openai: OpenAI - """The underlying OpenAI client instance.""" - def __init__( self, api_base: str | None = None, *, api_key: str | None = None, platform_token: str | None = None, + admin_key: str | None = None, default_headers: dict[str, str] | None = None, - openai_options: dict[str, Any] | None = None, + timeout: float | None = None, ) -> None: super().__init__( api_base, api_key=api_key, platform_token=platform_token, + admin_key=admin_key, default_headers=default_headers, - openai_options=openai_options, ) - self.openai = OpenAI( - api_key=self._openai_api_key, - base_url=self._openai_base_url, - default_headers=self._openai_default_headers, - **self._openai_extra_kwargs, - ) - # httpx client for raw HTTP calls (batch, etc.) - self._http = httpx.Client() + self._timeout = timeout + config = Configuration(host=self._gateway_root_url) + self._api = ApiClient(config) + # set_default_header is generated (untyped); seed the per-mode auth header. + api_any = cast("Any", self._api) + for name, value in self._default_headers.items(): + api_any.set_default_header(name, value) + # Raw httpx client used only for the SSE streaming shim (the generated + # core buffers and cannot stream). + self._http = httpx.Client(timeout=timeout) + + self._chat = ChatApi(self._api) + self._responses = ResponsesApi(self._api) + self._embeddings = EmbeddingsApi(self._api) + self._moderations = ModerationsApi(self._api) + self._rerank = RerankApi(self._api) + self._messages = MessagesApi(self._api) + self._models = ModelsApi(self._api) + self._batches = BatchesApi(self._api) + + @cached_property + def control_plane(self) -> ControlPlane: + """Typed client for the management endpoints (keys, users, budgets, pricing, usage). + + Requires an admin credential: pass ``admin_key`` (the gateway master key), + set ``GATEWAY_ADMIN_KEY``, or use ``platform_token`` (which doubles as the + control-plane bearer in platform mode). + """ + if not self._admin_token: + msg = ( + "control-plane management requires an admin credential; pass " + "admin_key=... (the gateway master key) or use platform_token=..." + ) + raise OtariError(msg) + return ControlPlane(self._gateway_root_url, self._admin_token) # -- Chat completions --------------------------------------------------- @@ -135,9 +166,9 @@ def completion( *, model: str, messages: list[dict[str, Any]], - stream: bool = ..., + stream: bool, **kwargs: Any, - ) -> ChatCompletion | Stream[ChatCompletionChunk]: ... + ) -> ChatCompletion | Iterator[ChatCompletionChunk]: ... def completion( self, @@ -149,25 +180,24 @@ def completion( ) -> Any: """Create a chat completion. - When ``stream=True`` is set, returns an iterable of chunks. + When ``stream=True``, returns an iterator of typed + :class:`~otari._client.models.chat_completion_chunk.ChatCompletionChunk`. + Otherwise returns a typed + :class:`~otari._client.models.chat_completion.ChatCompletion`. Args: model: Model identifier (e.g. ``"openai:gpt-4o-mini"``). messages: List of message dicts with ``role`` and ``content``. stream: Whether to stream the response. - **kwargs: Additional parameters forwarded to the OpenAI API. - - Returns: - A ``ChatCompletion`` or a stream of ``ChatCompletionChunk``. + **kwargs: Additional parameters modeled by the gateway chat schema + (e.g. ``temperature``, ``tools``, ``guardrails``). """ - try: - params: dict[str, Any] = {"model": model, "messages": messages, **kwargs} - if stream is not None: - params["stream"] = stream - return self.openai.chat.completions.create(**params) - except Exception as exc: - self._handle_error(exc) - raise + body = {"model": model, "messages": messages, **kwargs} + if stream: + body["stream"] = True + return self._stream("/chat/completions", body, "chat") + request = build_request(ChatCompletionRequest, body) + return self._call(lambda: self._chat.chat_completions_v1_chat_completions_post(request)) # -- Responses API ------------------------------------------------------ @@ -178,28 +208,51 @@ def response( input: Any, # noqa: A002 stream: bool | None = None, **kwargs: Any, - ) -> Response | Stream[ResponseStreamEvent]: - """Create a response using the OpenAI Responses API. + ) -> Any: + """Create a response via the OpenAI-style Responses API. + + When ``stream=True``, returns an iterator of raw response-stream event + dicts (the gateway's responses event stream has no single typed chunk + model). Otherwise returns the parsed response object. + """ + body = {"model": model, "input": input, **kwargs} + if stream: + body["stream"] = True + return self._stream("/responses", body, "responses") + return self._call(lambda: self._responses.create_response_v1_responses_post(body)) # type: ignore[arg-type] + + # -- Messages API (Anthropic-shaped /messages) -------------------------- + + def message( + self, + *, + model: str, + messages: list[dict[str, Any]], + max_tokens: int, + stream: bool | None = None, + **kwargs: Any, + ) -> Any: + """Create an Anthropic-style message via the gateway ``/messages`` endpoint. + + This endpoint has no OpenAI-SDK seam and was previously missing from the + SDK. When ``stream=True``, returns an iterator of raw message-stream + event dicts (no single typed chunk model exists). Otherwise returns a + typed :class:`~otari._client.models.message_response.MessageResponse`. Args: - model: Model identifier (e.g. ``"openai:gpt-4o-mini"``). - input: The input for the response. + model: Model identifier (e.g. ``"anthropic:claude-3-5-sonnet"``). + messages: Anthropic-style message list. + max_tokens: Maximum tokens to generate (required by ``/messages``). stream: Whether to stream the response. - **kwargs: Additional parameters forwarded to the OpenAI API. - - Returns: - A ``Response`` or a stream of ``ResponseStreamEvent``. + **kwargs: Additional ``/messages`` parameters (``system``, + ``temperature``, ``tools``, ``thinking``, ...). """ - try: - params: dict[str, Any] = {"model": model, "input": input, **kwargs} - if stream is not None: - params["stream"] = stream - result: Response | Stream[ResponseStreamEvent] = self.openai.responses.create(**params) - except Exception as exc: - self._handle_error(exc) - raise - else: - return result + body = {"model": model, "messages": messages, "max_tokens": max_tokens, **kwargs} + if stream: + body["stream"] = True + return self._stream("/messages", body, "messages") + request = build_request(MessagesRequest, body) + return self._call(lambda: self._messages.create_message_v1_messages_post(request)) # -- Embeddings --------------------------------------------------------- @@ -210,177 +263,143 @@ def embedding( input: str | list[str], # noqa: A002 **kwargs: Any, ) -> CreateEmbeddingResponse: - """Create embeddings for the given input. + """Create embeddings for the given input.""" + request = build_request(EmbeddingRequest, {"model": model, "input": input, **kwargs}) + result = self._call(lambda: self._embeddings.create_embedding_v1_embeddings_post(request)) + return cast("CreateEmbeddingResponse", result) - Args: - model: Model identifier (e.g. ``"openai:text-embedding-3-small"``). - input: Text or list of texts to embed. - **kwargs: Additional parameters forwarded to the OpenAI API. + # -- Moderations -------------------------------------------------------- - Returns: - An ``CreateEmbeddingResponse``. - """ - try: - return self.openai.embeddings.create(model=model, input=input, **kwargs) - except Exception as exc: - self._handle_error(exc) - raise - - # -- Models ------------------------------------------------------------- - - def list_models(self) -> list[Model]: - """List available models from the gateway. - - Returns: - A list of ``Model`` objects. - """ - try: - page = self.openai.models.list() - except Exception as exc: - self._handle_error(exc) - raise - else: - return list(page) + def moderation( + self, + *, + model: str, + input: str | list[str], # noqa: A002 + **kwargs: Any, + ) -> ModerationResponse: + """Classify text against the gateway moderation endpoint.""" + request = build_request(ModerationRequest, {"model": model, "input": input, **kwargs}) + result = self._call(lambda: self._moderations.create_moderation_v1_moderations_post(request)) + return cast("ModerationResponse", result) - # -- Batch operations --------------------------------------------------- + # -- Rerank ------------------------------------------------------------- - def create_batch(self, params: CreateBatchParams) -> dict[str, Any]: - """Create a batch job. + def rerank( + self, + *, + model: str, + query: str, + documents: list[str], + **kwargs: Any, + ) -> RerankResponse: + """Rerank ``documents`` by relevance to ``query``.""" + request = build_request( + RerankRequest, {"model": model, "query": query, "documents": documents, **kwargs} + ) + result = self._call(lambda: self._rerank.create_rerank_v1_rerank_post(request)) + return cast("RerankResponse", result) - Args: - params: Batch creation parameters including model and requests array. + # -- Models ------------------------------------------------------------- - Returns: - The created batch object. - """ - return self._batch_request("POST", "/batches", body=dict(params)) + def list_models(self) -> list[ModelObject]: + """List available models from the gateway.""" + result = self._call(self._models.list_models_v1_models_get) + return list(result.data) - def retrieve_batch(self, batch_id: str, provider: str) -> dict[str, Any]: - """Retrieve the status of a batch job. + # -- Batch operations --------------------------------------------------- - Args: - batch_id: The ID of the batch to retrieve. - provider: The provider name (e.g. ``"openai"``). + def create_batch(self, params: CreateBatchParams) -> Any: + """Create a batch job.""" + request = build_request(CreateBatchRequest, dict(params)) + return self._call(lambda: self._batches.create_batch_v1_batches_post(request)) - Returns: - The batch object with current status. - """ - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - return self._batch_request( - "GET", - f"{encoded_id}?provider={_url_encode(provider)}", + def retrieve_batch(self, batch_id: str, provider: str) -> Any: + """Retrieve the status of a batch job.""" + return self._call( + lambda: self._batches.retrieve_batch_v1_batches_batch_id_get(batch_id, provider) ) - def cancel_batch(self, batch_id: str, provider: str) -> dict[str, Any]: - """Cancel a batch job. - - Args: - batch_id: The ID of the batch to cancel. - provider: The provider name (e.g. ``"openai"``). - - Returns: - The batch object with updated status. - """ - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - return self._batch_request( - "POST", - f"{encoded_id}/cancel?provider={_url_encode(provider)}", + def cancel_batch(self, batch_id: str, provider: str) -> Any: + """Cancel a batch job.""" + return self._call( + lambda: self._batches.cancel_batch_v1_batches_batch_id_cancel_post(batch_id, provider) ) def list_batches( self, provider: str, options: ListBatchesOptions | None = None, - ) -> list[dict[str, Any]]: - """List batch jobs for a provider. - - Args: - provider: The provider name (e.g. ``"openai"``). - options: Optional pagination parameters. + ) -> list[Any]: + """List batch jobs for a provider.""" + options = options or {} + result = self._call( + lambda: self._batches.list_batches_v1_batches_get( + provider, + after=options.get("after"), + limit=options.get("limit"), + ) + ) + data = result.get("data", []) if isinstance(result, dict) else [] + return list(data) - Returns: - List of batch objects. - """ - params_parts = [f"provider={_url_encode(provider)}"] - if options: - if "after" in options: - params_parts.append(f"after={_url_encode(options['after'])}") - if "limit" in options: - params_parts.append(f"limit={options['limit']}") - query = "&".join(params_parts) - response = self._batch_request("GET", f"/batches?{query}") - data: list[dict[str, Any]] = response.get("data", []) - return data - - def retrieve_batch_results( - self, - batch_id: str, - provider: str, - ) -> BatchResult: + def retrieve_batch_results(self, batch_id: str, provider: str) -> BatchResult: """Retrieve the results of a completed batch job. - Args: - batch_id: The ID of the batch. - provider: The provider name (e.g. ``"openai"``). - - Returns: - The batch results containing per-request outcomes. - Raises: - BatchNotCompleteError: If the batch is not yet complete. + BatchNotCompleteError: If the batch is not yet complete (HTTP 409). """ from otari.types import BatchResult as BatchResultType # noqa: PLC0415 from otari.types import BatchResultItem # noqa: PLC0415 - encoded_id = httpx.URL(f"/batches/{batch_id}").raw_path.decode() - data = self._batch_request( - "GET", - f"{encoded_id}/results?provider={_url_encode(provider)}", + data = self._call( + lambda: self._batches.retrieve_batch_results_v1_batches_batch_id_results_get( + batch_id, provider + ) ) + results = data.get("results", []) if isinstance(data, dict) else [] items = [ BatchResultItem( custom_id=entry["custom_id"], result=entry.get("result"), error=entry.get("error"), ) - for entry in data.get("results", []) + for entry in results ] return BatchResultType(results=items) - # -- Batch HTTP helpers ------------------------------------------------- + # -- Internal helpers --------------------------------------------------- - def _batch_request( - self, - method: str, - path: str, - *, - body: dict[str, Any] | None = None, - ) -> dict[str, Any]: - """Make a direct HTTP request for batch operations. + def _call(self, fn: Callable[[], Any]) -> Any: + """Run a generated call, mapping its ``ApiException`` to a typed error.""" + try: + return fn() + except ApiException as exc: + raise self._map_api_exception(exc) from exc - Unlike completion/embedding which use ``self.openai``, batch methods - use direct HTTP because the gateway batch API has a custom JSON format. + def _stream(self, path: str, body: dict[str, Any], kind: Any) -> Iterator[Any]: + """Open a raw streaming POST and yield parsed SSE chunks. + + The generated core buffers responses, so streaming is hand-written here: + a raw httpx streaming request parsed by :mod:`otari._streaming`. """ url = f"{self._base_url}{path}" - response = self._http.request( - method, - url, - headers=self._build_batch_headers(), - json=body if body is not None else None, - ) - - if not response.is_success: - self._map_batch_error(response) - - result: dict[str, Any] = response.json() - return result + headers = { + "Content-Type": "application/json", + "Accept": "text/event-stream", + **self._default_headers, + } + with self._http.stream("POST", url, json=body, headers=headers) as response: + if response.status_code >= 400: + raw = response.read() + raise self._map_streaming_response(response, raw) + yield from iter_sse(response, kind) # -- Cleanup ------------------------------------------------------------ def close(self) -> None: """Close the underlying HTTP clients.""" self._http.close() - self.openai.close() + cast("Any", self._api).__exit__(None, None, None) def __enter__(self) -> OtariClient: return self diff --git a/src/otari/control_plane.py b/src/otari/control_plane.py new file mode 100644 index 0000000..27a37ea --- /dev/null +++ b/src/otari/control_plane.py @@ -0,0 +1,60 @@ +"""Typed client for the gateway control-plane (management) endpoints. + +Wraps the OpenAPI-generated :mod:`otari._client` core (the same core that backs +the inference path under Option C). The control-plane endpoints (API keys, +users, budgets, pricing, usage) authenticate with +``Authorization: Bearer ``, which is distinct from the +``Otari-Key`` virtual key used for inference. Obtain an instance via +:attr:`otari.OtariClient.control_plane`. +""" + +from __future__ import annotations + +from functools import cached_property +from typing import Any, cast + +from otari import _client as _cp +from otari._client.api.budgets_api import BudgetsApi +from otari._client.api.keys_api import KeysApi +from otari._client.api.pricing_api import PricingApi +from otari._client.api.usage_api import UsageApi +from otari._client.api.users_api import UsersApi + + +class ControlPlane: + """Accessors for the gateway management endpoints, sharing one authenticated client. + + Method names on the underlying API objects are generator-derived (for + example ``keys.create_key_v1_keys_post(...)``); friendlier aliases are a + planned follow-up. + """ + + def __init__(self, base_url: str, bearer_token: str) -> None: + config = _cp.Configuration(host=base_url) + # The generated client is intentionally not type-checked here; treat it + # as ``Any`` so strict mypy does not flag its untyped methods. + self._api_client = cast("Any", _cp.ApiClient(config)) + self._api_client.set_default_header("Authorization", f"Bearer {bearer_token}") + + @cached_property + def keys(self) -> KeysApi: + return KeysApi(self._api_client) + + @cached_property + def users(self) -> UsersApi: + return UsersApi(self._api_client) + + @cached_property + def budgets(self) -> BudgetsApi: + return BudgetsApi(self._api_client) + + @cached_property + def pricing(self) -> PricingApi: + return PricingApi(self._api_client) + + @cached_property + def usage(self) -> UsageApi: + return UsageApi(self._api_client) + + def close(self) -> None: + self._api_client.__exit__(None, None, None) diff --git a/src/otari/types.py b/src/otari/types.py index 578dfd3..15b1a02 100644 --- a/src/otari/types.py +++ b/src/otari/types.py @@ -1,6 +1,8 @@ """Configuration and type re-exports for the otari gateway client. -Re-exports OpenAI SDK types so consumers don't need to import ``openai`` directly. +Re-exports the OpenAPI-generated response/chunk models from +:mod:`otari._client` so consumers can name them without reaching into the +generated package, plus the SDK's own batch/option types. """ from __future__ import annotations @@ -9,21 +11,18 @@ from typing import Any, TypedDict # --------------------------------------------------------------------------- -# Re-export OpenAI types that callers interact with directly. -# These use explicit `as` aliases to make the re-exports public per PEP 484. -# The TC002 / PLC0414 warnings are intentionally suppressed because these -# imports exist solely for re-export. +# Re-export the generated models that callers interact with directly. +# Explicit ``as`` aliases make these public re-exports per PEP 484. # --------------------------------------------------------------------------- -from openai import AsyncStream as AsyncStream # noqa: PLC0414 -from openai import Stream as Stream # noqa: PLC0414 -from openai.types import CreateEmbeddingResponse as CreateEmbeddingResponse # noqa: PLC0414 -from openai.types import EmbeddingCreateParams as EmbeddingCreateParams # noqa: PLC0414 -from openai.types import Model as Model # noqa: PLC0414 -from openai.types.chat import ChatCompletion as ChatCompletion # noqa: PLC0414, TC002 -from openai.types.chat import ChatCompletionChunk as ChatCompletionChunk # noqa: PLC0414 -from openai.types.chat import ChatCompletionMessageParam as ChatCompletionMessageParam # noqa: PLC0414 -from openai.types.responses import Response as Response # noqa: PLC0414 -from openai.types.responses import ResponseStreamEvent as ResponseStreamEvent # noqa: PLC0414 +from otari._client.models.chat_completion import ChatCompletion as ChatCompletion # noqa: PLC0414 +from otari._client.models.chat_completion_chunk import ChatCompletionChunk as ChatCompletionChunk # noqa: PLC0414 +from otari._client.models.create_embedding_response import ( + CreateEmbeddingResponse as CreateEmbeddingResponse, # noqa: PLC0414 +) +from otari._client.models.message_response import MessageResponse as MessageResponse # noqa: PLC0414 +from otari._client.models.model_object import ModelObject as ModelObject # noqa: PLC0414 +from otari._client.models.moderation_response import ModerationResponse as ModerationResponse # noqa: PLC0414 +from otari._client.models.rerank_response import RerankResponse as RerankResponse # noqa: PLC0414 # --------------------------------------------------------------------------- # Client options @@ -34,7 +33,7 @@ class OtariClientOptions(TypedDict, total=False): """Options for constructing an :class:`~otari.client.OtariClient`. Auth resolution order (mirrors the TypeScript SDK / Python GatewayProvider): - 1. Explicit ``platform_token`` -> platform mode (Bearer token in Authorization header) + 1. Explicit ``platform_token`` -> platform mode (Bearer in Authorization header) 2. ``OTARI_AI_TOKEN`` (or legacy ``GATEWAY_PLATFORM_TOKEN``) env var (when no ``api_key``) -> platform mode 3. ``api_key`` or ``GATEWAY_API_KEY`` env var -> non-platform mode (``Otari-Key`` header) @@ -46,24 +45,20 @@ class OtariClientOptions(TypedDict, total=False): """ api_base: str - """Base URL of the gateway (e.g. ``"http://localhost:8000"``). - - Defaults to ``https://api.otari.ai`` in platform mode.""" + """Base URL of the gateway (defaults to ``https://api.otari.ai`` in platform mode).""" api_key: str """API key for non-platform mode. Sent via ``Otari-Key: Bearer ``.""" platform_token: str - """Platform token for platform mode. Sent as Bearer in the Authorization header. + """Platform token for platform mode. Sent as Bearer in the Authorization header.""" - Falls back to ``OTARI_AI_TOKEN`` (or legacy ``GATEWAY_PLATFORM_TOKEN``).""" + admin_key: str + """Master/admin key for the control-plane endpoints.""" default_headers: dict[str, str] """Additional default headers to send with every request.""" - openai_options: dict[str, Any] - """Extra options forwarded to the underlying ``AsyncOpenAI`` constructor.""" - # --------------------------------------------------------------------------- # Batch types @@ -105,7 +100,7 @@ class BatchResultItem: """Result of a single request within a batch.""" custom_id: str - result: ChatCompletion | None = None + result: dict[str, Any] | None = None error: BatchResultError | None = None diff --git a/tests/integration/README.md b/tests/integration/README.md new file mode 100644 index 0000000..e0e35f8 --- /dev/null +++ b/tests/integration/README.md @@ -0,0 +1,57 @@ +# Control-plane integration tests + +Strategy for verifying each control-plane endpoint (keys, users, budgets, +pricing, usage) end to end against a real gateway. `test_control_plane_generated.py` +is the Python reference; the same shape applies to the TS / Go / Rust SDKs. + +## Why this works without Docker or provider keys + +Control-plane endpoints are pure gateway + DB operations; they never call an LLM +provider. So a test can run the gateway on **SQLite** with just a **master key**: +no Postgres, no provider credentials. The fixture starts `gateway serve +--database-url sqlite:///... --master-key ... --auto-migrate`, waits for +`/health`, and tears it down. + +## Auth (verified) + +Management endpoints authenticate with `Authorization: Bearer `. +The `Otari-Key` header is for the virtual API keys used on inference endpoints +and returns 401 here. The integrated client must send Bearer for control-plane +calls. + +## Per-endpoint coverage + +Each resource is exercised through its full lifecycle, with extra attention on +the create/POST operations (the manually-integrated surface): + +| Resource | create | get | list | update | delete | extra | +|----------|--------|-----|------|--------|--------|-------| +| budgets | ✓ (asserts `budget_id`, `max_budget`) | ✓ | ✓ | ✓ | ✓ → 404 | | +| users | ✓ | ✓ | ✓ | ✓ | ✓ → 404 | `GET .../usage` | +| keys | ✓ (asserts the one-time `key` secret is returned) | ✓ | ✓ | ✓ | ✓ → 404 | | +| pricing | ✓ | ✓ | ✓ | — | ✓ → 404 | `GET .../history` | +| usage | — | — | ✓ | — | — | | + +Identifier fields differ per resource (gateway convention): `id` (keys), +`user_id` (users), `budget_id` (budgets), `model_key` (pricing). + +## Other languages (same pattern) + +- **TypeScript** (vitest): a `beforeAll` spawns the gateway via `child_process`, + polls `/health`; tests use the generated fetch client with an `Authorization` + header; `afterAll` kills it. +- **Go** (`testing`): `TestMain` starts the gateway with `os/exec`, waits on + `/health`; table-driven lifecycle tests per resource; defer cleanup. +- **Rust** (`tokio::test` + a shared harness): spawn the gateway with + `std::process::Command`, await `/health`; reqwest-based generated client. + +## Running + +```bash +# gateway must be importable as a console script (or set OTARI_GATEWAY_CMD) +OTARI_GATEWAY_CMD="gateway" pytest tests/integration/test_control_plane_generated.py -v +``` + +These tests target the generated client at `src/otari/_generated` for now. Once +it is wired into the public client, point the imports at the public surface so +the tests also cover the manual integration layer. diff --git a/tests/integration/test_control_plane_generated.py b/tests/integration/test_control_plane_generated.py new file mode 100644 index 0000000..4125ccf --- /dev/null +++ b/tests/integration/test_control_plane_generated.py @@ -0,0 +1,186 @@ +"""Integration tests for the control-plane surface against a live gateway. + +These drive ``OtariClient.control_plane`` through a full CRUD lifecycle for every +management endpoint (keys, users, budgets, pricing, usage), exercising the manual +wiring (Bearer auth + the generated client) end to end. They start a real gateway +on SQLite with a master key, so no provider credentials or database server are +needed: control-plane endpoints never call an LLM provider. + +Run requirements: +- The ``gateway`` console script on PATH (set ``OTARI_GATEWAY_CMD`` to override), + e.g. ``pip install otari-gateway`` in CI. + +Auth note, verified against the gateway: management endpoints authenticate via +``Authorization: Bearer ``, NOT the ``Otari-Key`` virtual-key header +used for inference. ``OtariClient`` sends the former when given ``admin_key``. +""" + +from __future__ import annotations + +import contextlib +import os +import shutil +import socket +import subprocess +import tempfile +import time +import urllib.error +import urllib.request +from collections.abc import Iterator + +import pytest + +from otari import OtariClient +from otari._client.exceptions import NotFoundException +from otari._client.models.create_budget_request import CreateBudgetRequest +from otari._client.models.create_key_request import CreateKeyRequest +from otari._client.models.create_user_request import CreateUserRequest +from otari._client.models.set_pricing_request import SetPricingRequest +from otari._client.models.update_budget_request import UpdateBudgetRequest +from otari._client.models.update_key_request import UpdateKeyRequest +from otari._client.models.update_user_request import UpdateUserRequest + +pytestmark = pytest.mark.integration + +MASTER_KEY = "itest-master-key" + + +def _free_port() -> int: + with socket.socket() as sock: + sock.bind(("127.0.0.1", 0)) + return int(sock.getsockname()[1]) + + +def _wait_healthy(base_url: str, timeout: float = 30.0) -> None: + deadline = time.time() + timeout + while time.time() < deadline: + with contextlib.suppress(urllib.error.URLError, ConnectionError): + with urllib.request.urlopen(f"{base_url}/health", timeout=2) as resp: + if resp.status == 200: + return + time.sleep(0.3) + raise RuntimeError(f"gateway did not become healthy at {base_url}") + + +@pytest.fixture(scope="module") +def gateway_url() -> Iterator[str]: + cmd = os.environ.get("OTARI_GATEWAY_CMD", "gateway").split() + if shutil.which(cmd[0]) is None: + pytest.skip(f"gateway command '{cmd[0]}' not found; set OTARI_GATEWAY_CMD (e.g. pip install the gateway)") + port = _free_port() + db_path = tempfile.NamedTemporaryFile(suffix=".db", delete=False).name + proc = subprocess.Popen( + [ + *cmd, "serve", + "--database-url", f"sqlite:///{db_path}", + "--master-key", MASTER_KEY, + "--host", "127.0.0.1", "--port", str(port), + "--auto-migrate", "--log-level", "40", + ], + stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, + ) + base_url = f"http://127.0.0.1:{port}" + try: + _wait_healthy(base_url) + yield base_url + finally: + proc.terminate() + with contextlib.suppress(subprocess.TimeoutExpired): + proc.wait(timeout=10) + with contextlib.suppress(FileNotFoundError): + os.unlink(db_path) + + +@pytest.fixture +def client(gateway_url: str) -> Iterator[OtariClient]: + otari = OtariClient(api_base=gateway_url, admin_key=MASTER_KEY) + try: + yield otari + finally: + otari.control_plane.close() + + +def test_budgets_lifecycle(client: OtariClient) -> None: + api = client.control_plane.budgets + created = api.create_budget_v1_budgets_post(CreateBudgetRequest(max_budget=100.0, budget_duration_sec=3600)) + assert created.budget_id + assert created.max_budget == 100.0 + bid = created.budget_id + + assert any(b.budget_id == bid for b in api.list_budgets_v1_budgets_get()) + assert api.get_budget_v1_budgets_budget_id_get(bid).budget_id == bid + + updated = api.update_budget_v1_budgets_budget_id_patch(bid, UpdateBudgetRequest(max_budget=250.0)) + assert updated.max_budget == 250.0 + + api.delete_budget_v1_budgets_budget_id_delete(bid) + with pytest.raises(NotFoundException): + api.get_budget_v1_budgets_budget_id_get(bid) + + +def test_users_lifecycle(client: OtariClient) -> None: + api = client.control_plane.users + created = api.create_user_v1_users_post(CreateUserRequest(user_id="itest-user", alias="Alice")) + assert created.user_id == "itest-user" + assert created.alias == "Alice" + + assert any(u.user_id == "itest-user" for u in api.list_users_v1_users_get()) + assert api.get_user_v1_users_user_id_get("itest-user").user_id == "itest-user" + + updated = api.update_user_v1_users_user_id_patch("itest-user", UpdateUserRequest(alias="Alice2")) + assert updated.alias == "Alice2" + + api.get_user_usage_v1_users_user_id_usage_get("itest-user") + + api.delete_user_v1_users_user_id_delete("itest-user") + with pytest.raises(NotFoundException): + api.get_user_v1_users_user_id_get("itest-user") + + +def test_keys_lifecycle_returns_secret_on_create(client: OtariClient) -> None: + api = client.control_plane.keys + created = api.create_key_v1_keys_post(CreateKeyRequest(key_name="itest-key")) + assert created.id + # The one-time key value must be present on create (manually-created surface). + assert getattr(created, "key", None), "create_key must return the key secret" + kid = created.id + + assert any(k.id == kid for k in api.list_keys_v1_keys_get()) + assert api.get_key_v1_keys_key_id_get(kid).id == kid + + updated = api.update_key_v1_keys_key_id_patch(kid, UpdateKeyRequest(key_name="itest-key-renamed")) + assert updated.key_name == "itest-key-renamed" + + api.delete_key_v1_keys_key_id_delete(kid) + with pytest.raises(NotFoundException): + api.get_key_v1_keys_key_id_get(kid) + + +def test_pricing_lifecycle(client: OtariClient) -> None: + api = client.control_plane.pricing + model_key = "openai:itest-model" + created = api.set_pricing_v1_pricing_post( + SetPricingRequest(model_key=model_key, input_price_per_million=1.0, output_price_per_million=2.0) + ) + assert created.model_key == model_key + + assert any(p.model_key == model_key for p in api.list_pricing_v1_pricing_get()) + assert api.get_pricing_v1_pricing_model_key_get(model_key).model_key == model_key + assert api.get_pricing_history_v1_pricing_model_key_history_get(model_key) is not None + + api.delete_pricing_v1_pricing_model_key_delete(model_key) + with pytest.raises(NotFoundException): + api.get_pricing_v1_pricing_model_key_get(model_key) + + +def test_usage_is_readable(client: OtariClient) -> None: + # Fresh gateway: usage list is readable, proving the typed GET works through the client. + assert client.control_plane.usage.list_usage_v1_usage_get() is not None + + +def test_control_plane_requires_admin_credential(gateway_url: str) -> None: + from otari import OtariError + + no_admin = OtariClient(api_base=gateway_url, api_key="some-virtual-key") + with pytest.raises(OtariError): + _ = no_admin.control_plane diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py new file mode 100644 index 0000000..c3f028a --- /dev/null +++ b/tests/unit/conftest.py @@ -0,0 +1,108 @@ +"""Shared test helpers for mocking the generated core's transport. + +Option C wires the SDK over the OpenAPI-generated core (:mod:`otari._client`), +whose non-streaming calls go through ``RESTClientObject.request`` (urllib3) and +whose streaming path is a hand-written raw httpx request. These helpers mock both +seams without a live gateway: + +- :func:`mock_rest` patches ``RESTClientObject.request`` to return a canned + response, exercising the full generated deserialization + the shell's error + mapping. It records the last request (method/url/headers/body) for assertions. +- streaming tests use ``respx`` to mock the httpx transport directly. +""" + +from __future__ import annotations + +import json +from dataclasses import dataclass, field +from typing import Any + +import pytest + +from otari._client.rest import RESTClientObject, RESTResponse + + +@dataclass +class _Urllib3Like: + """Minimal stand-in for a urllib3 ``HTTPResponse`` that ``RESTResponse`` wraps.""" + + status: int + data: bytes + headers: dict[str, str] + reason: str = "OK" + + +@dataclass +class RecordedRequest: + """The last request the generated core issued through the patched transport.""" + + method: str = "" + url: str = "" + headers: dict[str, Any] = field(default_factory=dict) + body: Any = None + + @property + def json_body(self) -> dict[str, Any]: + if isinstance(self.body, (bytes, bytearray)): + return json.loads(self.body.decode()) + if isinstance(self.body, str): + return json.loads(self.body) + return self.body or {} + + +class RestMock: + """Captures the request and serves a canned response for the generated core.""" + + def __init__( + self, + *, + status: int, + body: Any, + headers: dict[str, str] | None = None, + reason: str = "OK", + ) -> None: + self.status = status + self.reason = reason + self.headers = headers or {} + if isinstance(body, (dict, list)): + self.payload = json.dumps(body).encode() + elif isinstance(body, str): + self.payload = body.encode() + else: + self.payload = body + self.last = RecordedRequest() + + def request( + self, + method: str, + url: str, + headers: dict[str, Any] | None = None, + body: Any = None, + post_params: Any = None, # noqa: ARG002 + _request_timeout: Any = None, + ) -> RESTResponse: + self.last = RecordedRequest( + method=method, url=url, headers=dict(headers or {}), body=body + ) + resp = _Urllib3Like( + status=self.status, data=self.payload, headers=self.headers, reason=self.reason + ) + return RESTResponse(resp) + + +@pytest.fixture +def mock_rest(monkeypatch: pytest.MonkeyPatch) -> Any: + """Return a factory that installs a :class:`RestMock` over the generated core.""" + + def _install( + *, + status: int = 200, + body: Any = None, + headers: dict[str, str] | None = None, + reason: str = "OK", + ) -> RestMock: + mock = RestMock(status=status, body=body, headers=headers, reason=reason) + monkeypatch.setattr(RESTClientObject, "request", mock.request) + return mock + + return _install diff --git a/tests/unit/test_async_client.py b/tests/unit/test_async_client.py index 5fb41f0..794e4ee 100644 --- a/tests/unit/test_async_client.py +++ b/tests/unit/test_async_client.py @@ -1,761 +1,165 @@ -"""Tests for AsyncOtariClient. +"""Tests for the asynchronous AsyncOtariClient (Option C: generated-core shell). -Mirrors the TypeScript SDK's ``client.test.ts`` covering constructor, -auth modes, error mapping, and method delegation. +The async client dispatches the (synchronous) generated calls off-thread via +``asyncio.to_thread`` and streams natively over ``httpx.AsyncClient``. Non- +streaming calls reuse the ``mock_rest`` fixture (it patches the same generated +``RESTClientObject.request``); streaming uses ``respx``. """ from __future__ import annotations -from unittest.mock import AsyncMock, MagicMock +from typing import Any import httpx -import openai import pytest +import respx +from otari._client.models.chat_completion import ChatCompletion +from otari._client.models.chat_completion_chunk import ChatCompletionChunk from otari.async_client import AsyncOtariClient from otari.errors import ( AuthenticationError, - BatchNotCompleteError, GatewayTimeoutError, InsufficientFundsError, ModelNotFoundError, OtariError, RateLimitError, - UnsupportedCapabilityError, UpstreamProviderError, ) - -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- - - -def _make_api_error( - status: int, - message: str, - headers: dict[str, str] | None = None, -) -> openai.APIStatusError: - """Build a fake ``openai.APIStatusError`` for testing error mapping.""" - resp_headers = httpx.Headers(headers or {}) - request = httpx.Request("POST", "https://example.com/v1/chat/completions") - response = httpx.Response(status_code=status, headers=resp_headers, request=request) - return openai.APIStatusError( - message=message, - response=response, - body={"message": message}, - ) - - -# --------------------------------------------------------------------------- -# Constructor tests -# --------------------------------------------------------------------------- +from tests.unit.test_client import ( + CHAT_RESPONSE, + EMBEDDING_RESPONSE, + MESSAGE_RESPONSE, + MODELS_RESPONSE, + RERANK_RESPONSE, + _sse, +) class TestConstructor: def test_throws_when_api_base_missing(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.delenv("GATEWAY_API_BASE", raising=False) - with pytest.raises(ValueError, match="api_base is required"): - AsyncOtariClient() - - def test_uses_api_base_from_options(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" - - def test_does_not_double_append_v1(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000/v1") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" - - def test_strips_trailing_slash(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000/") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" - - def test_falls_back_to_env_var(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_API_BASE", "http://env-gateway:9000") - client = AsyncOtariClient() - assert str(client.openai.base_url).rstrip("/") == "http://env-gateway:9000/v1" - - -class TestPlatformMode: - def test_activates_with_explicit_token(self) -> None: - client = AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_test123", # noqa: S106 - ) - assert client.platform_mode is True - assert client.openai.api_key == "tk_test123" - - def test_activates_via_env_when_no_api_key(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_env_token") - client = AsyncOtariClient(api_base="http://localhost:8000") - assert client.platform_mode is True - assert client.openai.api_key == "tk_env_token" - - def test_does_not_activate_when_api_key_provided(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_env_token") - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - assert client.platform_mode is False - - -class TestHostedDefault: - """Hosted-gateway default + OTARI_AI_TOKEN precedence (parity with TS SDK).""" - - @staticmethod - def _clear_env(monkeypatch: pytest.MonkeyPatch) -> None: for name in ("GATEWAY_API_BASE", "OTARI_AI_TOKEN", "GATEWAY_PLATFORM_TOKEN"): monkeypatch.delenv(name, raising=False) - - def test_platform_token_uses_hosted_default_base(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - client = AsyncOtariClient(platform_token="tk_x") # noqa: S106 - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_otari_ai_token_env_uses_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("OTARI_AI_TOKEN", "tk_env") - client = AsyncOtariClient() - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_api_key_only_no_base_still_raises(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) with pytest.raises(ValueError, match="api_base is required"): - AsyncOtariClient(api_key="k") - - def test_legacy_platform_token_env_uses_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_legacy") - client = AsyncOtariClient() - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_canonical_token_takes_precedence_over_legacy(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("OTARI_AI_TOKEN", "tk_canonical") - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_legacy") - client = AsyncOtariClient() - assert client.platform_mode is True - assert client.openai.api_key == "tk_canonical" - assert client._auth_headers["Authorization"] == "Bearer tk_canonical" + AsyncOtariClient() - def test_explicit_api_base_overrides_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - client = AsyncOtariClient(api_base="http://localhost:8000", platform_token="tk_x") # noqa: S106 + def test_platform_mode_sets_bearer(self) -> None: + client = AsyncOtariClient(api_base="http://localhost:8000", platform_token="tk") # noqa: S106 assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" - + assert client._api.default_headers["Authorization"] == "Bearer tk" -class TestNonPlatformMode: - def test_is_default_without_platform_token(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.delenv("GATEWAY_PLATFORM_TOKEN", raising=False) - client = AsyncOtariClient(api_base="http://localhost:8000") + def test_non_platform_mode_sets_otari_key(self) -> None: + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") assert client.platform_mode is False + assert client._api.default_headers["Otari-Key"] == "Bearer vk" - def test_falls_back_to_api_key_env(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_API_KEY", "env-key") - monkeypatch.delenv("GATEWAY_PLATFORM_TOKEN", raising=False) - client = AsyncOtariClient(api_base="http://localhost:8000") - assert client.platform_mode is False - - def test_forwards_default_headers(self) -> None: - client = AsyncOtariClient( - api_base="http://localhost:8000", - default_headers={"X-Custom": "value"}, - ) - assert client is not None - - -# --------------------------------------------------------------------------- -# Error handling (platform mode) -# --------------------------------------------------------------------------- - - -class TestErrorHandlingPlatformMode: - @pytest.fixture - def client(self) -> AsyncOtariClient: - return AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - @pytest.mark.asyncio - async def test_maps_401_to_authentication_error(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - with pytest.raises(AuthenticationError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_maps_403_to_authentication_error(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(403, "Forbidden"), - ) - with pytest.raises(AuthenticationError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_maps_404_to_model_not_found(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(404, "Not Found"), - ) - with pytest.raises(ModelNotFoundError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_maps_402_to_insufficient_funds(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(402, "Payment Required"), - ) - with pytest.raises(InsufficientFundsError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_maps_429_to_rate_limit_with_retry_after(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(429, "Too Many Requests", {"retry-after": "60"}), - ) - with pytest.raises(RateLimitError) as exc_info: - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.retry_after == "60" - - @pytest.mark.asyncio - async def test_maps_502_to_upstream_provider_error(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(502, "Bad Gateway"), - ) - with pytest.raises(UpstreamProviderError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_maps_504_to_gateway_timeout(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(504, "Gateway Timeout"), - ) - with pytest.raises(GatewayTimeoutError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_includes_correlation_id_in_message(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized", {"x-correlation-id": "abc-123"}), - ) - with pytest.raises(AuthenticationError, match="correlation_id=abc-123"): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_passes_through_unrecognized_status(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(418, "I'm a teapot"), - ) - with pytest.raises(openai.APIStatusError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_passes_through_non_api_error(self, client: AsyncOtariClient) -> None: - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=TypeError("network failure"), - ) - with pytest.raises(TypeError, match="network failure"): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_stores_original_error(self, client: AsyncOtariClient) -> None: - api_err = _make_api_error(401, "Unauthorized") - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=api_err, - ) - with pytest.raises(AuthenticationError) as exc_info: - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.original_error is api_err - assert exc_info.value.provider_name == "gateway" - assert exc_info.value.status_code == 401 - - -# --------------------------------------------------------------------------- -# Error handling (non-platform mode) -# --------------------------------------------------------------------------- - - -class TestErrorHandlingNonPlatformMode: - @pytest.mark.asyncio - async def test_does_not_map_errors(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - # In non-platform mode, the raw APIStatusError should pass through. - with pytest.raises(openai.APIStatusError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_error_is_not_otari_error(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - with pytest.raises(openai.APIStatusError) as exc_info: - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert not isinstance(exc_info.value, OtariError) - - -# --------------------------------------------------------------------------- -# Unsupported capability error (both modes) -# --------------------------------------------------------------------------- - - -class TestUnsupportedCapabilityError: - @pytest.mark.asyncio - async def test_surfaces_in_platform_mode(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", platform_token="tk_test") # noqa: S106 - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Provider anthropic does not support moderation"), - ) - with pytest.raises(UnsupportedCapabilityError) as exc_info: - await client.completion( - model="anthropic:claude-3", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.capability == "moderation" - assert exc_info.value.provider == "anthropic" - - @pytest.mark.asyncio - async def test_surfaces_in_non_platform_mode(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Provider anthropic does not support moderation"), - ) - with pytest.raises(UnsupportedCapabilityError) as exc_info: - await client.completion( - model="anthropic:claude-3", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.capability == "moderation" - - @pytest.mark.asyncio - async def test_multimodal_moderation(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", platform_token="tk_test") # noqa: S106 - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error( - 400, "Provider openai does not support multimodal moderation for this model" - ), - ) - with pytest.raises(UnsupportedCapabilityError) as exc_info: - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.capability == "multimodal_moderation" - - @pytest.mark.asyncio - async def test_unrelated_400_passes_through_in_non_platform(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Invalid request parameters"), - ) - with pytest.raises(openai.APIStatusError): - await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - -# --------------------------------------------------------------------------- -# Method delegation -# --------------------------------------------------------------------------- - - -class TestMethodDelegation: - @pytest.fixture - def client(self) -> AsyncOtariClient: - return AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - @pytest.mark.asyncio - async def test_completion_delegates(self, client: AsyncOtariClient) -> None: - mock_response = MagicMock() - mock_response.id = "chatcmpl-123" - mock_response.choices = [] - client.openai.chat.completions.create = AsyncMock(return_value=mock_response) # type: ignore[method-assign] +class TestInference: + async def test_completion_returns_typed(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=CHAT_RESPONSE) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") result = await client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert result is mock_response - client.openai.chat.completions.create.assert_called_once_with( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - @pytest.mark.asyncio - async def test_embedding_delegates(self, client: AsyncOtariClient) -> None: - mock_response = MagicMock() - client.openai.embeddings.create = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.embedding( - model="openai:text-embedding-3-small", - input="hello", - ) - assert result is mock_response - client.openai.embeddings.create.assert_called_once_with( - model="openai:text-embedding-3-small", - input="hello", - ) - - @pytest.mark.asyncio - async def test_response_delegates(self, client: AsyncOtariClient) -> None: - mock_response = MagicMock() - client.openai.responses.create = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.response( - model="openai:gpt-4o-mini", - input="hello", - ) - assert result is mock_response - - @pytest.mark.asyncio - async def test_list_models_delegates(self, client: AsyncOtariClient) -> None: - mock_models = [ - MagicMock(id="model-1"), - MagicMock(id="model-2"), - ] - - mock_page = MagicMock() - - async def _aiter(_self: object) -> None: - for m in mock_models: - yield m - - mock_page.__aiter__ = _aiter - client.openai.models.list = AsyncMock(return_value=mock_page) # type: ignore[method-assign] - - result = await client.list_models() - assert result == mock_models - - @pytest.mark.asyncio - async def test_error_mapping_on_embedding(self, client: AsyncOtariClient) -> None: - client.openai.embeddings.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - with pytest.raises(AuthenticationError): - await client.embedding(model="openai:text-embedding-3-small", input="hello") - - @pytest.mark.asyncio - async def test_error_mapping_on_response(self, client: AsyncOtariClient) -> None: - client.openai.responses.create = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(429, "Rate limited"), + model="openai:gpt-4o-mini", messages=[{"role": "user", "content": "Hi"}] + ) + assert isinstance(result, ChatCompletion) + assert result.choices[0].message.content == "Hi" + assert mock.last.url.endswith("/v1/chat/completions") + assert mock.last.headers.get("Otari-Key") == "Bearer vk" + + async def test_embedding_returns_typed(self, mock_rest: Any) -> None: + mock_rest(status=200, body=EMBEDDING_RESPONSE) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + result = await client.embedding(model="m", input="hi") + assert result.data[0].embedding == [0.1, 0.2] + + async def test_rerank_returns_typed(self, mock_rest: Any) -> None: + mock_rest(status=200, body=RERANK_RESPONSE) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + result = await client.rerank(model="m", query="q", documents=["a"]) + assert result.results[0].relevance_score == 0.9 + + async def test_message_returns_typed(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=MESSAGE_RESPONSE) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + result = await client.message( + model="anthropic:claude", messages=[{"role": "user", "content": "Hi"}], max_tokens=8 + ) + assert result.id == "msg-1" + assert mock.last.url.endswith("/v1/messages") + + async def test_list_models_returns_typed(self, mock_rest: Any) -> None: + mock_rest(status=200, body=MODELS_RESPONSE) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + models = await client.list_models() + assert models[0].id == "openai:gpt-4o" + + +@pytest.mark.parametrize( + ("status", "expected"), + [ + (401, AuthenticationError), + (402, InsufficientFundsError), + (404, ModelNotFoundError), + (429, RateLimitError), + (502, UpstreamProviderError), + (504, GatewayTimeoutError), + (418, OtariError), + ], +) +class TestErrorMapping: + async def test_status_maps( + self, mock_rest: Any, status: int, expected: type[OtariError] + ) -> None: + mock_rest(status=status, body={"detail": "boom"}, reason="err") + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(expected) as exc_info: + await client.completion(model="m", messages=[{"role": "user", "content": "Hi"}]) + assert exc_info.value.status_code == status + + +class TestStreaming: + @respx.mock + async def test_yields_typed_chunks_and_stops_on_done(self) -> None: + chunk1 = ( + '{"id":"c","object":"chat.completion.chunk","created":1,"model":"m",' + '"choices":[{"index":0,"delta":{"role":"assistant","content":"He"}}]}' + ) + chunk2 = ( + '{"id":"c","object":"chat.completion.chunk","created":1,"model":"m",' + '"choices":[{"index":0,"delta":{"content":"llo"}}]}' + ) + route = respx.post("http://localhost:8000/v1/chat/completions").mock( + return_value=httpx.Response( + 200, + headers={"content-type": "text/event-stream"}, + content=_sse(chunk1, chunk2), + ) + ) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + stream = await client.completion( + model="m", messages=[{"role": "user", "content": "Hi"}], stream=True + ) + chunks = [chunk async for chunk in stream] + assert all(isinstance(c, ChatCompletionChunk) for c in chunks) + assert [c.choices[0].delta.content for c in chunks] == ["He", "llo"] + assert route.calls.last.request.headers["accept"] == "text/event-stream" + assert route.calls.last.request.headers["otari-key"] == "Bearer vk" + + @respx.mock + async def test_streaming_error_maps(self) -> None: + respx.post("http://localhost:8000/v1/chat/completions").mock( + return_value=httpx.Response(429, json={"detail": "rate limited"}) + ) + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + stream = await client.completion( + model="m", messages=[{"role": "user", "content": "Hi"}], stream=True ) with pytest.raises(RateLimitError): - await client.response(model="openai:gpt-4o-mini", input="hello") - - @pytest.mark.asyncio - async def test_error_mapping_on_list_models(self, client: AsyncOtariClient) -> None: - client.openai.models.list = AsyncMock( # type: ignore[method-assign] - side_effect=_make_api_error(502, "Bad Gateway"), - ) - with pytest.raises(UpstreamProviderError): - await client.list_models() - - -# --------------------------------------------------------------------------- -# Batch operations -# --------------------------------------------------------------------------- - - -class TestBatchOperations: - @pytest.fixture - def client(self) -> AsyncOtariClient: - return AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - @pytest.mark.asyncio - async def test_create_batch(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "created", "provider": "openai"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [{"custom_id": "r1", "body": {"messages": []}}], - }) - assert result["id"] == "batch-123" - - @pytest.mark.asyncio - async def test_retrieve_batch(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "completed"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.retrieve_batch("batch-123", "openai") - assert result["status"] == "completed" - - @pytest.mark.asyncio - async def test_cancel_batch(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "cancelled"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.cancel_batch("batch-123", "openai") - assert result["status"] == "cancelled" - - @pytest.mark.asyncio - async def test_list_batches(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"data": [{"id": "b1"}, {"id": "b2"}]}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.list_batches("openai") - assert len(result) == 2 - - @pytest.mark.asyncio - async def test_retrieve_batch_results(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 200, - json={ - "results": [ - {"custom_id": "r1", "result": {"id": "cmpl-1", "choices": []}}, - {"custom_id": "r2", "error": {"code": "err", "message": "failed"}}, - ] - }, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - result = await client.retrieve_batch_results("batch-123", "openai") - assert len(result.results) == 2 - assert result.results[0].custom_id == "r1" - assert result.results[1].error is not None - - -class TestBatchErrorHandling: - @pytest.fixture - def client(self) -> AsyncOtariClient: - return AsyncOtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - @pytest.mark.asyncio - async def test_409_maps_to_batch_not_complete(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 409, - json={"detail": "Batch 'batch-123' is not complete (status: in_progress)"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(BatchNotCompleteError) as exc_info: - await client.retrieve_batch_results("batch-123", "openai") - assert exc_info.value.batch_id == "batch-123" - assert exc_info.value.batch_status == "in_progress" - - @pytest.mark.asyncio - async def test_404_suggests_upgrade(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 404, - json={"detail": "Not supported"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError, match="Upgrade your gateway"): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - @pytest.mark.asyncio - async def test_404_passes_through_not_found(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 404, - json={"detail": "Batch not found"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError, match="not found"): - await client.retrieve_batch("batch-xyz", "openai") - - @pytest.mark.asyncio - async def test_401_maps_to_authentication_error(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 401, - json={"detail": "Invalid key"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(AuthenticationError): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - @pytest.mark.asyncio - async def test_429_maps_to_rate_limit(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 429, - headers={"retry-after": "30"}, - json={"detail": "Rate limited"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(RateLimitError) as exc_info: - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - assert exc_info.value.retry_after == "30" - - @pytest.mark.asyncio - async def test_502_maps_to_upstream_error(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 502, - json={"detail": "Bad Gateway"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(UpstreamProviderError): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - @pytest.mark.asyncio - async def test_504_maps_to_gateway_timeout(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 504, - json={"detail": "Gateway Timeout"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(GatewayTimeoutError): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - @pytest.mark.asyncio - async def test_correlation_id_in_batch_error(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 401, - headers={"x-correlation-id": "corr-456"}, - json={"detail": "Invalid key"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(AuthenticationError, match="correlation_id=corr-456"): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - @pytest.mark.asyncio - async def test_unknown_status_maps_to_otari_error(self, client: AsyncOtariClient) -> None: - mock_response = httpx.Response( - 418, - json={"detail": "I'm a teapot"}, - ) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError): - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - -# --------------------------------------------------------------------------- -# Batch auth modes -# --------------------------------------------------------------------------- - - -class TestBatchAuthModes: - @pytest.mark.asyncio - async def test_non_platform_sends_otari_key(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", api_key="my-key") - mock_response = httpx.Response(200, json={"id": "b1", "provider": "openai"}) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - call_kwargs = client._http.request.call_args - headers = call_kwargs.kwargs.get("headers") or call_kwargs[1].get("headers", {}) - assert headers.get("Otari-Key") == "Bearer my-key" - assert "Authorization" not in headers - - @pytest.mark.asyncio - async def test_platform_sends_authorization(self) -> None: - client = AsyncOtariClient(api_base="http://localhost:8000", platform_token="tk_123") # noqa: S106 - mock_response = httpx.Response(200, json={"id": "b1", "provider": "openai"}) - client._http.request = AsyncMock(return_value=mock_response) # type: ignore[method-assign] - - await client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - call_kwargs = client._http.request.call_args - headers = call_kwargs.kwargs.get("headers") or call_kwargs[1].get("headers", {}) - assert headers.get("Authorization") == "Bearer tk_123" - assert "Otari-Key" not in headers - - -# --------------------------------------------------------------------------- -# Context manager -# --------------------------------------------------------------------------- + _ = [chunk async for chunk in stream] -class TestContextManager: - @pytest.mark.asyncio - async def test_async_context_manager(self) -> None: - async with AsyncOtariClient(api_base="http://localhost:8000") as client: - assert client.platform_mode is False +class TestControlPlane: + def test_requires_admin_credential(self) -> None: + client = AsyncOtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(OtariError, match="admin credential"): + _ = client.control_plane diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 50a97f0..dc8d4c8 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -1,21 +1,25 @@ -"""Tests for the synchronous OtariClient. +"""Tests for the synchronous OtariClient (Option C: generated-core shell). -Mirrors the TypeScript SDK's ``client.test.ts`` covering constructor, -auth modes, error mapping, and method delegation. +Covers constructor / auth-mode wiring, request shaping, typed response parsing, +generated ``ApiException`` -> typed error mapping, and the hand-written SSE +streaming shim. Non-streaming calls are mocked at the generated transport +(``RESTClientObject.request``, see ``conftest.py``); streaming is mocked with +``respx`` over the httpx layer the shim uses. """ from __future__ import annotations -from unittest.mock import MagicMock +from typing import Any import httpx -import openai import pytest +import respx +from otari._client.models.chat_completion import ChatCompletion +from otari._client.models.chat_completion_chunk import ChatCompletionChunk from otari.client import OtariClient from otari.errors import ( AuthenticationError, - BatchNotCompleteError, GatewayTimeoutError, InsufficientFundsError, ModelNotFoundError, @@ -26,690 +30,347 @@ ) # --------------------------------------------------------------------------- -# Helpers +# Response fixtures (validated against the generated models) # --------------------------------------------------------------------------- - -def _make_api_error( - status: int, - message: str, - headers: dict[str, str] | None = None, -) -> openai.APIStatusError: - """Build a fake ``openai.APIStatusError`` for testing error mapping.""" - resp_headers = httpx.Headers(headers or {}) - request = httpx.Request("POST", "https://example.com/v1/chat/completions") - response = httpx.Response(status_code=status, headers=resp_headers, request=request) - return openai.APIStatusError( - message=message, - response=response, - body={"message": message}, - ) +CHAT_RESPONSE: dict[str, Any] = { + "id": "chatcmpl-1", + "object": "chat.completion", + "created": 1, + "model": "openai:gpt-4o-mini", + "choices": [ + {"index": 0, "finish_reason": "stop", "message": {"role": "assistant", "content": "Hi"}} + ], +} + +EMBEDDING_RESPONSE: dict[str, Any] = { + "object": "list", + "model": "openai:text-embedding-3-small", + "data": [{"object": "embedding", "index": 0, "embedding": [0.1, 0.2]}], + "usage": {"prompt_tokens": 1, "total_tokens": 1}, +} + +RERANK_RESPONSE: dict[str, Any] = { + "id": "rerank-1", + "results": [{"index": 0, "relevance_score": 0.9}], +} + +MESSAGE_RESPONSE: dict[str, Any] = { + "id": "msg-1", + "type": "message", + "role": "assistant", + "model": "anthropic:claude-3-5-sonnet", + "content": [{"type": "text", "text": "Hi"}], + "usage": {"input_tokens": 1, "output_tokens": 1}, +} + +MODERATION_RESPONSE: dict[str, Any] = { + "id": "modr-1", + "model": "openai:omni-moderation-latest", + "results": [{"flagged": False, "categories": {}, "category_scores": {}}], +} + +MODELS_RESPONSE: dict[str, Any] = { + "object": "list", + "data": [{"id": "openai:gpt-4o", "object": "model", "created": 1, "owned_by": "openai"}], +} + + +def _sse(*events: str) -> bytes: + """Build a ``text/event-stream`` body from JSON event strings + the DONE sentinel.""" + body = "".join(f"data: {e}\n\n" for e in events) + return (body + "data: [DONE]\n\n").encode() # --------------------------------------------------------------------------- -# Constructor tests +# Constructor / auth-mode wiring # --------------------------------------------------------------------------- class TestConstructor: def test_throws_when_api_base_missing(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.delenv("GATEWAY_API_BASE", raising=False) + for name in ("GATEWAY_API_BASE", "OTARI_AI_TOKEN", "GATEWAY_PLATFORM_TOKEN"): + monkeypatch.delenv(name, raising=False) with pytest.raises(ValueError, match="api_base is required"): OtariClient() def test_uses_api_base_from_options(self) -> None: client = OtariClient(api_base="http://localhost:8000") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" + assert client._base_url == "http://localhost:8000/v1" + assert client._gateway_root_url == "http://localhost:8000" def test_does_not_double_append_v1(self) -> None: client = OtariClient(api_base="http://localhost:8000/v1") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" + assert client._base_url == "http://localhost:8000/v1" def test_strips_trailing_slash(self) -> None: client = OtariClient(api_base="http://localhost:8000/") - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" + assert client._base_url == "http://localhost:8000/v1" def test_falls_back_to_env_var(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("GATEWAY_API_BASE", "http://env-gateway:9000") client = OtariClient() - assert str(client.openai.base_url).rstrip("/") == "http://env-gateway:9000/v1" + assert client._base_url == "http://env-gateway:9000/v1" -class TestPlatformMode: - def test_activates_with_explicit_token(self) -> None: - client = OtariClient( - api_base="http://localhost:8000", - platform_token="tk_test123", # noqa: S106 - ) +class TestAuthModes: + def test_platform_mode_sets_bearer_header(self) -> None: + client = OtariClient(api_base="http://localhost:8000", platform_token="tk_test") # noqa: S106 assert client.platform_mode is True - assert client.openai.api_key == "tk_test123" + assert client._default_headers["Authorization"] == "Bearer tk_test" + assert "Otari-Key" not in client._default_headers + # The header is fed into the generated ApiClient default headers. + assert client._api.default_headers["Authorization"] == "Bearer tk_test" - def test_activates_via_env_when_no_api_key(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_env_token") + def test_platform_mode_via_env(self, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("OTARI_AI_TOKEN", "tk_env") client = OtariClient(api_base="http://localhost:8000") assert client.platform_mode is True - assert client.openai.api_key == "tk_env_token" + assert client._default_headers["Authorization"] == "Bearer tk_env" - def test_does_not_activate_when_api_key_provided(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_env_token") - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") + def test_non_platform_mode_sets_otari_key_header(self) -> None: + client = OtariClient(api_base="http://localhost:8000", api_key="vk_123") assert client.platform_mode is False + assert client._default_headers["Otari-Key"] == "Bearer vk_123" + assert "Authorization" not in client._default_headers + assert client._api.default_headers["Otari-Key"] == "Bearer vk_123" + def test_api_key_overrides_platform_token_env(self, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_env") + client = OtariClient(api_base="http://localhost:8000", api_key="vk_123") + assert client.platform_mode is False -class TestHostedDefault: - """Hosted-gateway default + OTARI_AI_TOKEN precedence (parity with TS SDK).""" - - @staticmethod - def _clear_env(monkeypatch: pytest.MonkeyPatch) -> None: + def test_hosted_default_base_in_platform_mode(self, monkeypatch: pytest.MonkeyPatch) -> None: for name in ("GATEWAY_API_BASE", "OTARI_AI_TOKEN", "GATEWAY_PLATFORM_TOKEN"): monkeypatch.delenv(name, raising=False) - - def test_platform_token_uses_hosted_default_base(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) client = OtariClient(platform_token="tk_x") # noqa: S106 - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_otari_ai_token_env_uses_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("OTARI_AI_TOKEN", "tk_env") - client = OtariClient() - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_api_key_only_no_base_still_raises(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - with pytest.raises(ValueError, match="api_base is required"): - OtariClient(api_key="k") - - def test_legacy_platform_token_env_uses_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_legacy") - client = OtariClient() - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "https://api.otari.ai/v1" - - def test_canonical_token_takes_precedence_over_legacy(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - monkeypatch.setenv("OTARI_AI_TOKEN", "tk_canonical") - monkeypatch.setenv("GATEWAY_PLATFORM_TOKEN", "tk_legacy") - client = OtariClient() - assert client.platform_mode is True - assert client.openai.api_key == "tk_canonical" - assert client._auth_headers["Authorization"] == "Bearer tk_canonical" - - def test_explicit_api_base_overrides_hosted_default(self, monkeypatch: pytest.MonkeyPatch) -> None: - self._clear_env(monkeypatch) - client = OtariClient(api_base="http://localhost:8000", platform_token="tk_x") # noqa: S106 - assert client.platform_mode is True - assert str(client.openai.base_url).rstrip("/") == "http://localhost:8000/v1" - - -class TestNonPlatformMode: - def test_is_default_without_platform_token(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.delenv("GATEWAY_PLATFORM_TOKEN", raising=False) - client = OtariClient(api_base="http://localhost:8000") - assert client.platform_mode is False - - def test_falls_back_to_api_key_env(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("GATEWAY_API_KEY", "env-key") - monkeypatch.delenv("GATEWAY_PLATFORM_TOKEN", raising=False) - client = OtariClient(api_base="http://localhost:8000") - assert client.platform_mode is False - - def test_forwards_default_headers(self) -> None: - client = OtariClient( - api_base="http://localhost:8000", - default_headers={"X-Custom": "value"}, - ) - assert client is not None + assert client._base_url == "https://api.otari.ai/v1" # --------------------------------------------------------------------------- -# Error handling (platform mode) +# Request shaping + typed response parsing # --------------------------------------------------------------------------- -class TestErrorHandlingPlatformMode: - @pytest.fixture - def client(self) -> OtariClient: - return OtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - def test_maps_401_to_authentication_error(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - with pytest.raises(AuthenticationError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_maps_403_to_authentication_error(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(403, "Forbidden"), - ) - with pytest.raises(AuthenticationError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_maps_404_to_model_not_found(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(404, "Not Found"), - ) - with pytest.raises(ModelNotFoundError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_maps_402_to_insufficient_funds(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(402, "Payment Required"), - ) - with pytest.raises(InsufficientFundsError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_maps_429_to_rate_limit_with_retry_after(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(429, "Too Many Requests", {"retry-after": "60"}), - ) - with pytest.raises(RateLimitError) as exc_info: - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.retry_after == "60" - - def test_maps_502_to_upstream_provider_error(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(502, "Bad Gateway"), - ) - with pytest.raises(UpstreamProviderError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_maps_504_to_gateway_timeout(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(504, "Gateway Timeout"), - ) - with pytest.raises(GatewayTimeoutError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_includes_correlation_id_in_message(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized", {"x-correlation-id": "abc-123"}), - ) - with pytest.raises(AuthenticationError, match="correlation_id=abc-123"): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_passes_through_unrecognized_status(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(418, "I'm a teapot"), - ) - with pytest.raises(openai.APIStatusError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_passes_through_non_api_error(self, client: OtariClient) -> None: - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=TypeError("network failure"), - ) - with pytest.raises(TypeError, match="network failure"): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_stores_original_error(self, client: OtariClient) -> None: - api_err = _make_api_error(401, "Unauthorized") - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=api_err, - ) - with pytest.raises(AuthenticationError) as exc_info: - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.original_error is api_err - assert exc_info.value.provider_name == "gateway" - assert exc_info.value.status_code == 401 +class TestCompletion: + def test_returns_typed_chat_completion(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=CHAT_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + result = client.completion( + model="openai:gpt-4o-mini", + messages=[{"role": "user", "content": "Hi"}], + temperature=0.5, + ) + assert isinstance(result, ChatCompletion) + assert result.choices[0].message.content == "Hi" + # Request shaping: correct path + body, with the Otari-Key auth header. + assert mock.last.method == "POST" + assert mock.last.url.endswith("/v1/chat/completions") + body = mock.last.json_body + assert body["model"] == "openai:gpt-4o-mini" + assert body["temperature"] == 0.5 + assert mock.last.headers.get("Otari-Key") == "Bearer vk" + + def test_platform_mode_sends_bearer(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=CHAT_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", platform_token="tk") # noqa: S106 + client.completion(model="m", messages=[{"role": "user", "content": "Hi"}]) + assert mock.last.headers.get("Authorization") == "Bearer tk" + + +class TestEmbedding: + def test_returns_typed_embedding(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=EMBEDDING_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + result = client.embedding(model="openai:text-embedding-3-small", input="hello") + assert result.data[0].embedding == [0.1, 0.2] + assert mock.last.url.endswith("/v1/embeddings") + assert mock.last.json_body["input"] == "hello" + + +class TestRerank: + def test_returns_typed_rerank(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=RERANK_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + result = client.rerank(model="m", query="q", documents=["a", "b"]) + assert result.results[0].relevance_score == 0.9 + assert mock.last.url.endswith("/v1/rerank") + assert mock.last.json_body["documents"] == ["a", "b"] + + +class TestMessage: + def test_returns_typed_message_response(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=MESSAGE_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + result = client.message( + model="anthropic:claude-3-5-sonnet", + messages=[{"role": "user", "content": "Hi"}], + max_tokens=64, + ) + assert result.id == "msg-1" + assert mock.last.url.endswith("/v1/messages") + body = mock.last.json_body + assert body["max_tokens"] == 64 + assert body["model"] == "anthropic:claude-3-5-sonnet" + + +class TestModeration: + def test_returns_typed_moderation(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=MODERATION_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + result = client.moderation(model="m", input="text") + assert result.results[0].flagged is False + assert mock.last.url.endswith("/v1/moderations") + + +class TestListModels: + def test_returns_typed_models(self, mock_rest: Any) -> None: + mock = mock_rest(status=200, body=MODELS_RESPONSE) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + models = client.list_models() + assert models[0].id == "openai:gpt-4o" + assert mock.last.url.endswith("/v1/models") # --------------------------------------------------------------------------- -# Error handling (non-platform mode) +# Error mapping (generated ApiException -> typed otari errors) # --------------------------------------------------------------------------- -class TestErrorHandlingNonPlatformMode: - def test_does_not_map_errors(self) -> None: - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - # In non-platform mode, the raw APIStatusError should pass through. - with pytest.raises(openai.APIStatusError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_error_is_not_otari_error(self) -> None: - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), - ) - with pytest.raises(openai.APIStatusError) as exc_info: - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert not isinstance(exc_info.value, OtariError) - - -# --------------------------------------------------------------------------- -# Unsupported capability error (both modes) -# --------------------------------------------------------------------------- +@pytest.mark.parametrize( + ("status", "expected"), + [ + (401, AuthenticationError), + (403, AuthenticationError), + (402, InsufficientFundsError), + (404, ModelNotFoundError), + (429, RateLimitError), + (502, UpstreamProviderError), + (503, UpstreamProviderError), + (504, GatewayTimeoutError), + (418, OtariError), + ], +) +class TestErrorMapping: + def test_status_maps_to_error( + self, mock_rest: Any, status: int, expected: type[OtariError] + ) -> None: + mock_rest(status=status, body={"detail": "boom"}, reason="err") + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(expected) as exc_info: + client.completion(model="m", messages=[{"role": "user", "content": "Hi"}]) + assert exc_info.value.status_code == status + assert "boom" in str(exc_info.value) + + +class TestErrorDetails: + def test_rate_limit_carries_retry_after(self, mock_rest: Any) -> None: + mock_rest(status=429, body={"detail": "slow down"}, headers={"retry-after": "30"}) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(RateLimitError) as exc_info: + client.completion(model="m", messages=[{"role": "user", "content": "Hi"}]) + assert exc_info.value.retry_after == "30" + def test_correlation_id_in_message(self, mock_rest: Any) -> None: + mock_rest(status=402, body={"detail": "no funds"}, headers={"x-correlation-id": "abc-123"}) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(InsufficientFundsError) as exc_info: + client.completion(model="m", messages=[{"role": "user", "content": "Hi"}]) + assert "abc-123" in str(exc_info.value) -class TestUnsupportedCapabilityError: - def test_surfaces_in_platform_mode(self) -> None: - client = OtariClient(api_base="http://localhost:8000", platform_token="tk_test") # noqa: S106 - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Provider anthropic does not support moderation"), + def test_unsupported_moderation_maps_in_any_mode(self, mock_rest: Any) -> None: + mock_rest( + status=400, body={"detail": "Provider anthropic does not support moderation"} ) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") with pytest.raises(UnsupportedCapabilityError) as exc_info: - client.completion( - model="anthropic:claude-3", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.capability == "moderation" + client.moderation(model="anthropic:claude", input="text") assert exc_info.value.provider == "anthropic" - - def test_surfaces_in_non_platform_mode(self) -> None: - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Provider anthropic does not support moderation"), - ) - with pytest.raises(UnsupportedCapabilityError) as exc_info: - client.completion( - model="anthropic:claude-3", - messages=[{"role": "user", "content": "hi"}], - ) assert exc_info.value.capability == "moderation" - def test_multimodal_moderation(self) -> None: - client = OtariClient(api_base="http://localhost:8000", platform_token="tk_test") # noqa: S106 - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error( - 400, "Provider openai does not support multimodal moderation for this model" - ), - ) - with pytest.raises(UnsupportedCapabilityError) as exc_info: - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert exc_info.value.capability == "multimodal_moderation" - - def test_unrelated_400_passes_through_in_non_platform(self) -> None: - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") - client.openai.chat.completions.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(400, "Invalid request parameters"), - ) - with pytest.raises(openai.APIStatusError): - client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - # --------------------------------------------------------------------------- -# Method delegation +# SSE streaming shim (chat = must-have) # --------------------------------------------------------------------------- -class TestMethodDelegation: - @pytest.fixture - def client(self) -> OtariClient: - return OtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - def test_completion_delegates(self, client: OtariClient) -> None: - mock_response = MagicMock() - mock_response.id = "chatcmpl-123" - mock_response.choices = [] - client.openai.chat.completions.create = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.completion( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - assert result is mock_response - client.openai.chat.completions.create.assert_called_once_with( - model="openai:gpt-4o-mini", - messages=[{"role": "user", "content": "hi"}], - ) - - def test_embedding_delegates(self, client: OtariClient) -> None: - mock_response = MagicMock() - client.openai.embeddings.create = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.embedding( - model="openai:text-embedding-3-small", - input="hello", +class TestChatStreaming: + @respx.mock + def test_yields_typed_chunks_and_stops_on_done(self) -> None: + chunk1 = ( + '{"id":"c","object":"chat.completion.chunk","created":1,"model":"m",' + '"choices":[{"index":0,"delta":{"role":"assistant","content":"He"}}]}' ) - assert result is mock_response - client.openai.embeddings.create.assert_called_once_with( - model="openai:text-embedding-3-small", - input="hello", + chunk2 = ( + '{"id":"c","object":"chat.completion.chunk","created":1,"model":"m",' + '"choices":[{"index":0,"delta":{"content":"llo"}}]}' ) - - def test_response_delegates(self, client: OtariClient) -> None: - mock_response = MagicMock() - client.openai.responses.create = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.response( - model="openai:gpt-4o-mini", - input="hello", + route = respx.post("http://localhost:8000/v1/chat/completions").mock( + return_value=httpx.Response( + 200, + headers={"content-type": "text/event-stream"}, + content=_sse(chunk1, chunk2), + ) ) - assert result is mock_response - - def test_list_models_delegates(self, client: OtariClient) -> None: - mock_models = [ - MagicMock(id="model-1"), - MagicMock(id="model-2"), - ] - - mock_page = MagicMock() - mock_page.__iter__.return_value = iter(mock_models) - client.openai.models.list = MagicMock(return_value=mock_page) # type: ignore[method-assign] - - result = client.list_models() - assert result == mock_models - - def test_error_mapping_on_embedding(self, client: OtariClient) -> None: - client.openai.embeddings.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(401, "Unauthorized"), + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + stream = client.completion( + model="m", messages=[{"role": "user", "content": "Hi"}], stream=True ) - with pytest.raises(AuthenticationError): - client.embedding(model="openai:text-embedding-3-small", input="hello") + chunks = list(stream) + assert all(isinstance(c, ChatCompletionChunk) for c in chunks) + assert [c.choices[0].delta.content for c in chunks] == ["He", "llo"] + # The streaming request set the SSE Accept + auth header and stream flag. + request = route.calls.last.request + assert request.headers["accept"] == "text/event-stream" + assert request.headers["otari-key"] == "Bearer vk" - def test_error_mapping_on_response(self, client: OtariClient) -> None: - client.openai.responses.create = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(429, "Rate limited"), + @respx.mock + def test_streaming_error_maps_to_typed_error(self) -> None: + respx.post("http://localhost:8000/v1/chat/completions").mock( + return_value=httpx.Response(429, json={"detail": "rate limited"}) ) + client = OtariClient(api_base="http://localhost:8000", api_key="vk") with pytest.raises(RateLimitError): - client.response(model="openai:gpt-4o-mini", input="hello") - - def test_error_mapping_on_list_models(self, client: OtariClient) -> None: - client.openai.models.list = MagicMock( # type: ignore[method-assign] - side_effect=_make_api_error(502, "Bad Gateway"), - ) - with pytest.raises(UpstreamProviderError): - client.list_models() - - -# --------------------------------------------------------------------------- -# Batch operations -# --------------------------------------------------------------------------- - - -class TestBatchOperations: - @pytest.fixture - def client(self) -> OtariClient: - return OtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - def test_create_batch(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "created", "provider": "openai"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [{"custom_id": "r1", "body": {"messages": []}}], - }) - assert result["id"] == "batch-123" - - def test_retrieve_batch(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "completed"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.retrieve_batch("batch-123", "openai") - assert result["status"] == "completed" - - def test_cancel_batch(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"id": "batch-123", "status": "cancelled"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.cancel_batch("batch-123", "openai") - assert result["status"] == "cancelled" - - def test_list_batches(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 200, - json={"data": [{"id": "b1"}, {"id": "b2"}]}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.list_batches("openai") - assert len(result) == 2 - - def test_retrieve_batch_results(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 200, - json={ - "results": [ - {"custom_id": "r1", "result": {"id": "cmpl-1", "choices": []}}, - {"custom_id": "r2", "error": {"code": "err", "message": "failed"}}, - ] - }, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - result = client.retrieve_batch_results("batch-123", "openai") - assert len(result.results) == 2 - assert result.results[0].custom_id == "r1" - assert result.results[1].error is not None - - -class TestBatchErrorHandling: - @pytest.fixture - def client(self) -> OtariClient: - return OtariClient( - api_base="http://localhost:8000", - platform_token="tk_test", # noqa: S106 - ) - - def test_409_maps_to_batch_not_complete(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 409, - json={"detail": "Batch 'batch-123' is not complete (status: in_progress)"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(BatchNotCompleteError) as exc_info: - client.retrieve_batch_results("batch-123", "openai") - assert exc_info.value.batch_id == "batch-123" - assert exc_info.value.batch_status == "in_progress" - - def test_404_suggests_upgrade(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 404, - json={"detail": "Not supported"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError, match="Upgrade your gateway"): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - def test_404_passes_through_not_found(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 404, - json={"detail": "Batch not found"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError, match="not found"): - client.retrieve_batch("batch-xyz", "openai") - - def test_401_maps_to_authentication_error(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 401, - json={"detail": "Invalid key"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(AuthenticationError): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - def test_429_maps_to_rate_limit(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 429, - headers={"retry-after": "30"}, - json={"detail": "Rate limited"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(RateLimitError) as exc_info: - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - assert exc_info.value.retry_after == "30" + list( + client.completion( + model="m", messages=[{"role": "user", "content": "Hi"}], stream=True + ) + ) - def test_502_maps_to_upstream_error(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 502, - json={"detail": "Bad Gateway"}, - ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(UpstreamProviderError): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - def test_504_maps_to_gateway_timeout(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 504, - json={"detail": "Gateway Timeout"}, + @respx.mock + def test_platform_mode_streaming_sends_bearer(self) -> None: + chunk = ( + '{"id":"c","object":"chat.completion.chunk","created":1,"model":"m",' + '"choices":[{"index":0,"delta":{"content":"x"}}]}' ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(GatewayTimeoutError): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - def test_correlation_id_in_batch_error(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 401, - headers={"x-correlation-id": "corr-456"}, - json={"detail": "Invalid key"}, + route = respx.post("http://localhost:8000/v1/chat/completions").mock( + return_value=httpx.Response( + 200, headers={"content-type": "text/event-stream"}, content=_sse(chunk) + ) ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(AuthenticationError, match="correlation_id=corr-456"): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - - def test_unknown_status_maps_to_otari_error(self, client: OtariClient) -> None: - mock_response = httpx.Response( - 418, - json={"detail": "I'm a teapot"}, + client = OtariClient(api_base="http://localhost:8000", platform_token="tk") # noqa: S106 + list( + client.completion( + model="m", messages=[{"role": "user", "content": "Hi"}], stream=True + ) ) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - with pytest.raises(OtariError): - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) + assert route.calls.last.request.headers["authorization"] == "Bearer tk" # --------------------------------------------------------------------------- -# Batch auth modes +# Control-plane accessor # --------------------------------------------------------------------------- -class TestBatchAuthModes: - def test_non_platform_sends_otari_key(self) -> None: - client = OtariClient(api_base="http://localhost:8000", api_key="my-key") - mock_response = httpx.Response(200, json={"id": "b1", "provider": "openai"}) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - call_kwargs = client._http.request.call_args - headers = call_kwargs.kwargs.get("headers") or call_kwargs[1].get("headers", {}) - assert headers.get("Otari-Key") == "Bearer my-key" - assert "Authorization" not in headers - - def test_platform_sends_authorization(self) -> None: - client = OtariClient(api_base="http://localhost:8000", platform_token="tk_123") # noqa: S106 - mock_response = httpx.Response(200, json={"id": "b1", "provider": "openai"}) - client._http.request = MagicMock(return_value=mock_response) # type: ignore[method-assign] - - client.create_batch({ - "model": "openai:gpt-4o-mini", - "requests": [], - }) - call_kwargs = client._http.request.call_args - headers = call_kwargs.kwargs.get("headers") or call_kwargs[1].get("headers", {}) - assert headers.get("Authorization") == "Bearer tk_123" - assert "Otari-Key" not in headers - - -# --------------------------------------------------------------------------- -# Context manager -# --------------------------------------------------------------------------- - +class TestControlPlane: + def test_requires_admin_credential(self) -> None: + client = OtariClient(api_base="http://localhost:8000", api_key="vk") + with pytest.raises(OtariError, match="admin credential"): + _ = client.control_plane -class TestContextManager: - def test_context_manager(self) -> None: - with OtariClient(api_base="http://localhost:8000") as client: - assert client.platform_mode is False + def test_available_with_admin_key(self) -> None: + client = OtariClient(api_base="http://localhost:8000", admin_key="master") + cp = client.control_plane + assert cp.keys is not None + assert cp._api_client.default_headers["Authorization"] == "Bearer master" + cp.close() diff --git a/tests/unit/test_endpoint_coverage.py b/tests/unit/test_endpoint_coverage.py new file mode 100644 index 0000000..42866ad --- /dev/null +++ b/tests/unit/test_endpoint_coverage.py @@ -0,0 +1,103 @@ +"""Endpoint-coverage drift gate. + +Fetches the canonical otari gateway OpenAPI spec and asserts that every API +endpoint it exposes is accounted for in ``sdk-endpoints.txt`` -- either wrapped +by this SDK's public surface (``[covered]``) or deliberately deferred +(``[excluded]``). A new gateway endpoint in neither section fails this test, +so a future endpoint (as ``/messages`` once was) cannot silently go unsurfaced. + +The fetch uses :mod:`urllib.request` (stdlib) so the test runs in the normal +suite. It is skipped offline (network error / ``OTARI_SKIP_NETWORK_TESTS=1``) +but runs in CI, where the network is available. +""" + +from __future__ import annotations + +import json +import os +import urllib.error +import urllib.request +from pathlib import Path + +import pytest + +SPEC_URL = "https://raw.githubusercontent.com/mozilla-ai/otari/main/docs/public/openapi.json" +MANIFEST = Path(__file__).resolve().parents[2] / "sdk-endpoints.txt" +HTTP_METHODS = {"get", "post", "put", "patch", "delete"} + + +def parse_manifest(text: str) -> tuple[set[str], set[str]]: + """Return (covered, excluded) endpoint sets from manifest text. + + Format: ``[covered]`` / ``[excluded]`` sections; each entry is + ``METHOD /path`` with an optional ``# reason`` trailer; ``#`` lines and + blank lines are ignored. + """ + covered: set[str] = set() + excluded: set[str] = set() + section: set[str] | None = None + for raw in text.splitlines(): + line = raw.strip() + if not line or line.startswith("#"): + continue + if line == "[covered]": + section = covered + continue + if line == "[excluded]": + section = excluded + continue + entry = line.split("#", 1)[0].strip() + if not entry or section is None: + continue + method, path = entry.split(None, 1) + section.add(f"{method.upper()} {path.strip()}") + return covered, excluded + + +def spec_endpoints(spec: dict) -> set[str]: + """Extract ``METHOD /path`` pairs from an OpenAPI doc, dropping meta routes.""" + eps: set[str] = set() + for path, methods in spec.get("paths", {}).items(): + if path == "/health" or path.startswith("/health/"): + continue + for method in methods: + if method.lower() in HTTP_METHODS: + eps.add(f"{method.upper()} {path}") + return eps + + +def fetch_spec() -> dict: + if os.environ.get("OTARI_SKIP_NETWORK_TESTS") == "1": + pytest.skip("OTARI_SKIP_NETWORK_TESTS=1") + try: + with urllib.request.urlopen(SPEC_URL, timeout=30) as resp: # noqa: S310 + return json.loads(resp.read()) + except (urllib.error.URLError, TimeoutError) as exc: + pytest.skip(f"could not fetch otari OpenAPI spec from {SPEC_URL}: {exc}") + + +def test_manifest_parses() -> None: + covered, excluded = parse_manifest(MANIFEST.read_text()) + assert covered, "manifest [covered] section is empty" + assert not (covered & excluded), f"endpoints in both sections: {sorted(covered & excluded)}" + + +def test_spec_endpoints_are_accounted_for() -> None: + covered, excluded = parse_manifest(MANIFEST.read_text()) + spec = spec_endpoints(fetch_spec()) + accounted = covered | excluded + unaccounted = sorted(spec - accounted) + assert not unaccounted, ( + "Gateway OpenAPI exposes endpoint(s) the SDK does not account for: " + f"{unaccounted}. Add a public wrapper and list under [covered], or " + "defer it under [excluded] with a reason, in sdk-endpoints.txt." + ) + + +def test_manifest_has_no_stale_entries() -> None: + """Warn (not fail) if a manifest entry no longer exists in the spec.""" + covered, excluded = parse_manifest(MANIFEST.read_text()) + spec = spec_endpoints(fetch_spec()) + stale = sorted((covered | excluded) - spec) + if stale: + pytest.skip(f"manifest entries not present in current spec (review): {stale}")