From 09c84bdf3208ce3be5060435122c5006a16a301e Mon Sep 17 00:00:00 2001 From: njbrake <33383515+njbrake@users.noreply.github.com> Date: Fri, 17 Jul 2026 01:20:37 +0000 Subject: [PATCH] chore: regenerate SDK client core from Otari OpenAPI spec --- src/otari/_client/__init__.py | 30 + src/otari/_client/api/__init__.py | 3 + src/otari/_client/api/aliases_api.py | 825 ++++++++++++++++++ src/otari/_client/api/batches_api.py | 12 +- src/otari/_client/api/keys_api.py | 264 ++++++ src/otari/_client/api/messages_api.py | 6 +- src/otari/_client/api/models_api.py | 494 +++++++++++ src/otari/_client/api/pricing_api.py | 6 +- src/otari/_client/api/providers_api.py | 281 ++++++ src/otari/_client/api/responses_api.py | 6 +- src/otari/_client/api/settings_api.py | 559 ++++++++++++ src/otari/_client/models/__init__.py | 12 + src/otari/_client/models/alias_request.py | 90 ++ src/otari/_client/models/alias_response.py | 106 +++ .../models/cc_chat_completion_message.py | 11 +- src/otari/_client/models/cck_choice_delta.py | 11 +- .../models/cck_choice_delta_function_call.py | 2 +- .../models/cck_choice_delta_tool_call.py | 13 +- .../_client/models/create_batch_request.py | 11 +- .../_client/models/discoverable_model.py | 90 ++ .../models/discoverable_models_response.py | 96 ++ .../_client/models/discoverable_provider.py | 107 +++ src/otari/_client/models/gateway_settings.py | 96 ++ src/otari/_client/models/messages_request.py | 9 +- src/otari/_client/models/model_metadata.py | 174 ++++ .../_client/models/model_metadata_response.py | 105 +++ src/otari/_client/models/model_object.py | 13 +- .../models/provider_capabilities_schema.py | 108 +++ .../_client/models/provider_info_schema.py | 121 +++ .../_client/models/providers_response.py | 96 ++ .../_client/models/update_settings_request.py | 100 +++ 31 files changed, 3829 insertions(+), 28 deletions(-) create mode 100644 src/otari/_client/api/aliases_api.py create mode 100644 src/otari/_client/api/providers_api.py create mode 100644 src/otari/_client/api/settings_api.py create mode 100644 src/otari/_client/models/alias_request.py create mode 100644 src/otari/_client/models/alias_response.py create mode 100644 src/otari/_client/models/discoverable_model.py create mode 100644 src/otari/_client/models/discoverable_models_response.py create mode 100644 src/otari/_client/models/discoverable_provider.py create mode 100644 src/otari/_client/models/gateway_settings.py create mode 100644 src/otari/_client/models/model_metadata.py create mode 100644 src/otari/_client/models/model_metadata_response.py create mode 100644 src/otari/_client/models/provider_capabilities_schema.py create mode 100644 src/otari/_client/models/provider_info_schema.py create mode 100644 src/otari/_client/models/providers_response.py create mode 100644 src/otari/_client/models/update_settings_request.py diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py index a3c18c1..518b9e6 100644 --- a/src/otari/_client/__init__.py +++ b/src/otari/_client/__init__.py @@ -18,6 +18,7 @@ # Define package exports __all__ = [ + "AliasesApi", "AudioApi", "BatchesApi", "BudgetsApi", @@ -31,8 +32,10 @@ "ModelsApi", "ModerationsApi", "PricingApi", + "ProvidersApi", "RerankApi", "ResponsesApi", + "SettingsApi", "UsageApi", "UsersApi", "ApiResponse", @@ -44,6 +47,8 @@ "ApiKeyError", "ApiAttributeError", "ApiException", + "AliasRequest", + "AliasResponse", "AudioSpeechRequest", "BatchRequestItem", "BudgetResponse", @@ -100,9 +105,13 @@ "CreateKeyRequest", "CreateKeyResponse", "CreateUserRequest", + "DiscoverableModel", + "DiscoverableModelsResponse", + "DiscoverableProvider", "EMBEmbedding", "EMBUsage", "EmbeddingRequest", + "GatewaySettings", "GuardrailConfig", "HTTPValidationError", "IMGImage", @@ -188,12 +197,17 @@ "MessagesRequest", "Model", "ModelListResponse", + "ModelMetadata", + "ModelMetadataResponse", "ModelObject", "ModelPricingInfo", "ModerationRequest", "ModerationResponse", "ModerationResult", "PricingResponse", + "ProviderCapabilitiesSchema", + "ProviderInfoSchema", + "ProvidersResponse", "RRRerankMeta", "RRRerankResult", "RRRerankUsage", @@ -209,6 +223,7 @@ "ToolChoice1", "UpdateBudgetRequest", "UpdateKeyRequest", + "UpdateSettingsRequest", "UpdateUserRequest", "UsageEntry", "UsageLogResponse", @@ -217,6 +232,7 @@ ] # import apis into sdk package +from otari._client.api.aliases_api import AliasesApi as AliasesApi 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 @@ -230,8 +246,10 @@ 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.providers_api import ProvidersApi as ProvidersApi from otari._client.api.rerank_api import RerankApi as RerankApi from otari._client.api.responses_api import ResponsesApi as ResponsesApi +from otari._client.api.settings_api import SettingsApi as SettingsApi from otari._client.api.usage_api import UsageApi as UsageApi from otari._client.api.users_api import UsersApi as UsersApi @@ -247,6 +265,8 @@ from otari._client.exceptions import ApiException as ApiException # import models into sdk package +from otari._client.models.alias_request import AliasRequest as AliasRequest +from otari._client.models.alias_response import AliasResponse as AliasResponse 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 @@ -303,9 +323,13 @@ 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.discoverable_model import DiscoverableModel as DiscoverableModel +from otari._client.models.discoverable_models_response import DiscoverableModelsResponse as DiscoverableModelsResponse +from otari._client.models.discoverable_provider import DiscoverableProvider as DiscoverableProvider 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.gateway_settings import GatewaySettings as GatewaySettings 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.img_image import IMGImage as IMGImage @@ -391,12 +415,17 @@ 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_metadata import ModelMetadata as ModelMetadata +from otari._client.models.model_metadata_response import ModelMetadataResponse as ModelMetadataResponse 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.provider_capabilities_schema import ProviderCapabilitiesSchema as ProviderCapabilitiesSchema +from otari._client.models.provider_info_schema import ProviderInfoSchema as ProviderInfoSchema +from otari._client.models.providers_response import ProvidersResponse as ProvidersResponse 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 @@ -412,6 +441,7 @@ from otari._client.models.tool_choice1 import ToolChoice1 as ToolChoice1 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_settings_request import UpdateSettingsRequest as UpdateSettingsRequest 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 diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py index ae486dd..bf8ddd6 100644 --- a/src/otari/_client/api/__init__.py +++ b/src/otari/_client/api/__init__.py @@ -1,6 +1,7 @@ # flake8: noqa # import apis into api package +from otari._client.api.aliases_api import AliasesApi from otari._client.api.audio_api import AudioApi from otari._client.api.batches_api import BatchesApi from otari._client.api.budgets_api import BudgetsApi @@ -14,8 +15,10 @@ 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.providers_api import ProvidersApi from otari._client.api.rerank_api import RerankApi from otari._client.api.responses_api import ResponsesApi +from otari._client.api.settings_api import SettingsApi from otari._client.api.usage_api import UsageApi from otari._client.api.users_api import UsersApi diff --git a/src/otari/_client/api/aliases_api.py b/src/otari/_client/api/aliases_api.py new file mode 100644 index 0000000..ef4e173 --- /dev/null +++ b/src/otari/_client/api/aliases_api.py @@ -0,0 +1,825 @@ +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 List +from otari._client.models.alias_request import AliasRequest +from otari._client.models.alias_response import AliasResponse + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class AliasesApi: + """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_alias_v1_aliases_name_delete( + self, + name: 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 Alias + + Delete a stored alias. + + :param name: (required) + :type name: 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_alias_v1_aliases_name_delete_serialize( + name=name, + _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_alias_v1_aliases_name_delete_with_http_info( + self, + name: 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 Alias + + Delete a stored alias. + + :param name: (required) + :type name: 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_alias_v1_aliases_name_delete_serialize( + name=name, + _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_alias_v1_aliases_name_delete_without_preload_content( + self, + name: 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 Alias + + Delete a stored alias. + + :param name: (required) + :type name: 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_alias_v1_aliases_name_delete_serialize( + name=name, + _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_alias_v1_aliases_name_delete_serialize( + self, + name, + _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 name is not None: + _path_params['name'] = name + # 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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/aliases/{name}', + 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_aliases_v1_aliases_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, + ) -> List[AliasResponse]: + """List Aliases + + List every alias in force, from config.yml and from storage. + + :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_aliases_v1_aliases_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[AliasResponse]", + } + 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_aliases_v1_aliases_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[List[AliasResponse]]: + """List Aliases + + List every alias in force, from config.yml and from storage. + + :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_aliases_v1_aliases_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[AliasResponse]", + } + 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_aliases_v1_aliases_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: + """List Aliases + + List every alias in force, from config.yml and from storage. + + :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_aliases_v1_aliases_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[AliasResponse]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_aliases_v1_aliases_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/aliases', + 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_alias_v1_aliases_post( + self, + alias_request: AliasRequest, + _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, + ) -> AliasResponse: + """Set Alias + + Create or update a stored alias. + + :param alias_request: (required) + :type alias_request: AliasRequest + :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_alias_v1_aliases_post_serialize( + alias_request=alias_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AliasResponse", + '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_alias_v1_aliases_post_with_http_info( + self, + alias_request: AliasRequest, + _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[AliasResponse]: + """Set Alias + + Create or update a stored alias. + + :param alias_request: (required) + :type alias_request: AliasRequest + :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_alias_v1_aliases_post_serialize( + alias_request=alias_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AliasResponse", + '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_alias_v1_aliases_post_without_preload_content( + self, + alias_request: AliasRequest, + _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 Alias + + Create or update a stored alias. + + :param alias_request: (required) + :type alias_request: AliasRequest + :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_alias_v1_aliases_post_serialize( + alias_request=alias_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AliasResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _set_alias_v1_aliases_post_serialize( + self, + alias_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 alias_request is not None: + _body_params = alias_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/aliases', + 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 index fda9adb..8d3f2af 100644 --- a/src/otari/_client/api/batches_api.py +++ b/src/otari/_client/api/batches_api.py @@ -337,7 +337,7 @@ def create_batch_v1_batches_post( ) -> object: """Create Batch - Create a batch of LLM requests for asynchronous processing. + Create a batch of LLM requests for asynchronous processing. 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 create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -405,7 +405,7 @@ def create_batch_v1_batches_post_with_http_info( ) -> ApiResponse[object]: """Create Batch - Create a batch of LLM requests for asynchronous processing. + Create a batch of LLM requests for asynchronous processing. 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 create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -473,7 +473,7 @@ def create_batch_v1_batches_post_without_preload_content( ) -> RESTResponseType: """Create Batch - Create a batch of LLM requests for asynchronous processing. + Create a batch of LLM requests for asynchronous processing. 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 create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -616,7 +616,7 @@ def list_batches_v1_batches_get( ) -> object: """List Batches - List batches for a provider. + List batches for a provider. Non-master keys only see batches they own (plus legacy batches without an ownership marker); the page is filtered after the provider call, so a page may contain fewer than ``limit`` items. :param provider: (required) :type provider: str @@ -692,7 +692,7 @@ def list_batches_v1_batches_get_with_http_info( ) -> ApiResponse[object]: """List Batches - List batches for a provider. + List batches for a provider. Non-master keys only see batches they own (plus legacy batches without an ownership marker); the page is filtered after the provider call, so a page may contain fewer than ``limit`` items. :param provider: (required) :type provider: str @@ -768,7 +768,7 @@ def list_batches_v1_batches_get_without_preload_content( ) -> RESTResponseType: """List Batches - List batches for a provider. + List batches for a provider. Non-master keys only see batches they own (plus legacy batches without an ownership marker); the page is filtered after the provider call, so a page may contain fewer than ``limit`` items. :param provider: (required) :type provider: str diff --git a/src/otari/_client/api/keys_api.py b/src/otari/_client/api/keys_api.py index 7721864..1c9bfc5 100644 --- a/src/otari/_client/api/keys_api.py +++ b/src/otari/_client/api/keys_api.py @@ -1129,6 +1129,270 @@ def _list_keys_v1_keys_get_serialize( + @validate_call + def rotate_key_v1_keys_key_id_rotate_post( + 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, + ) -> CreateKeyResponse: + """Rotate Key + + Rotate an API key's secret in place. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + + :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._rotate_key_v1_keys_key_id_rotate_post_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': "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 rotate_key_v1_keys_key_id_rotate_post_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[CreateKeyResponse]: + """Rotate Key + + Rotate an API key's secret in place. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + + :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._rotate_key_v1_keys_key_id_rotate_post_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': "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 rotate_key_v1_keys_key_id_rotate_post_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: + """Rotate Key + + Rotate an API key's secret in place. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + + :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._rotate_key_v1_keys_key_id_rotate_post_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': "CreateKeyResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _rotate_key_v1_keys_key_id_rotate_post_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/keys/{key_id}/rotate', + 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, diff --git a/src/otari/_client/api/messages_api.py b/src/otari/_client/api/messages_api.py index 8ef85d5..53ab5ec 100644 --- a/src/otari/_client/api/messages_api.py +++ b/src/otari/_client/api/messages_api.py @@ -334,7 +334,7 @@ def create_message_v1_messages_post( ) -> 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 hybrid mode. Hybrid-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. + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param messages_request: (required) :type messages_request: MessagesRequest @@ -402,7 +402,7 @@ def create_message_v1_messages_post_with_http_info( ) -> 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 hybrid mode. Hybrid-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. + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param messages_request: (required) :type messages_request: MessagesRequest @@ -470,7 +470,7 @@ def create_message_v1_messages_post_without_preload_content( ) -> 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 hybrid mode. Hybrid-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. + Anthropic Messages API-compatible endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param messages_request: (required) :type messages_request: MessagesRequest diff --git a/src/otari/_client/api/models_api.py b/src/otari/_client/api/models_api.py index 3b158f4..78b3877 100644 --- a/src/otari/_client/api/models_api.py +++ b/src/otari/_client/api/models_api.py @@ -18,7 +18,9 @@ from pydantic import Field, StrictStr from typing import Optional from typing_extensions import Annotated +from otari._client.models.discoverable_models_response import DiscoverableModelsResponse from otari._client.models.model_list_response import ModelListResponse +from otari._client.models.model_metadata_response import ModelMetadataResponse from otari._client.models.model_object import ModelObject from otari._client.api_client import ApiClient, RequestSerialized @@ -303,6 +305,498 @@ def _get_model_v1_models_model_id_get_serialize( + @validate_call + def list_discoverable_models_v1_models_discoverable_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, + ) -> DiscoverableModelsResponse: + """List Discoverable Models + + List every model the configured provider credentials can reach. Operator-facing counterpart to GET /v1/models, which serves a curated catalog to API callers. This reports each provider separately and keeps its error, so a provider with a bad key is distinguishable from one with no models. It is master-key gated because a provider error message describes the gateway's own configuration. + + :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_discoverable_models_v1_models_discoverable_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DiscoverableModelsResponse", + } + 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_discoverable_models_v1_models_discoverable_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[DiscoverableModelsResponse]: + """List Discoverable Models + + List every model the configured provider credentials can reach. Operator-facing counterpart to GET /v1/models, which serves a curated catalog to API callers. This reports each provider separately and keeps its error, so a provider with a bad key is distinguishable from one with no models. It is master-key gated because a provider error message describes the gateway's own configuration. + + :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_discoverable_models_v1_models_discoverable_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DiscoverableModelsResponse", + } + 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_discoverable_models_v1_models_discoverable_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: + """List Discoverable Models + + List every model the configured provider credentials can reach. Operator-facing counterpart to GET /v1/models, which serves a curated catalog to API callers. This reports each provider separately and keeps its error, so a provider with a bad key is distinguishable from one with no models. It is master-key gated because a provider error message describes the gateway's own configuration. + + :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_discoverable_models_v1_models_discoverable_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DiscoverableModelsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_discoverable_models_v1_models_discoverable_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/models/discoverable', + 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_model_metadata_v1_models_metadata_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, + ) -> ModelMetadataResponse: + """List Model Metadata + + Per-model metadata for the dashboard's detail view, from models.dev. Covers every model models.dev lists under a configured provider, keyed by the ``instance:model`` selector the dashboard uses. ``available`` is false when enrichment is disabled (``models_dev_metadata``) or models.dev could not be reached; the response is then empty and the UI falls back to bundled data. Master-key gated: it describes the gateway's configured providers. + + :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_model_metadata_v1_models_metadata_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelMetadataResponse", + } + 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_model_metadata_v1_models_metadata_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[ModelMetadataResponse]: + """List Model Metadata + + Per-model metadata for the dashboard's detail view, from models.dev. Covers every model models.dev lists under a configured provider, keyed by the ``instance:model`` selector the dashboard uses. ``available`` is false when enrichment is disabled (``models_dev_metadata``) or models.dev could not be reached; the response is then empty and the UI falls back to bundled data. Master-key gated: it describes the gateway's configured providers. + + :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_model_metadata_v1_models_metadata_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelMetadataResponse", + } + 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_model_metadata_v1_models_metadata_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: + """List Model Metadata + + Per-model metadata for the dashboard's detail view, from models.dev. Covers every model models.dev lists under a configured provider, keyed by the ``instance:model`` selector the dashboard uses. ``available`` is false when enrichment is disabled (``models_dev_metadata``) or models.dev could not be reached; the response is then empty and the UI falls back to bundled data. Master-key gated: it describes the gateway's configured providers. + + :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_model_metadata_v1_models_metadata_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ModelMetadataResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_model_metadata_v1_models_metadata_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/models/metadata', + 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, diff --git a/src/otari/_client/api/pricing_api.py b/src/otari/_client/api/pricing_api.py index f68e0ea..f15e028 100644 --- a/src/otari/_client/api/pricing_api.py +++ b/src/otari/_client/api/pricing_api.py @@ -1186,7 +1186,7 @@ def set_pricing_v1_pricing_post( ) -> PricingResponse: """Set Pricing - Set or update pricing for a model. + Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest @@ -1254,7 +1254,7 @@ def set_pricing_v1_pricing_post_with_http_info( ) -> ApiResponse[PricingResponse]: """Set Pricing - Set or update pricing for a model. + Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest @@ -1322,7 +1322,7 @@ def set_pricing_v1_pricing_post_without_preload_content( ) -> RESTResponseType: """Set Pricing - Set or update pricing for a model. + Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest diff --git a/src/otari/_client/api/providers_api.py b/src/otari/_client/api/providers_api.py new file mode 100644 index 0000000..f2ad3fe --- /dev/null +++ b/src/otari/_client/api/providers_api.py @@ -0,0 +1,281 @@ +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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.providers_response import ProvidersResponse + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ProvidersApi: + """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_providers_v1_providers_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, + ) -> ProvidersResponse: + """List Providers + + List static metadata for every configured provider. Operator-facing: reports each provider's capabilities, documentation and pricing links, and display name from the bundled any-llm and genai-prices datasets. No provider is contacted, so this is cheap and always available. Master-key gated because it describes the gateway's own configuration. + + :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_providers_v1_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProvidersResponse", + } + 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_providers_v1_providers_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[ProvidersResponse]: + """List Providers + + List static metadata for every configured provider. Operator-facing: reports each provider's capabilities, documentation and pricing links, and display name from the bundled any-llm and genai-prices datasets. No provider is contacted, so this is cheap and always available. Master-key gated because it describes the gateway's own configuration. + + :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_providers_v1_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProvidersResponse", + } + 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_providers_v1_providers_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: + """List Providers + + List static metadata for every configured provider. Operator-facing: reports each provider's capabilities, documentation and pricing links, and display name from the bundled any-llm and genai-prices datasets. No provider is contacted, so this is cheap and always available. Master-key gated because it describes the gateway's own configuration. + + :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_providers_v1_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProvidersResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_providers_v1_providers_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/providers', + 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 index 3193bd8..6b3be77 100644 --- a/src/otari/_client/api/responses_api.py +++ b/src/otari/_client/api/responses_api.py @@ -55,7 +55,7 @@ def create_response_v1_responses_post( ) -> object: """Create Response - OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-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. + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param responses_request: (required) :type responses_request: ResponsesRequest @@ -123,7 +123,7 @@ def create_response_v1_responses_post_with_http_info( ) -> 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 hybrid mode. Hybrid-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. + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param responses_request: (required) :type responses_request: ResponsesRequest @@ -191,7 +191,7 @@ def create_response_v1_responses_post_without_preload_content( ) -> RESTResponseType: """Create Response - OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-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. + OpenAI-compatible Responses endpoint. Supports MCP tool-use loops, sandboxed code execution, and SearXNG web_search in both standalone mode and hybrid mode. Hybrid-mode requests resolve credentials via the platform service and get multi-attempt fallback across the resolved route, tool-loop requests included (fallback applies up to the pre-lock-in point, same as chat). :param responses_request: (required) :type responses_request: ResponsesRequest diff --git a/src/otari/_client/api/settings_api.py b/src/otari/_client/api/settings_api.py new file mode 100644 index 0000000..0eaa805 --- /dev/null +++ b/src/otari/_client/api/settings_api.py @@ -0,0 +1,559 @@ +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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.gateway_settings import GatewaySettings +from otari._client.models.update_settings_request import UpdateSettingsRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class SettingsApi: + """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_settings_v1_settings_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, + ) -> GatewaySettings: + """Get Settings + + Return non-secret runtime settings for the admin dashboard. + + :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_settings_v1_settings_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + } + 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_settings_v1_settings_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[GatewaySettings]: + """Get Settings + + Return non-secret runtime settings for the admin dashboard. + + :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_settings_v1_settings_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + } + 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_settings_v1_settings_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: + """Get Settings + + Return non-secret runtime settings for the admin dashboard. + + :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_settings_v1_settings_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_settings_v1_settings_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/settings', + 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_settings_v1_settings_patch( + self, + update_settings_request: UpdateSettingsRequest, + _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, + ) -> GatewaySettings: + """Update Settings + + Persist and apply runtime setting toggles. Each provided flag is stored as an override (winning over config/env) and applied to the running gateway immediately. Master-key gated: these change how the gateway meters and lists models. + + :param update_settings_request: (required) + :type update_settings_request: UpdateSettingsRequest + :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_settings_v1_settings_patch_serialize( + update_settings_request=update_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + '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_settings_v1_settings_patch_with_http_info( + self, + update_settings_request: UpdateSettingsRequest, + _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[GatewaySettings]: + """Update Settings + + Persist and apply runtime setting toggles. Each provided flag is stored as an override (winning over config/env) and applied to the running gateway immediately. Master-key gated: these change how the gateway meters and lists models. + + :param update_settings_request: (required) + :type update_settings_request: UpdateSettingsRequest + :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_settings_v1_settings_patch_serialize( + update_settings_request=update_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + '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_settings_v1_settings_patch_without_preload_content( + self, + update_settings_request: UpdateSettingsRequest, + _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 Settings + + Persist and apply runtime setting toggles. Each provided flag is stored as an override (winning over config/env) and applied to the running gateway immediately. Master-key gated: these change how the gateway meters and lists models. + + :param update_settings_request: (required) + :type update_settings_request: UpdateSettingsRequest + :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_settings_v1_settings_patch_serialize( + update_settings_request=update_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "GatewaySettings", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_settings_v1_settings_patch_serialize( + self, + update_settings_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 update_settings_request is not None: + _body_params = update_settings_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] = [ + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/settings', + 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/models/__init__.py b/src/otari/_client/models/__init__.py index e0a75c0..5f7ee1e 100644 --- a/src/otari/_client/models/__init__.py +++ b/src/otari/_client/models/__init__.py @@ -13,6 +13,8 @@ """ # noqa: E501 # import models into model package +from otari._client.models.alias_request import AliasRequest +from otari._client.models.alias_response import AliasResponse 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 @@ -69,9 +71,13 @@ 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.discoverable_model import DiscoverableModel +from otari._client.models.discoverable_models_response import DiscoverableModelsResponse +from otari._client.models.discoverable_provider import DiscoverableProvider 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.gateway_settings import GatewaySettings from otari._client.models.guardrail_config import GuardrailConfig from otari._client.models.http_validation_error import HTTPValidationError from otari._client.models.img_image import IMGImage @@ -157,12 +163,17 @@ 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_metadata import ModelMetadata +from otari._client.models.model_metadata_response import ModelMetadataResponse 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.provider_capabilities_schema import ProviderCapabilitiesSchema +from otari._client.models.provider_info_schema import ProviderInfoSchema +from otari._client.models.providers_response import ProvidersResponse 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 @@ -178,6 +189,7 @@ from otari._client.models.tool_choice1 import ToolChoice1 from otari._client.models.update_budget_request import UpdateBudgetRequest from otari._client.models.update_key_request import UpdateKeyRequest +from otari._client.models.update_settings_request import UpdateSettingsRequest 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 diff --git a/src/otari/_client/models/alias_request.py b/src/otari/_client/models/alias_request.py new file mode 100644 index 0000000..f9e4f04 --- /dev/null +++ b/src/otari/_client/models/alias_request.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AliasRequest(BaseModel): + """ + Request to create or update an alias. + """ # noqa: E501 + name: StrictStr = Field(description="Display name callers use as the model, e.g. 'fast-model'.") + target: StrictStr = Field(description="Selector the alias resolves to, as 'provider:model' or 'instance:model'.") + __properties: ClassVar[List[str]] = ["name", "target"] + + 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 AliasRequest 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 AliasRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "name": obj.get("name"), + "target": obj.get("target") + }) + return _obj + + diff --git a/src/otari/_client/models/alias_response.py b/src/otari/_client/models/alias_response.py new file mode 100644 index 0000000..a12682b --- /dev/null +++ b/src/otari/_client/models/alias_response.py @@ -0,0 +1,106 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 AliasResponse(BaseModel): + """ + A model alias and where it is defined. + """ # noqa: E501 + created_at: Optional[StrictStr] = None + name: StrictStr + source: StrictStr + target: StrictStr + updated_at: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["created_at", "name", "source", "target", "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 AliasResponse 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 created_at (nullable) is None + # and model_fields_set contains the field + if self.created_at is None and "created_at" in self.model_fields_set: + _dict['created_at'] = None + + # set to None if updated_at (nullable) is None + # and model_fields_set contains the field + if self.updated_at is None and "updated_at" in self.model_fields_set: + _dict['updated_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AliasResponse 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"), + "name": obj.get("name"), + "source": obj.get("source"), + "target": obj.get("target"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/src/otari/_client/models/cc_chat_completion_message.py b/src/otari/_client/models/cc_chat_completion_message.py index 1590978..b2f5859 100644 --- a/src/otari/_client/models/cc_chat_completion_message.py +++ b/src/otari/_client/models/cc_chat_completion_message.py @@ -38,8 +38,9 @@ class CCChatCompletionMessage(BaseModel): function_call: Optional[CCFunctionCall] = None tool_calls: Optional[List[CCChatCompletionMessageToolCallsInner]] = None reasoning: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + extra_content: Optional[Dict[str, Any]] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["content", "refusal", "role", "annotations", "audio", "function_call", "tool_calls", "reasoning"] + __properties: ClassVar[List[str]] = ["content", "refusal", "role", "annotations", "audio", "function_call", "tool_calls", "reasoning", "extra_content"] @field_validator('role') def role_validate_enum(cls, value): @@ -142,6 +143,11 @@ def to_dict(self) -> Dict[str, Any]: if self.reasoning is None and "reasoning" in self.model_fields_set: _dict['reasoning'] = None + # set to None if extra_content (nullable) is None + # and model_fields_set contains the field + if self.extra_content is None and "extra_content" in self.model_fields_set: + _dict['extra_content'] = None + return _dict @classmethod @@ -161,7 +167,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "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": obj.get("reasoning") + "reasoning": obj.get("reasoning"), + "extra_content": obj.get("extra_content") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/src/otari/_client/models/cck_choice_delta.py b/src/otari/_client/models/cck_choice_delta.py index ebdb11d..75688e2 100644 --- a/src/otari/_client/models/cck_choice_delta.py +++ b/src/otari/_client/models/cck_choice_delta.py @@ -35,8 +35,9 @@ class CCKChoiceDelta(BaseModel): role: Optional[StrictStr] = None tool_calls: Optional[List[CCKChoiceDeltaToolCall]] = None reasoning: Optional[StrictStr] = Field(default=None, description="Filter models by provider name") + extra_content: Optional[Dict[str, Any]] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["content", "function_call", "refusal", "role", "tool_calls", "reasoning"] + __properties: ClassVar[List[str]] = ["content", "function_call", "refusal", "role", "tool_calls", "reasoning", "extra_content"] @field_validator('role') def role_validate_enum(cls, value): @@ -134,6 +135,11 @@ def to_dict(self) -> Dict[str, Any]: if self.reasoning is None and "reasoning" in self.model_fields_set: _dict['reasoning'] = None + # set to None if extra_content (nullable) is None + # and model_fields_set contains the field + if self.extra_content is None and "extra_content" in self.model_fields_set: + _dict['extra_content'] = None + return _dict @classmethod @@ -151,7 +157,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "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": obj.get("reasoning") + "reasoning": obj.get("reasoning"), + "extra_content": obj.get("extra_content") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/src/otari/_client/models/cck_choice_delta_function_call.py b/src/otari/_client/models/cck_choice_delta_function_call.py index c9d4b0f..db8a66e 100644 --- a/src/otari/_client/models/cck_choice_delta_function_call.py +++ b/src/otari/_client/models/cck_choice_delta_function_call.py @@ -28,7 +28,7 @@ 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") + name: Optional[StrictStr] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["arguments", "name"] diff --git a/src/otari/_client/models/cck_choice_delta_tool_call.py b/src/otari/_client/models/cck_choice_delta_tool_call.py index 424165a..06ab174 100644 --- a/src/otari/_client/models/cck_choice_delta_tool_call.py +++ b/src/otari/_client/models/cck_choice_delta_tool_call.py @@ -26,14 +26,15 @@ class CCKChoiceDeltaToolCall(BaseModel): """ - CCKChoiceDeltaToolCall + Streaming counterpart of ``ChatCompletionMessageFunctionToolCall``. Adds the same ``extra_content`` field so provider-specific tool-call metadata (e.g. Gemini's ``thought_signature``) can be carried on streaming deltas, not just on the final non-streaming tool call. """ # noqa: E501 index: StrictInt id: Optional[StrictStr] = None function: Optional[CCKChoiceDeltaToolCallFunction] = None type: Optional[StrictStr] = None + extra_content: Optional[Dict[str, Any]] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["index", "id", "function", "type"] + __properties: ClassVar[List[str]] = ["index", "id", "function", "type", "extra_content"] @field_validator('type') def type_validate_enum(cls, value): @@ -109,6 +110,11 @@ def to_dict(self) -> Dict[str, Any]: if self.type is None and "type" in self.model_fields_set: _dict['type'] = None + # set to None if extra_content (nullable) is None + # and model_fields_set contains the field + if self.extra_content is None and "extra_content" in self.model_fields_set: + _dict['extra_content'] = None + return _dict @classmethod @@ -124,7 +130,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "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") + "type": obj.get("type"), + "extra_content": obj.get("extra_content") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/src/otari/_client/models/create_batch_request.py b/src/otari/_client/models/create_batch_request.py index 63571ef..ff8dadd 100644 --- a/src/otari/_client/models/create_batch_request.py +++ b/src/otari/_client/models/create_batch_request.py @@ -33,7 +33,8 @@ class CreateBatchRequest(BaseModel): 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"] + user: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["completion_window", "metadata", "model", "requests", "user"] model_config = ConfigDict( validate_by_name=True, @@ -86,6 +87,11 @@ def to_dict(self) -> Dict[str, Any]: if self.metadata is None and "metadata" in self.model_fields_set: _dict['metadata'] = 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 @@ -101,7 +107,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "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 + "requests": [BatchRequestItem.from_dict(_item) for _item in obj["requests"]] if obj.get("requests") is not None else None, + "user": obj.get("user") }) return _obj diff --git a/src/otari/_client/models/discoverable_model.py b/src/otari/_client/models/discoverable_model.py new file mode 100644 index 0000000..34e7128 --- /dev/null +++ b/src/otari/_client/models/discoverable_model.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class DiscoverableModel(BaseModel): + """ + A model one provider instance reports as available. + """ # noqa: E501 + id: StrictStr = Field(description="Bare model id as the provider reports it.") + key: StrictStr = Field(description="Selector to send as `model`, in `instance:model` form.") + __properties: ClassVar[List[str]] = ["id", "key"] + + 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 DiscoverableModel 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 DiscoverableModel 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"), + "key": obj.get("key") + }) + return _obj + + diff --git a/src/otari/_client/models/discoverable_models_response.py b/src/otari/_client/models/discoverable_models_response.py new file mode 100644 index 0000000..fad5da1 --- /dev/null +++ b/src/otari/_client/models/discoverable_models_response.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 +from otari._client.models.discoverable_provider import DiscoverableProvider +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class DiscoverableModelsResponse(BaseModel): + """ + Per-provider discovery results for operator model selection. + """ # noqa: E501 + providers: List[DiscoverableProvider] + __properties: ClassVar[List[str]] = ["providers"] + + 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 DiscoverableModelsResponse 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 providers (list) + _items = [] + if self.providers: + for _item_providers in self.providers: + if _item_providers: + _items.append(_item_providers.to_dict()) + _dict['providers'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DiscoverableModelsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "providers": [DiscoverableProvider.from_dict(_item) for _item in obj["providers"]] if obj.get("providers") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/discoverable_provider.py b/src/otari/_client/models/discoverable_provider.py new file mode 100644 index 0000000..46bf17f --- /dev/null +++ b/src/otari/_client/models/discoverable_provider.py @@ -0,0 +1,107 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 otari._client.models.discoverable_model import DiscoverableModel +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class DiscoverableProvider(BaseModel): + """ + One provider instance's discovery result. + """ # noqa: E501 + error: Optional[StrictStr] = Field(default=None, description="Why discovery failed. Null when `ok` is true.") + models: List[DiscoverableModel] + ok: StrictBool = Field(description="False when this instance could not be queried.") + provider: StrictStr + __properties: ClassVar[List[str]] = ["error", "models", "ok", "provider"] + + 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 DiscoverableProvider 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 models (list) + _items = [] + if self.models: + for _item_models in self.models: + if _item_models: + _items.append(_item_models.to_dict()) + _dict['models'] = _items + # set to None if error (nullable) is None + # and model_fields_set contains the field + if self.error is None and "error" in self.model_fields_set: + _dict['error'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DiscoverableProvider from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error": obj.get("error"), + "models": [DiscoverableModel.from_dict(_item) for _item in obj["models"]] if obj.get("models") is not None else None, + "ok": obj.get("ok"), + "provider": obj.get("provider") + }) + return _obj + + diff --git a/src/otari/_client/models/gateway_settings.py b/src/otari/_client/models/gateway_settings.py new file mode 100644 index 0000000..c3e4b20 --- /dev/null +++ b/src/otari/_client/models/gateway_settings.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class GatewaySettings(BaseModel): + """ + Operator-facing runtime settings surfaced to the dashboard. + """ # noqa: E501 + default_pricing: StrictBool + mode: StrictStr + model_discovery: StrictBool + require_pricing: StrictBool + version: StrictStr + __properties: ClassVar[List[str]] = ["default_pricing", "mode", "model_discovery", "require_pricing", "version"] + + 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 GatewaySettings 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 GatewaySettings from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "default_pricing": obj.get("default_pricing"), + "mode": obj.get("mode"), + "model_discovery": obj.get("model_discovery"), + "require_pricing": obj.get("require_pricing"), + "version": obj.get("version") + }) + return _obj + + diff --git a/src/otari/_client/models/messages_request.py b/src/otari/_client/models/messages_request.py index 31bbad2..33b3d5f 100644 --- a/src/otari/_client/models/messages_request.py +++ b/src/otari/_client/models/messages_request.py @@ -41,6 +41,7 @@ class MessagesRequest(BaseModel): messages: Annotated[List[Dict[str, Any]], Field(min_length=1)] metadata: Optional[Dict[str, Any]] = None model: StrictStr + output_format: Optional[Dict[str, Any]] = None session_label: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.") stop_sequences: Optional[List[StrictStr]] = None stream: Optional[StrictBool] = False @@ -52,7 +53,7 @@ class MessagesRequest(BaseModel): 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", "session_label", "stop_sequences", "stream", "system", "temperature", "thinking", "tool_choice", "tools", "tools_header", "top_k", "top_p"] + __properties: ClassVar[List[str]] = ["cache_control", "guardrails", "max_tokens", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "messages", "metadata", "model", "output_format", "session_label", "stop_sequences", "stream", "system", "temperature", "thinking", "tool_choice", "tools", "tools_header", "top_k", "top_p"] model_config = ConfigDict( validate_by_name=True, @@ -140,6 +141,11 @@ def to_dict(self) -> Dict[str, Any]: if self.metadata is None and "metadata" in self.model_fields_set: _dict['metadata'] = None + # set to None if output_format (nullable) is None + # and model_fields_set contains the field + if self.output_format is None and "output_format" in self.model_fields_set: + _dict['output_format'] = None + # set to None if session_label (nullable) is None # and model_fields_set contains the field if self.session_label is None and "session_label" in self.model_fields_set: @@ -211,6 +217,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "messages": obj.get("messages"), "metadata": obj.get("metadata"), "model": obj.get("model"), + "output_format": obj.get("output_format"), "session_label": obj.get("session_label"), "stop_sequences": obj.get("stop_sequences"), "stream": obj.get("stream") if obj.get("stream") is not None else False, diff --git a/src/otari/_client/models/model_metadata.py b/src/otari/_client/models/model_metadata.py new file mode 100644 index 0000000..8f334fc --- /dev/null +++ b/src/otari/_client/models/model_metadata.py @@ -0,0 +1,174 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 ModelMetadata(BaseModel): + """ + models.dev metadata for one model, for the dashboard's detail view. + """ # noqa: E501 + attachment: Optional[StrictBool] = False + context_window: Optional[StrictInt] = None + cost_input: Optional[Union[StrictFloat, StrictInt]] = None + cost_output: Optional[Union[StrictFloat, StrictInt]] = None + deprecated: Optional[StrictBool] = False + description: Optional[StrictStr] = None + family: Optional[StrictStr] = None + input_modalities: Optional[List[StrictStr]] = None + knowledge_cutoff: Optional[StrictStr] = None + last_updated: Optional[StrictStr] = None + max_output_tokens: Optional[StrictInt] = None + name: Optional[StrictStr] = None + open_weights: Optional[StrictBool] = False + output_modalities: Optional[List[StrictStr]] = None + reasoning: Optional[StrictBool] = False + release_date: Optional[StrictStr] = None + structured_output: Optional[StrictBool] = False + temperature: Optional[StrictBool] = False + tool_call: Optional[StrictBool] = False + __properties: ClassVar[List[str]] = ["attachment", "context_window", "cost_input", "cost_output", "deprecated", "description", "family", "input_modalities", "knowledge_cutoff", "last_updated", "max_output_tokens", "name", "open_weights", "output_modalities", "reasoning", "release_date", "structured_output", "temperature", "tool_call"] + + 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 ModelMetadata 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 context_window (nullable) is None + # and model_fields_set contains the field + if self.context_window is None and "context_window" in self.model_fields_set: + _dict['context_window'] = None + + # set to None if cost_input (nullable) is None + # and model_fields_set contains the field + if self.cost_input is None and "cost_input" in self.model_fields_set: + _dict['cost_input'] = None + + # set to None if cost_output (nullable) is None + # and model_fields_set contains the field + if self.cost_output is None and "cost_output" in self.model_fields_set: + _dict['cost_output'] = None + + # set to None if description (nullable) is None + # and model_fields_set contains the field + if self.description is None and "description" in self.model_fields_set: + _dict['description'] = None + + # set to None if family (nullable) is None + # and model_fields_set contains the field + if self.family is None and "family" in self.model_fields_set: + _dict['family'] = None + + # set to None if knowledge_cutoff (nullable) is None + # and model_fields_set contains the field + if self.knowledge_cutoff is None and "knowledge_cutoff" in self.model_fields_set: + _dict['knowledge_cutoff'] = None + + # set to None if last_updated (nullable) is None + # and model_fields_set contains the field + if self.last_updated is None and "last_updated" in self.model_fields_set: + _dict['last_updated'] = None + + # set to None if max_output_tokens (nullable) is None + # and model_fields_set contains the field + if self.max_output_tokens is None and "max_output_tokens" in self.model_fields_set: + _dict['max_output_tokens'] = 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 + + # set to None if release_date (nullable) is None + # and model_fields_set contains the field + if self.release_date is None and "release_date" in self.model_fields_set: + _dict['release_date'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModelMetadata from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "attachment": obj.get("attachment") if obj.get("attachment") is not None else False, + "context_window": obj.get("context_window"), + "cost_input": obj.get("cost_input"), + "cost_output": obj.get("cost_output"), + "deprecated": obj.get("deprecated") if obj.get("deprecated") is not None else False, + "description": obj.get("description"), + "family": obj.get("family"), + "input_modalities": obj.get("input_modalities"), + "knowledge_cutoff": obj.get("knowledge_cutoff"), + "last_updated": obj.get("last_updated"), + "max_output_tokens": obj.get("max_output_tokens"), + "name": obj.get("name"), + "open_weights": obj.get("open_weights") if obj.get("open_weights") is not None else False, + "output_modalities": obj.get("output_modalities"), + "reasoning": obj.get("reasoning") if obj.get("reasoning") is not None else False, + "release_date": obj.get("release_date"), + "structured_output": obj.get("structured_output") if obj.get("structured_output") is not None else False, + "temperature": obj.get("temperature") if obj.get("temperature") is not None else False, + "tool_call": obj.get("tool_call") if obj.get("tool_call") is not None else False + }) + return _obj + + diff --git a/src/otari/_client/models/model_metadata_response.py b/src/otari/_client/models/model_metadata_response.py new file mode 100644 index 0000000..ca2a0b2 --- /dev/null +++ b/src/otari/_client/models/model_metadata_response.py @@ -0,0 +1,105 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 otari._client.models.model_metadata import ModelMetadata +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ModelMetadataResponse(BaseModel): + """ + models.dev metadata keyed by ``provider:model``. + """ # noqa: E501 + available: StrictBool = Field(description="False when metadata could not be loaded (enrichment disabled or models.dev unreachable).") + models: Optional[Dict[str, ModelMetadata]] = None + source: Optional[StrictStr] = 'models.dev' + __properties: ClassVar[List[str]] = ["available", "models", "source"] + + 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 ModelMetadataResponse 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 value in models (dict) + _field_dict = {} + if self.models: + for _key_models in self.models: + if self.models[_key_models]: + _field_dict[_key_models] = self.models[_key_models].to_dict() + _dict['models'] = _field_dict + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ModelMetadataResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "available": obj.get("available"), + "models": dict( + (_k, ModelMetadata.from_dict(_v)) + for _k, _v in obj["models"].items() + ) + if obj.get("models") is not None + else None, + "source": obj.get("source") if obj.get("source") is not None else 'models.dev' + }) + return _obj + + diff --git a/src/otari/_client/models/model_object.py b/src/otari/_client/models/model_object.py index c96fa7f..9c90023 100644 --- a/src/otari/_client/models/model_object.py +++ b/src/otari/_client/models/model_object.py @@ -28,12 +28,14 @@ class ModelObject(BaseModel): """ OpenAI-compatible model object. """ # noqa: E501 + context_window: Optional[StrictInt] = None 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"] + pricing_source: Optional[StrictStr] = 'none' + __properties: ClassVar[List[str]] = ["context_window", "created", "id", "object", "owned_by", "pricing", "pricing_source"] model_config = ConfigDict( validate_by_name=True, @@ -77,6 +79,11 @@ def to_dict(self) -> Dict[str, Any]: # 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 context_window (nullable) is None + # and model_fields_set contains the field + if self.context_window is None and "context_window" in self.model_fields_set: + _dict['context_window'] = None + # 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: @@ -94,11 +101,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "context_window": obj.get("context_window"), "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 + "pricing": ModelPricingInfo.from_dict(obj["pricing"]) if obj.get("pricing") is not None else None, + "pricing_source": obj.get("pricing_source") if obj.get("pricing_source") is not None else 'none' }) return _obj diff --git a/src/otari/_client/models/provider_capabilities_schema.py b/src/otari/_client/models/provider_capabilities_schema.py new file mode 100644 index 0000000..8ce3387 --- /dev/null +++ b/src/otari/_client/models/provider_capabilities_schema.py @@ -0,0 +1,108 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 ProviderCapabilitiesSchema(BaseModel): + """ + Curated capability flags for a provider. + """ # noqa: E501 + audio: StrictBool + embeddings: StrictBool + image_generation: StrictBool + list_models: StrictBool + moderation: StrictBool + pdf: StrictBool + reasoning: StrictBool + rerank: StrictBool + responses_api: StrictBool + streaming: StrictBool + vision: StrictBool + __properties: ClassVar[List[str]] = ["audio", "embeddings", "image_generation", "list_models", "moderation", "pdf", "reasoning", "rerank", "responses_api", "streaming", "vision"] + + 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 ProviderCapabilitiesSchema 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 ProviderCapabilitiesSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "audio": obj.get("audio"), + "embeddings": obj.get("embeddings"), + "image_generation": obj.get("image_generation"), + "list_models": obj.get("list_models"), + "moderation": obj.get("moderation"), + "pdf": obj.get("pdf"), + "reasoning": obj.get("reasoning"), + "rerank": obj.get("rerank"), + "responses_api": obj.get("responses_api"), + "streaming": obj.get("streaming"), + "vision": obj.get("vision") + }) + return _obj + + diff --git a/src/otari/_client/models/provider_info_schema.py b/src/otari/_client/models/provider_info_schema.py new file mode 100644 index 0000000..9118b39 --- /dev/null +++ b/src/otari/_client/models/provider_info_schema.py @@ -0,0 +1,121 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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.provider_capabilities_schema import ProviderCapabilitiesSchema +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ProviderInfoSchema(BaseModel): + """ + Static, network-free metadata for one configured provider instance. + """ # noqa: E501 + capabilities: ProviderCapabilitiesSchema + description: Optional[StrictStr] = None + doc_url: Optional[StrictStr] = None + env_key: Optional[StrictStr] = Field(default=None, description="Env var the credential is read from.") + instance: StrictStr = Field(description="Configured provider key (may differ from the type).") + name: StrictStr = Field(description="Human-friendly provider name.") + pricing_urls: Optional[List[StrictStr]] = None + provider_type: StrictStr = Field(description="Underlying any-llm provider type.") + __properties: ClassVar[List[str]] = ["capabilities", "description", "doc_url", "env_key", "instance", "name", "pricing_urls", "provider_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 ProviderInfoSchema 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 capabilities + if self.capabilities: + _dict['capabilities'] = self.capabilities.to_dict() + # set to None if description (nullable) is None + # and model_fields_set contains the field + if self.description is None and "description" in self.model_fields_set: + _dict['description'] = None + + # set to None if doc_url (nullable) is None + # and model_fields_set contains the field + if self.doc_url is None and "doc_url" in self.model_fields_set: + _dict['doc_url'] = None + + # set to None if env_key (nullable) is None + # and model_fields_set contains the field + if self.env_key is None and "env_key" in self.model_fields_set: + _dict['env_key'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ProviderInfoSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "capabilities": ProviderCapabilitiesSchema.from_dict(obj["capabilities"]) if obj.get("capabilities") is not None else None, + "description": obj.get("description"), + "doc_url": obj.get("doc_url"), + "env_key": obj.get("env_key"), + "instance": obj.get("instance"), + "name": obj.get("name"), + "pricing_urls": obj.get("pricing_urls"), + "provider_type": obj.get("provider_type") + }) + return _obj + + diff --git a/src/otari/_client/models/providers_response.py b/src/otari/_client/models/providers_response.py new file mode 100644 index 0000000..3c11c97 --- /dev/null +++ b/src/otari/_client/models/providers_response.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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 +from otari._client.models.provider_info_schema import ProviderInfoSchema +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ProvidersResponse(BaseModel): + """ + Metadata for every configured provider. + """ # noqa: E501 + providers: List[ProviderInfoSchema] + __properties: ClassVar[List[str]] = ["providers"] + + 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 ProvidersResponse 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 providers (list) + _items = [] + if self.providers: + for _item_providers in self.providers: + if _item_providers: + _items.append(_item_providers.to_dict()) + _dict['providers'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ProvidersResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "providers": [ProviderInfoSchema.from_dict(_item) for _item in obj["providers"]] if obj.get("providers") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/update_settings_request.py b/src/otari/_client/models/update_settings_request.py new file mode 100644 index 0000000..7f9311e --- /dev/null +++ b/src/otari/_client/models/update_settings_request.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway 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, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateSettingsRequest(BaseModel): + """ + Toggle one or more runtime settings. Omitted fields are left unchanged. + """ # noqa: E501 + default_pricing: Optional[StrictBool] = None + model_discovery: Optional[StrictBool] = None + __properties: ClassVar[List[str]] = ["default_pricing", "model_discovery"] + + 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 UpdateSettingsRequest 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 default_pricing (nullable) is None + # and model_fields_set contains the field + if self.default_pricing is None and "default_pricing" in self.model_fields_set: + _dict['default_pricing'] = None + + # set to None if model_discovery (nullable) is None + # and model_fields_set contains the field + if self.model_discovery is None and "model_discovery" in self.model_fields_set: + _dict['model_discovery'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateSettingsRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "default_pricing": obj.get("default_pricing"), + "model_discovery": obj.get("model_discovery") + }) + return _obj + +