diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py index a3c18c1..23a8a46 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,11 @@ "ModelsApi", "ModerationsApi", "PricingApi", + "ProvidersApi", "RerankApi", "ResponsesApi", + "SettingsApi", + "ToolSettingsApi", "UsageApi", "UsersApi", "ApiResponse", @@ -44,8 +48,11 @@ "ApiKeyError", "ApiAttributeError", "ApiException", + "AliasRequest", + "AliasResponse", "AudioSpeechRequest", "BatchRequestItem", + "BudgetResetLogResponse", "BudgetResponse", "CCChatCompletionAudio", "CCChatCompletionMessage", @@ -79,6 +86,7 @@ "ChatCompletionRequest", "ChatCompletionRequestToolsInner", "ChatMessageInput", + "ConfigField", "Content", "Content1", "Content2", @@ -99,10 +107,15 @@ "CreateEmbeddingResponse", "CreateKeyRequest", "CreateKeyResponse", + "CreateStoredProviderRequest", "CreateUserRequest", + "DiscoverableModel", + "DiscoverableModelsResponse", + "DiscoverableProvider", "EMBEmbedding", "EMBUsage", "EmbeddingRequest", + "GatewaySettings", "GuardrailConfig", "HTTPValidationError", "IMGImage", @@ -114,6 +127,7 @@ "Input", "Input1", "KeyInfo", + "KnownProviderSchema", "LocationInner", "MRBase64PDFSource", "MRBashCodeExecutionOutputBlock", @@ -188,12 +202,19 @@ "MessagesRequest", "Model", "ModelListResponse", + "ModelMetadata", + "ModelMetadataResponse", "ModelObject", "ModelPricingInfo", "ModerationRequest", "ModerationResponse", "ModerationResult", "PricingResponse", + "ProviderCapabilitiesSchema", + "ProviderHealthResponse", + "ProviderHealthSchema", + "ProviderInfoSchema", + "ProvidersResponse", "RRRerankMeta", "RRRerankResult", "RRRerankUsage", @@ -203,20 +224,38 @@ "SetPricingRequest", "Source", "Stop", + "StoredProviderResponse", "System", + "TestProviderRequest", + "TestProviderResponse", + "TestServiceRequest", + "TestServiceResponse", "ToolCallsInner", "ToolChoice", "ToolChoice1", + "ToolSettingField", + "ToolSettingsResponse", "UpdateBudgetRequest", "UpdateKeyRequest", + "UpdateSettingsRequest", + "UpdateStoredProviderRequest", + "UpdateToolSettingsRequest", "UpdateUserRequest", + "UsageCount", "UsageEntry", + "UsageGroupRow", "UsageLogResponse", + "UsageSeriesPoint", + "UsageSummary", + "UsageTotals", "UserResponse", "ValidationError", + "Value", + "Value1", ] # 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 +269,11 @@ 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.tool_settings_api import ToolSettingsApi as ToolSettingsApi from otari._client.api.usage_api import UsageApi as UsageApi from otari._client.api.users_api import UsersApi as UsersApi @@ -247,8 +289,11 @@ 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_reset_log_response import BudgetResetLogResponse as BudgetResetLogResponse from otari._client.models.budget_response import BudgetResponse as BudgetResponse from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio as CCChatCompletionAudio from otari._client.models.cc_chat_completion_message import CCChatCompletionMessage as CCChatCompletionMessage @@ -282,6 +327,7 @@ from otari._client.models.chat_completion_request import ChatCompletionRequest as ChatCompletionRequest from otari._client.models.chat_completion_request_tools_inner import ChatCompletionRequestToolsInner as ChatCompletionRequestToolsInner from otari._client.models.chat_message_input import ChatMessageInput as ChatMessageInput +from otari._client.models.config_field import ConfigField as ConfigField from otari._client.models.content import Content as Content from otari._client.models.content1 import Content1 as Content1 from otari._client.models.content2 import Content2 as Content2 @@ -302,10 +348,15 @@ from otari._client.models.create_embedding_response import CreateEmbeddingResponse as CreateEmbeddingResponse from otari._client.models.create_key_request import CreateKeyRequest as CreateKeyRequest from otari._client.models.create_key_response import CreateKeyResponse as CreateKeyResponse +from otari._client.models.create_stored_provider_request import CreateStoredProviderRequest as CreateStoredProviderRequest 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 @@ -317,6 +368,7 @@ from otari._client.models.input import Input as Input from otari._client.models.input1 import Input1 as Input1 from otari._client.models.key_info import KeyInfo as KeyInfo +from otari._client.models.known_provider_schema import KnownProviderSchema as KnownProviderSchema from otari._client.models.location_inner import LocationInner as LocationInner from otari._client.models.mr_base64_pdf_source import MRBase64PDFSource as MRBase64PDFSource from otari._client.models.mr_bash_code_execution_output_block import MRBashCodeExecutionOutputBlock as MRBashCodeExecutionOutputBlock @@ -391,12 +443,19 @@ 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_health_response import ProviderHealthResponse as ProviderHealthResponse +from otari._client.models.provider_health_schema import ProviderHealthSchema as ProviderHealthSchema +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 @@ -406,15 +465,32 @@ from otari._client.models.set_pricing_request import SetPricingRequest as SetPricingRequest from otari._client.models.source import Source as Source from otari._client.models.stop import Stop as Stop +from otari._client.models.stored_provider_response import StoredProviderResponse as StoredProviderResponse from otari._client.models.system import System as System +from otari._client.models.test_provider_request import TestProviderRequest as TestProviderRequest +from otari._client.models.test_provider_response import TestProviderResponse as TestProviderResponse +from otari._client.models.test_service_request import TestServiceRequest as TestServiceRequest +from otari._client.models.test_service_response import TestServiceResponse as TestServiceResponse from otari._client.models.tool_calls_inner import ToolCallsInner as ToolCallsInner from otari._client.models.tool_choice import ToolChoice as ToolChoice from otari._client.models.tool_choice1 import ToolChoice1 as ToolChoice1 +from otari._client.models.tool_setting_field import ToolSettingField as ToolSettingField +from otari._client.models.tool_settings_response import ToolSettingsResponse as ToolSettingsResponse 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_stored_provider_request import UpdateStoredProviderRequest as UpdateStoredProviderRequest +from otari._client.models.update_tool_settings_request import UpdateToolSettingsRequest as UpdateToolSettingsRequest from otari._client.models.update_user_request import UpdateUserRequest as UpdateUserRequest +from otari._client.models.usage_count import UsageCount as UsageCount from otari._client.models.usage_entry import UsageEntry as UsageEntry +from otari._client.models.usage_group_row import UsageGroupRow as UsageGroupRow from otari._client.models.usage_log_response import UsageLogResponse as UsageLogResponse +from otari._client.models.usage_series_point import UsageSeriesPoint as UsageSeriesPoint +from otari._client.models.usage_summary import UsageSummary as UsageSummary +from otari._client.models.usage_totals import UsageTotals as UsageTotals from otari._client.models.user_response import UserResponse as UserResponse from otari._client.models.validation_error import ValidationError as ValidationError +from otari._client.models.value import Value as Value +from otari._client.models.value1 import Value1 as Value1 diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py index ae486dd..fa92b9b 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,11 @@ 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.tool_settings_api import ToolSettingsApi 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..26cc5fb --- /dev/null +++ b/src/otari/_client/api/aliases_api.py @@ -0,0 +1,828 @@ +""" + 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] = [ + 'XApiKeyAuth', + '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] = [ + 'XApiKeyAuth', + '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] = [ + 'XApiKeyAuth', + '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/audio_api.py b/src/otari/_client/api/audio_api.py index aed06a2..954591f 100644 --- a/src/otari/_client/api/audio_api.py +++ b/src/otari/_client/api/audio_api.py @@ -56,7 +56,7 @@ def create_speech_v1_audio_speech_post( ) -> object: """Create Speech - OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param audio_speech_request: (required) :type audio_speech_request: AudioSpeechRequest @@ -124,7 +124,7 @@ def create_speech_v1_audio_speech_post_with_http_info( ) -> ApiResponse[object]: """Create Speech - OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param audio_speech_request: (required) :type audio_speech_request: AudioSpeechRequest @@ -192,7 +192,7 @@ def create_speech_v1_audio_speech_post_without_preload_content( ) -> RESTResponseType: """Create Speech - OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio speech (TTS) endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param audio_speech_request: (required) :type audio_speech_request: AudioSpeechRequest @@ -299,6 +299,7 @@ def _create_speech_v1_audio_speech_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -345,7 +346,7 @@ def create_transcription_v1_audio_transcriptions_post( ) -> object: """Create Transcription - OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param file: (required) :type file: str @@ -437,7 +438,7 @@ def create_transcription_v1_audio_transcriptions_post_with_http_info( ) -> ApiResponse[object]: """Create Transcription - OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param file: (required) :type file: str @@ -529,7 +530,7 @@ def create_transcription_v1_audio_transcriptions_post_without_preload_content( ) -> RESTResponseType: """Create Transcription - OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible audio transcription endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param file: (required) :type file: str @@ -666,6 +667,7 @@ def _create_transcription_v1_audio_transcriptions_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/batches_api.py b/src/otari/_client/api/batches_api.py index fda9adb..e36a02f 100644 --- a/src/otari/_client/api/batches_api.py +++ b/src/otari/_client/api/batches_api.py @@ -297,6 +297,7 @@ def _cancel_batch_v1_batches_batch_id_cancel_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -337,7 +338,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 the shared \"default\" user :param create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -405,7 +406,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 the shared \"default\" user :param create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -473,7 +474,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 the shared \"default\" user :param create_batch_request: (required) :type create_batch_request: CreateBatchRequest @@ -574,6 +575,7 @@ def _create_batch_v1_batches_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -616,7 +618,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 +694,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 +770,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 @@ -874,6 +876,7 @@ def _list_batches_v1_batches_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1161,6 +1164,7 @@ def _retrieve_batch_results_v1_batches_batch_id_results_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1442,6 +1446,7 @@ def _retrieve_batch_v1_batches_batch_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/budgets_api.py b/src/otari/_client/api/budgets_api.py index ec5a82f..f13bc49 100644 --- a/src/otari/_client/api/budgets_api.py +++ b/src/otari/_client/api/budgets_api.py @@ -18,6 +18,7 @@ from pydantic import Field, StrictStr from typing import List, Optional from typing_extensions import Annotated +from otari._client.models.budget_reset_log_response import BudgetResetLogResponse from otari._client.models.budget_response import BudgetResponse from otari._client.models.create_budget_request import CreateBudgetRequest from otari._client.models.update_budget_request import UpdateBudgetRequest @@ -296,6 +297,7 @@ def _create_budget_v1_budgets_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -560,6 +562,7 @@ def _delete_budget_v1_budgets_budget_id_delete_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -824,6 +827,7 @@ def _get_budget_v1_budgets_budget_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -845,6 +849,305 @@ def _get_budget_v1_budgets_budget_id_get_serialize( + @validate_call + def list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get( + self, + budget_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[BudgetResetLogResponse]: + """List Budget Reset Logs + + List per-user reset events for a budget, newest first. + + :param budget_id: (required) + :type budget_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_serialize( + budget_id=budget_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResetLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_with_http_info( + self, + budget_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[BudgetResetLogResponse]]: + """List Budget Reset Logs + + List per-user reset events for a budget, newest first. + + :param budget_id: (required) + :type budget_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_serialize( + budget_id=budget_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResetLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_without_preload_content( + self, + budget_id: StrictStr, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Budget Reset Logs + + List per-user reset events for a budget, newest first. + + :param budget_id: (required) + :type budget_id: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_serialize( + budget_id=budget_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[BudgetResetLogResponse]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_budget_reset_logs_v1_budgets_budget_id_reset_logs_get_serialize( + self, + budget_id, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if budget_id is not None: + _path_params['budget_id'] = budget_id + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/budgets/{budget_id}/reset-logs', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def list_budgets_v1_budgets_get( self, @@ -1107,6 +1410,7 @@ def _list_budgets_v1_budgets_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1399,6 +1703,7 @@ def _update_budget_v1_budgets_budget_id_patch_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/chat_api.py b/src/otari/_client/api/chat_api.py index 987bcbf..a22dcf8 100644 --- a/src/otari/_client/api/chat_api.py +++ b/src/otari/_client/api/chat_api.py @@ -55,7 +55,7 @@ def chat_completions_v1_chat_completions_post( ) -> ChatCompletion: """Chat Completions - OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param chat_completion_request: (required) :type chat_completion_request: ChatCompletionRequest @@ -123,7 +123,7 @@ def chat_completions_v1_chat_completions_post_with_http_info( ) -> ApiResponse[ChatCompletion]: """Chat Completions - OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param chat_completion_request: (required) :type chat_completion_request: ChatCompletionRequest @@ -191,7 +191,7 @@ def chat_completions_v1_chat_completions_post_without_preload_content( ) -> RESTResponseType: """Chat Completions - OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible chat completions endpoint. Supports both streaming and non-streaming responses. Handles reasoning content from otari providers. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param chat_completion_request: (required) :type chat_completion_request: ChatCompletionRequest @@ -292,6 +292,7 @@ def _chat_completions_v1_chat_completions_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/embeddings_api.py b/src/otari/_client/api/embeddings_api.py index db99779..6c0254a 100644 --- a/src/otari/_client/api/embeddings_api.py +++ b/src/otari/_client/api/embeddings_api.py @@ -55,7 +55,7 @@ def create_embedding_v1_embeddings_post( ) -> CreateEmbeddingResponse: """Create Embedding - OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param embedding_request: (required) :type embedding_request: EmbeddingRequest @@ -123,7 +123,7 @@ def create_embedding_v1_embeddings_post_with_http_info( ) -> ApiResponse[CreateEmbeddingResponse]: """Create Embedding - OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param embedding_request: (required) :type embedding_request: EmbeddingRequest @@ -191,7 +191,7 @@ def create_embedding_v1_embeddings_post_without_preload_content( ) -> RESTResponseType: """Create Embedding - OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible embeddings endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param embedding_request: (required) :type embedding_request: EmbeddingRequest @@ -292,6 +292,7 @@ def _create_embedding_v1_embeddings_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/files_api.py b/src/otari/_client/api/files_api.py index db9509c..05c7cc4 100644 --- a/src/otari/_client/api/files_api.py +++ b/src/otari/_client/api/files_api.py @@ -322,6 +322,7 @@ def _create_file_v1_files_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -603,6 +604,7 @@ def _delete_file_v1_files_file_id_delete_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -884,6 +886,7 @@ def _get_file_content_v1_files_file_id_content_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1165,6 +1168,7 @@ def _get_file_v1_files_file_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1448,6 +1452,7 @@ def _list_files_v1_files_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/images_api.py b/src/otari/_client/api/images_api.py index 3aeb316..0b27c96 100644 --- a/src/otari/_client/api/images_api.py +++ b/src/otari/_client/api/images_api.py @@ -55,7 +55,7 @@ def create_image_v1_images_generations_post( ) -> ImagesResponse: """Create Image - OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param image_generation_request: (required) :type image_generation_request: ImageGenerationRequest @@ -123,7 +123,7 @@ def create_image_v1_images_generations_post_with_http_info( ) -> ApiResponse[ImagesResponse]: """Create Image - OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param image_generation_request: (required) :type image_generation_request: ImageGenerationRequest @@ -191,7 +191,7 @@ def create_image_v1_images_generations_post_without_preload_content( ) -> RESTResponseType: """Create Image - OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible image generation endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param image_generation_request: (required) :type image_generation_request: ImageGenerationRequest @@ -292,6 +292,7 @@ def _create_image_v1_images_generations_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/keys_api.py b/src/otari/_client/api/keys_api.py index 7721864..e539a52 100644 --- a/src/otari/_client/api/keys_api.py +++ b/src/otari/_client/api/keys_api.py @@ -60,7 +60,7 @@ def create_key_v1_keys_post( ) -> CreateKeyResponse: """Create Key - Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, the key is associated with the shared \"default\" user, which is created on first use. Keys without an explicit owner therefore share one identity, and so share budget, usage, and files. :param create_key_request: (required) :type create_key_request: CreateKeyRequest @@ -128,7 +128,7 @@ def create_key_v1_keys_post_with_http_info( ) -> ApiResponse[CreateKeyResponse]: """Create Key - Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, the key is associated with the shared \"default\" user, which is created on first use. Keys without an explicit owner therefore share one identity, and so share budget, usage, and files. :param create_key_request: (required) :type create_key_request: CreateKeyRequest @@ -196,7 +196,7 @@ def create_key_v1_keys_post_without_preload_content( ) -> RESTResponseType: """Create Key - Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, a new user will be created automatically and the key will be associated with it. + Create a new API key. Requires master key authentication. If user_id is provided, the key will be associated with that user (creates user if it doesn't exist). If user_id is not provided, the key is associated with the shared \"default\" user, which is created on first use. Keys without an explicit owner therefore share one identity, and so share budget, usage, and files. :param create_key_request: (required) :type create_key_request: CreateKeyRequest @@ -297,6 +297,7 @@ def _create_key_v1_keys_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -561,6 +562,7 @@ def _delete_key_v1_keys_key_id_delete_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -825,6 +827,7 @@ def _get_key_v1_keys_key_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1108,6 +1111,7 @@ def _list_keys_v1_keys_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1129,6 +1133,271 @@ 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] = [ + 'XApiKeyAuth', + '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, @@ -1400,6 +1669,7 @@ def _update_key_v1_keys_key_id_patch_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/messages_api.py b/src/otari/_client/api/messages_api.py index 8ef85d5..7ebc867 100644 --- a/src/otari/_client/api/messages_api.py +++ b/src/otari/_client/api/messages_api.py @@ -294,6 +294,7 @@ def _count_message_tokens_v1_messages_count_tokens_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -334,7 +335,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 +403,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 +471,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 @@ -571,6 +572,7 @@ def _create_message_v1_messages_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/models_api.py b/src/otari/_client/api/models_api.py index 3b158f4..9b98553 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 @@ -282,6 +284,7 @@ def _get_model_v1_models_model_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -303,6 +306,500 @@ 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] = [ + 'XApiKeyAuth', + '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] = [ + 'XApiKeyAuth', + '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, @@ -548,6 +1045,7 @@ def _list_models_v1_models_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/moderations_api.py b/src/otari/_client/api/moderations_api.py index 64512a1..3ec4a2e 100644 --- a/src/otari/_client/api/moderations_api.py +++ b/src/otari/_client/api/moderations_api.py @@ -58,7 +58,7 @@ def create_moderation_v1_moderations_post( ) -> ModerationResponse: """Create Moderation - OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param moderation_request: (required) :type moderation_request: ModerationRequest @@ -130,7 +130,7 @@ def create_moderation_v1_moderations_post_with_http_info( ) -> ApiResponse[ModerationResponse]: """Create Moderation - OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param moderation_request: (required) :type moderation_request: ModerationRequest @@ -202,7 +202,7 @@ def create_moderation_v1_moderations_post_without_preload_content( ) -> RESTResponseType: """Create Moderation - OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + OpenAI-compatible moderations endpoint. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param moderation_request: (required) :type moderation_request: ModerationRequest @@ -311,6 +311,7 @@ def _create_moderation_v1_moderations_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/pricing_api.py b/src/otari/_client/api/pricing_api.py index f68e0ea..571d395 100644 --- a/src/otari/_client/api/pricing_api.py +++ b/src/otari/_client/api/pricing_api.py @@ -309,6 +309,7 @@ def _delete_pricing_v1_pricing_model_key_delete_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -573,6 +574,7 @@ def _get_pricing_history_v1_pricing_model_key_history_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -863,6 +865,7 @@ def _get_pricing_v1_pricing_model_key_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1146,6 +1149,7 @@ def _list_pricing_v1_pricing_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1186,7 +1190,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 +1258,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 +1326,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 @@ -1423,6 +1427,7 @@ def _set_pricing_v1_pricing_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/providers_api.py b/src/otari/_client/api/providers_api.py new file mode 100644 index 0000000..fa96abf --- /dev/null +++ b/src/otari/_client/api/providers_api.py @@ -0,0 +1,2431 @@ +""" + 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 StrictBool, StrictStr +from typing import List, Optional +from otari._client.models.create_stored_provider_request import CreateStoredProviderRequest +from otari._client.models.known_provider_schema import KnownProviderSchema +from otari._client.models.provider_health_response import ProviderHealthResponse +from otari._client.models.providers_response import ProvidersResponse +from otari._client.models.stored_provider_response import StoredProviderResponse +from otari._client.models.test_provider_request import TestProviderRequest +from otari._client.models.test_provider_response import TestProviderResponse +from otari._client.models.update_stored_provider_request import UpdateStoredProviderRequest + +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 create_stored_provider_v1_provider_credentials_post( + self, + create_stored_provider_request: CreateStoredProviderRequest, + _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, + ) -> StoredProviderResponse: + """Create Stored Provider + + Add a provider at runtime. Storing a key requires OTARI_SECRET_KEY. + + :param create_stored_provider_request: (required) + :type create_stored_provider_request: CreateStoredProviderRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_stored_provider_v1_provider_credentials_post_serialize( + create_stored_provider_request=create_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_stored_provider_v1_provider_credentials_post_with_http_info( + self, + create_stored_provider_request: CreateStoredProviderRequest, + _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[StoredProviderResponse]: + """Create Stored Provider + + Add a provider at runtime. Storing a key requires OTARI_SECRET_KEY. + + :param create_stored_provider_request: (required) + :type create_stored_provider_request: CreateStoredProviderRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_stored_provider_v1_provider_credentials_post_serialize( + create_stored_provider_request=create_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_stored_provider_v1_provider_credentials_post_without_preload_content( + self, + create_stored_provider_request: CreateStoredProviderRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Stored Provider + + Add a provider at runtime. Storing a key requires OTARI_SECRET_KEY. + + :param create_stored_provider_request: (required) + :type create_stored_provider_request: CreateStoredProviderRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_stored_provider_v1_provider_credentials_post_serialize( + create_stored_provider_request=create_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_stored_provider_v1_provider_credentials_post_serialize( + self, + create_stored_provider_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_stored_provider_request is not None: + _body_params = create_stored_provider_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/provider-credentials', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_stored_provider_v1_provider_credentials_instance_delete( + self, + instance: 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 Stored Provider + + Delete a stored provider. A config.yml provider cannot be deleted here. + + :param instance: (required) + :type instance: 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_stored_provider_v1_provider_credentials_instance_delete_serialize( + instance=instance, + _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_stored_provider_v1_provider_credentials_instance_delete_with_http_info( + self, + instance: 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 Stored Provider + + Delete a stored provider. A config.yml provider cannot be deleted here. + + :param instance: (required) + :type instance: 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_stored_provider_v1_provider_credentials_instance_delete_serialize( + instance=instance, + _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_stored_provider_v1_provider_credentials_instance_delete_without_preload_content( + self, + instance: 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 Stored Provider + + Delete a stored provider. A config.yml provider cannot be deleted here. + + :param instance: (required) + :type instance: 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_stored_provider_v1_provider_credentials_instance_delete_serialize( + instance=instance, + _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_stored_provider_v1_provider_credentials_instance_delete_serialize( + self, + instance, + _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 instance is not None: + _path_params['instance'] = instance + # 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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/provider-credentials/{instance}', + 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_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] = [ + 'XApiKeyAuth', + '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 + ) + + + + + @validate_call + def list_stored_providers_v1_provider_credentials_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[StoredProviderResponse]: + """List Stored Providers + + List runtime-stored providers. Keys are never returned, only ``last4``. + + :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_stored_providers_v1_provider_credentials_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[StoredProviderResponse]", + } + 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_stored_providers_v1_provider_credentials_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[StoredProviderResponse]]: + """List Stored Providers + + List runtime-stored providers. Keys are never returned, only ``last4``. + + :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_stored_providers_v1_provider_credentials_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[StoredProviderResponse]", + } + 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_stored_providers_v1_provider_credentials_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 Stored Providers + + List runtime-stored providers. Keys are never returned, only ``last4``. + + :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_stored_providers_v1_provider_credentials_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[StoredProviderResponse]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_stored_providers_v1_provider_credentials_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/provider-credentials', + 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 provider_catalog_v1_providers_catalog_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[KnownProviderSchema]: + """Provider Catalog + + List every known provider for the add-provider picker. Network-free and config-independent: the full any-llm provider set with each one's display name, credential env var, default endpoint, and whether it needs a key. Master-key gated because it is operator-facing dashboard data. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :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._provider_catalog_v1_providers_catalog_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[KnownProviderSchema]", + } + 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 provider_catalog_v1_providers_catalog_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[KnownProviderSchema]]: + """Provider Catalog + + List every known provider for the add-provider picker. Network-free and config-independent: the full any-llm provider set with each one's display name, credential env var, default endpoint, and whether it needs a key. Master-key gated because it is operator-facing dashboard data. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :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._provider_catalog_v1_providers_catalog_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[KnownProviderSchema]", + } + 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 provider_catalog_v1_providers_catalog_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: + """Provider Catalog + + List every known provider for the add-provider picker. Network-free and config-independent: the full any-llm provider set with each one's display name, credential env var, default endpoint, and whether it needs a key. Master-key gated because it is operator-facing dashboard data. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :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._provider_catalog_v1_providers_catalog_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[KnownProviderSchema]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _provider_catalog_v1_providers_catalog_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/providers/catalog', + 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 provider_health_v1_providers_health_get( + self, + refresh: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ProviderHealthResponse: + """Provider Health + + Report every configured provider's reachability, with a last-checked time. Reuses the per-provider model-discovery test path, so a provider is healthy when its credentials can list models. Results are served from the discovery cache (cheap enough to poll), so ``checked_at`` reflects when each provider was actually dialed. Pass ``refresh=true`` to force a live re-dial of every provider. Master-key gated because it describes the gateway's own providers. + + :param refresh: + :type refresh: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._provider_health_v1_providers_health_get_serialize( + refresh=refresh, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProviderHealthResponse", + '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 provider_health_v1_providers_health_get_with_http_info( + self, + refresh: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ProviderHealthResponse]: + """Provider Health + + Report every configured provider's reachability, with a last-checked time. Reuses the per-provider model-discovery test path, so a provider is healthy when its credentials can list models. Results are served from the discovery cache (cheap enough to poll), so ``checked_at`` reflects when each provider was actually dialed. Pass ``refresh=true`` to force a live re-dial of every provider. Master-key gated because it describes the gateway's own providers. + + :param refresh: + :type refresh: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._provider_health_v1_providers_health_get_serialize( + refresh=refresh, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProviderHealthResponse", + '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 provider_health_v1_providers_health_get_without_preload_content( + self, + refresh: Optional[StrictBool] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Provider Health + + Report every configured provider's reachability, with a last-checked time. Reuses the per-provider model-discovery test path, so a provider is healthy when its credentials can list models. Results are served from the discovery cache (cheap enough to poll), so ``checked_at`` reflects when each provider was actually dialed. Pass ``refresh=true`` to force a live re-dial of every provider. Master-key gated because it describes the gateway's own providers. + + :param refresh: + :type refresh: bool + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._provider_health_v1_providers_health_get_serialize( + refresh=refresh, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ProviderHealthResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _provider_health_v1_providers_health_get_serialize( + self, + refresh, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if refresh is not None: + + _query_params.append(('refresh', refresh)) + + # 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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/providers/health', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def test_provider_connection_v1_provider_credentials_test_post( + self, + test_provider_request: TestProviderRequest, + _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, + ) -> TestProviderResponse: + """Test Provider Connection + + Test provider credentials without storing them (for the add/edit form). Resolves the implementation from ``provider_type`` (honoring the ``*-compatible`` aliases) or the ``instance`` name, then lists the provider's models with the supplied credentials. Nothing is persisted and the key is never echoed. + + :param test_provider_request: (required) + :type test_provider_request: TestProviderRequest + :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._test_provider_connection_v1_provider_credentials_test_post_serialize( + test_provider_request=test_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '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 test_provider_connection_v1_provider_credentials_test_post_with_http_info( + self, + test_provider_request: TestProviderRequest, + _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[TestProviderResponse]: + """Test Provider Connection + + Test provider credentials without storing them (for the add/edit form). Resolves the implementation from ``provider_type`` (honoring the ``*-compatible`` aliases) or the ``instance`` name, then lists the provider's models with the supplied credentials. Nothing is persisted and the key is never echoed. + + :param test_provider_request: (required) + :type test_provider_request: TestProviderRequest + :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._test_provider_connection_v1_provider_credentials_test_post_serialize( + test_provider_request=test_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '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 test_provider_connection_v1_provider_credentials_test_post_without_preload_content( + self, + test_provider_request: TestProviderRequest, + _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: + """Test Provider Connection + + Test provider credentials without storing them (for the add/edit form). Resolves the implementation from ``provider_type`` (honoring the ``*-compatible`` aliases) or the ``instance`` name, then lists the provider's models with the supplied credentials. Nothing is persisted and the key is never echoed. + + :param test_provider_request: (required) + :type test_provider_request: TestProviderRequest + :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._test_provider_connection_v1_provider_credentials_test_post_serialize( + test_provider_request=test_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _test_provider_connection_v1_provider_credentials_test_post_serialize( + self, + test_provider_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 test_provider_request is not None: + _body_params = test_provider_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/provider-credentials/test', + 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 test_stored_provider_v1_provider_credentials_instance_test_post( + self, + instance: 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, + ) -> TestProviderResponse: + """Test Stored Provider + + Verify a stored provider's key by listing its models, without exposing the key. + + :param instance: (required) + :type instance: 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._test_stored_provider_v1_provider_credentials_instance_test_post_serialize( + instance=instance, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '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 test_stored_provider_v1_provider_credentials_instance_test_post_with_http_info( + self, + instance: 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[TestProviderResponse]: + """Test Stored Provider + + Verify a stored provider's key by listing its models, without exposing the key. + + :param instance: (required) + :type instance: 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._test_stored_provider_v1_provider_credentials_instance_test_post_serialize( + instance=instance, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '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 test_stored_provider_v1_provider_credentials_instance_test_post_without_preload_content( + self, + instance: 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: + """Test Stored Provider + + Verify a stored provider's key by listing its models, without exposing the key. + + :param instance: (required) + :type instance: 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._test_stored_provider_v1_provider_credentials_instance_test_post_serialize( + instance=instance, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _test_stored_provider_v1_provider_credentials_instance_test_post_serialize( + self, + instance, + _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 instance is not None: + _path_params['instance'] = instance + # 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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/provider-credentials/{instance}/test', + 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_stored_provider_v1_provider_credentials_instance_patch( + self, + instance: StrictStr, + update_stored_provider_request: UpdateStoredProviderRequest, + _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, + ) -> StoredProviderResponse: + """Update Stored Provider + + Update a stored provider. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it. The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. + + :param instance: (required) + :type instance: str + :param update_stored_provider_request: (required) + :type update_stored_provider_request: UpdateStoredProviderRequest + :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_stored_provider_v1_provider_credentials_instance_patch_serialize( + instance=instance, + update_stored_provider_request=update_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredProviderResponse", + '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_stored_provider_v1_provider_credentials_instance_patch_with_http_info( + self, + instance: StrictStr, + update_stored_provider_request: UpdateStoredProviderRequest, + _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[StoredProviderResponse]: + """Update Stored Provider + + Update a stored provider. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it. The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. + + :param instance: (required) + :type instance: str + :param update_stored_provider_request: (required) + :type update_stored_provider_request: UpdateStoredProviderRequest + :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_stored_provider_v1_provider_credentials_instance_patch_serialize( + instance=instance, + update_stored_provider_request=update_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredProviderResponse", + '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_stored_provider_v1_provider_credentials_instance_patch_without_preload_content( + self, + instance: StrictStr, + update_stored_provider_request: UpdateStoredProviderRequest, + _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 Stored Provider + + Update a stored provider. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it. The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. + + :param instance: (required) + :type instance: str + :param update_stored_provider_request: (required) + :type update_stored_provider_request: UpdateStoredProviderRequest + :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_stored_provider_v1_provider_credentials_instance_patch_serialize( + instance=instance, + update_stored_provider_request=update_stored_provider_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredProviderResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_stored_provider_v1_provider_credentials_instance_patch_serialize( + self, + instance, + update_stored_provider_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if instance is not None: + _path_params['instance'] = instance + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_stored_provider_request is not None: + _body_params = update_stored_provider_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/provider-credentials/{instance}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/rerank_api.py b/src/otari/_client/api/rerank_api.py index 4cbfd45..0113099 100644 --- a/src/otari/_client/api/rerank_api.py +++ b/src/otari/_client/api/rerank_api.py @@ -55,7 +55,7 @@ def create_rerank_v1_rerank_post( ) -> RerankResponse: """Create Rerank - Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param rerank_request: (required) :type rerank_request: RerankRequest @@ -123,7 +123,7 @@ def create_rerank_v1_rerank_post_with_http_info( ) -> ApiResponse[RerankResponse]: """Create Rerank - Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param rerank_request: (required) :type rerank_request: RerankRequest @@ -191,7 +191,7 @@ def create_rerank_v1_rerank_post_without_preload_content( ) -> RESTResponseType: """Create Rerank - Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use virtual user created with API key + Rerank documents by relevance to a query. Authentication modes: - Master key + user field: Use specified user (must exist) - API key + user field: Use specified user (must exist) - API key without user field: Use the shared \"default\" user :param rerank_request: (required) :type rerank_request: RerankRequest @@ -292,6 +292,7 @@ def _create_rerank_v1_rerank_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/responses_api.py b/src/otari/_client/api/responses_api.py index 3193bd8..371fb05 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 @@ -292,6 +292,7 @@ def _create_response_v1_responses_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/api/settings_api.py b/src/otari/_client/api/settings_api.py new file mode 100644 index 0000000..404ad6d --- /dev/null +++ b/src/otari/_client/api/settings_api.py @@ -0,0 +1,561 @@ +""" + 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] = [ + 'XApiKeyAuth', + '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 changes. Each provided field 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 changes. Each provided field 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 changes. Each provided field 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] = [ + 'XApiKeyAuth', + '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/api/tool_settings_api.py b/src/otari/_client/api/tool_settings_api.py new file mode 100644 index 0000000..6ddf25c --- /dev/null +++ b/src/otari/_client/api/tool_settings_api.py @@ -0,0 +1,857 @@ +""" + 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 otari._client.models.test_service_request import TestServiceRequest +from otari._client.models.test_service_response import TestServiceResponse +from otari._client.models.tool_settings_response import ToolSettingsResponse +from otari._client.models.update_tool_settings_request import UpdateToolSettingsRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class ToolSettingsApi: + """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_tool_settings_v1_tool_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, + ) -> ToolSettingsResponse: + """Get Tool Settings + + Return the effective tool/guardrail settings for the 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_tool_settings_v1_tool_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': "ToolSettingsResponse", + } + 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_tool_settings_v1_tool_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[ToolSettingsResponse]: + """Get Tool Settings + + Return the effective tool/guardrail settings for the 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_tool_settings_v1_tool_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': "ToolSettingsResponse", + } + 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_tool_settings_v1_tool_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 Tool Settings + + Return the effective tool/guardrail settings for the 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_tool_settings_v1_tool_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': "ToolSettingsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_tool_settings_v1_tool_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/tool-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 test_service_v1_tool_settings_service_test_post( + self, + service: StrictStr, + test_service_request: TestServiceRequest, + _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, + ) -> TestServiceResponse: + """Test Service + + Structurally validate a URL and probe it for reachability. Tests the URL in the request body (typically unsaved), so an operator can verify before saving. The probe is a plain HTTP GET with a short timeout: any HTTP response means the host is reachable; a connection/timeout/DNS error means it is not. The operator is trusted (master key), so no SSRF deny-list applies; only the structural check (http/https + host) runs first. + + :param service: (required) + :type service: str + :param test_service_request: (required) + :type test_service_request: TestServiceRequest + :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._test_service_v1_tool_settings_service_test_post_serialize( + service=service, + test_service_request=test_service_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestServiceResponse", + '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 test_service_v1_tool_settings_service_test_post_with_http_info( + self, + service: StrictStr, + test_service_request: TestServiceRequest, + _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[TestServiceResponse]: + """Test Service + + Structurally validate a URL and probe it for reachability. Tests the URL in the request body (typically unsaved), so an operator can verify before saving. The probe is a plain HTTP GET with a short timeout: any HTTP response means the host is reachable; a connection/timeout/DNS error means it is not. The operator is trusted (master key), so no SSRF deny-list applies; only the structural check (http/https + host) runs first. + + :param service: (required) + :type service: str + :param test_service_request: (required) + :type test_service_request: TestServiceRequest + :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._test_service_v1_tool_settings_service_test_post_serialize( + service=service, + test_service_request=test_service_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestServiceResponse", + '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 test_service_v1_tool_settings_service_test_post_without_preload_content( + self, + service: StrictStr, + test_service_request: TestServiceRequest, + _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: + """Test Service + + Structurally validate a URL and probe it for reachability. Tests the URL in the request body (typically unsaved), so an operator can verify before saving. The probe is a plain HTTP GET with a short timeout: any HTTP response means the host is reachable; a connection/timeout/DNS error means it is not. The operator is trusted (master key), so no SSRF deny-list applies; only the structural check (http/https + host) runs first. + + :param service: (required) + :type service: str + :param test_service_request: (required) + :type test_service_request: TestServiceRequest + :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._test_service_v1_tool_settings_service_test_post_serialize( + service=service, + test_service_request=test_service_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TestServiceResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _test_service_v1_tool_settings_service_test_post_serialize( + self, + service, + test_service_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if service is not None: + _path_params['service'] = service + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if test_service_request is not None: + _body_params = test_service_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/tool-settings/{service}/test', + 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_tool_settings_v1_tool_settings_patch( + self, + update_tool_settings_request: UpdateToolSettingsRequest, + _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, + ) -> ToolSettingsResponse: + """Update Tool Settings + + Persist and apply tool/guardrail setting changes. Uses ``model_fields_set`` so an explicit ``null`` clears a field while an omitted field is left unchanged. Master-key gated and standalone-only. + + :param update_tool_settings_request: (required) + :type update_tool_settings_request: UpdateToolSettingsRequest + :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_tool_settings_v1_tool_settings_patch_serialize( + update_tool_settings_request=update_tool_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ToolSettingsResponse", + '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_tool_settings_v1_tool_settings_patch_with_http_info( + self, + update_tool_settings_request: UpdateToolSettingsRequest, + _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[ToolSettingsResponse]: + """Update Tool Settings + + Persist and apply tool/guardrail setting changes. Uses ``model_fields_set`` so an explicit ``null`` clears a field while an omitted field is left unchanged. Master-key gated and standalone-only. + + :param update_tool_settings_request: (required) + :type update_tool_settings_request: UpdateToolSettingsRequest + :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_tool_settings_v1_tool_settings_patch_serialize( + update_tool_settings_request=update_tool_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ToolSettingsResponse", + '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_tool_settings_v1_tool_settings_patch_without_preload_content( + self, + update_tool_settings_request: UpdateToolSettingsRequest, + _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 Tool Settings + + Persist and apply tool/guardrail setting changes. Uses ``model_fields_set`` so an explicit ``null`` clears a field while an omitted field is left unchanged. Master-key gated and standalone-only. + + :param update_tool_settings_request: (required) + :type update_tool_settings_request: UpdateToolSettingsRequest + :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_tool_settings_v1_tool_settings_patch_serialize( + update_tool_settings_request=update_tool_settings_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ToolSettingsResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_tool_settings_v1_tool_settings_patch_serialize( + self, + update_tool_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_tool_settings_request is not None: + _body_params = update_tool_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/tool-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/api/usage_api.py b/src/otari/_client/api/usage_api.py index cb2b65a..0d28769 100644 --- a/src/otari/_client/api/usage_api.py +++ b/src/otari/_client/api/usage_api.py @@ -16,10 +16,12 @@ from typing_extensions import Annotated from datetime import datetime -from pydantic import Field, StrictStr -from typing import List, Optional +from pydantic import Field, StrictStr, field_validator +from typing import Any, List, Optional from typing_extensions import Annotated +from otari._client.models.usage_count import UsageCount from otari._client.models.usage_entry import UsageEntry +from otari._client.models.usage_summary import UsageSummary from otari._client.api_client import ApiClient, RequestSerialized from otari._client.api_response import ApiResponse @@ -39,14 +41,965 @@ def __init__(self, api_client=None) -> None: self.api_client = api_client + @validate_call + def count_usage_v1_usage_count_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> UsageCount: + """Count Usage + + Total number of usage logs matching the given filters. Serves the dashboard paginator's \"N of M\" total without changing the bare array contract of ``GET /v1/usage``. Runs only when the client asks (a separate request), so the ``COUNT(*)`` is not paid on every page load. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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._count_usage_v1_usage_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UsageCount", + '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 count_usage_v1_usage_count_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[UsageCount]: + """Count Usage + + Total number of usage logs matching the given filters. Serves the dashboard paginator's \"N of M\" total without changing the bare array contract of ``GET /v1/usage``. Runs only when the client asks (a separate request), so the ``COUNT(*)`` is not paid on every page load. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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._count_usage_v1_usage_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UsageCount", + '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 count_usage_v1_usage_count_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Count Usage + + Total number of usage logs matching the given filters. Serves the dashboard paginator's \"N of M\" total without changing the bare array contract of ``GET /v1/usage``. Runs only when the client asks (a separate request), so the ``COUNT(*)`` is not paid on every page load. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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._count_usage_v1_usage_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UsageCount", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _count_usage_v1_usage_count_get_serialize( + self, + start_date, + end_date, + user_id, + status, + model, + endpoint, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if status is not None: + + _query_params.append(('status', status)) + + if model is not None: + + _query_params.append(('model', model)) + + if endpoint is not None: + + _query_params.append(('endpoint', endpoint)) + + # 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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/usage/count', + 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_usage_v1_usage_get( self, start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[UsageEntry]: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range, user, status, model, and endpoint. Paginated via skip/limit. The return shape is a bare JSON array; external billing/analytics consumers depend on this, so the total row count for a paginated UI is served separately by ``GET /v1/usage/count`` rather than wrapped in an envelope here. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_usage_v1_usage_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[UsageEntry]]: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range, user, status, model, and endpoint. Paginated via skip/limit. The return shape is a bare JSON array; external billing/analytics consumers depend on this, so the total row count for a paginated UI is served separately by ``GET /v1/usage/count`` rather than wrapped in an envelope here. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_usage_v1_usage_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Usage + + List usage logs ordered by timestamp (most recent first). Supports optional filters for time range, user, status, model, and endpoint. Paginated via skip/limit. The return shape is a bare JSON array; external billing/analytics consumers depend on this, so the total row count for a paginated UI is served separately by ``GET /v1/usage/count`` rather than wrapped in an envelope here. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param skip: + :type skip: int + :param limit: + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_usage_v1_usage_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[UsageEntry]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_usage_v1_usage_get_serialize( + self, + start_date, + end_date, + user_id, + status, + model, + endpoint, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if status is not None: + + _query_params.append(('status', status)) + + if model is not None: + + _query_params.append(('model', model)) + + if endpoint is not None: + + _query_params.append(('endpoint', endpoint)) + + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/usage', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def usage_summary_csv_v1_usage_summary_csv_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Usage Summary Csv + + Download the per-model / per-user / per-key breakdown as CSV. A dedicated route rather than a ``format=csv`` flag on ``/summary`` so that endpoint keeps a single JSON response model and a clean OpenAPI schema. The export is **uncapped** (no top-N fold): finance wants every row. Kept separate from the bare-array ``/v1/usage`` contract, which is untouched. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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._usage_summary_csv_v1_usage_summary_csv_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def usage_summary_csv_v1_usage_summary_csv_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Usage Summary Csv + + Download the per-model / per-user / per-key breakdown as CSV. A dedicated route rather than a ``format=csv`` flag on ``/summary`` so that endpoint keeps a single JSON response model and a clean OpenAPI schema. The export is **uncapped** (no top-N fold): finance wants every row. Kept separate from the bare-array ``/v1/usage`` contract, which is untouched. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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._usage_summary_csv_v1_usage_summary_csv_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def usage_summary_csv_v1_usage_summary_csv_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -59,10 +1012,10 @@ def list_usage_v1_usage_get( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> List[UsageEntry]: - """List Usage + ) -> RESTResponseType: + """Usage Summary Csv - List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + Download the per-model / per-user / per-key breakdown as CSV. A dedicated route rather than a ``format=csv`` flag on ``/summary`` so that endpoint keeps a single JSON response model and a clean OpenAPI schema. The export is **uncapped** (no top-N fold): finance wants every row. Kept separate from the bare-array ``/v1/usage`` contract, which is untouched. :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) :type start_date: datetime @@ -70,10 +1023,12 @@ def list_usage_v1_usage_get( :type end_date: datetime :param user_id: Filter to a single user :type user_id: str - :param skip: - :type skip: int - :param limit: - :type limit: int + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: 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 @@ -96,12 +1051,13 @@ def list_usage_v1_usage_get( :return: Returns the result object. """ # noqa: E501 - _param = self._list_usage_v1_usage_get_serialize( + _param = self._usage_summary_csv_v1_usage_summary_csv_get_serialize( start_date=start_date, end_date=end_date, user_id=user_id, - skip=skip, - limit=limit, + status=status, + model=model, + endpoint=endpoint, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -109,7 +1065,205 @@ def list_usage_v1_usage_get( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[UsageEntry]", + '200': "object", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _usage_summary_csv_v1_usage_summary_csv_get_serialize( + self, + start_date, + end_date, + user_id, + status, + model, + endpoint, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if status is not None: + + _query_params.append(('status', status)) + + if model is not None: + + _query_params.append(('model', model)) + + if endpoint is not None: + + _query_params.append(('endpoint', endpoint)) + + # 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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/usage/summary.csv', + 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 usage_summary_v1_usage_summary_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> UsageSummary: + """Usage Summary + + Aggregate spend, tokens, and request volume for the dashboard Usage page. Range-bounded (default last 30 days, hard-capped): unlike the raw ``/v1/usage`` list, every aggregate is scoped to a bounded window so it stays served by the timestamp index. Returns grand totals, breakdowns by model / user / API key (top rows plus a reconciling ``other`` fold), and a UTC-bucketed time series. + + :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to a single user + :type user_id: str + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._usage_summary_v1_usage_summary_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + status=status, + model=model, + endpoint=endpoint, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "UsageSummary", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -124,13 +1278,15 @@ def list_usage_v1_usage_get( @validate_call - def list_usage_v1_usage_get_with_http_info( + def usage_summary_v1_usage_summary_get_with_http_info( self, start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -143,10 +1299,10 @@ def list_usage_v1_usage_get_with_http_info( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[List[UsageEntry]]: - """List Usage + ) -> ApiResponse[UsageSummary]: + """Usage Summary - List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + Aggregate spend, tokens, and request volume for the dashboard Usage page. Range-bounded (default last 30 days, hard-capped): unlike the raw ``/v1/usage`` list, every aggregate is scoped to a bounded window so it stays served by the timestamp index. Returns grand totals, breakdowns by model / user / API key (top rows plus a reconciling ``other`` fold), and a UTC-bucketed time series. :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) :type start_date: datetime @@ -154,10 +1310,14 @@ def list_usage_v1_usage_get_with_http_info( :type end_date: datetime :param user_id: Filter to a single user :type user_id: str - :param skip: - :type skip: int - :param limit: - :type limit: int + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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 @@ -180,12 +1340,14 @@ def list_usage_v1_usage_get_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._list_usage_v1_usage_get_serialize( + _param = self._usage_summary_v1_usage_summary_get_serialize( start_date=start_date, end_date=end_date, user_id=user_id, - skip=skip, - limit=limit, + status=status, + model=model, + endpoint=endpoint, + bucket=bucket, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -193,7 +1355,7 @@ def list_usage_v1_usage_get_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[UsageEntry]", + '200': "UsageSummary", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -208,13 +1370,15 @@ def list_usage_v1_usage_get_with_http_info( @validate_call - def list_usage_v1_usage_get_without_preload_content( + def usage_summary_v1_usage_summary_get_without_preload_content( self, start_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, end_date: Annotated[Optional[datetime], Field(description="Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, user_id: Annotated[Optional[StrictStr], Field(description="Filter to a single user")] = None, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + status: Annotated[Optional[StrictStr], Field(description="Filter to a single status (e.g. 'success' or 'error')")] = None, + model: Annotated[Optional[StrictStr], Field(description="Filter to a single model")] = None, + endpoint: Annotated[Optional[StrictStr], Field(description="Filter to a single endpoint (e.g. '/v1/chat/completions')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -228,9 +1392,9 @@ def list_usage_v1_usage_get_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """List Usage + """Usage Summary - List usage logs ordered by timestamp (most recent first). Supports optional filters for time range and user. Paginated via skip/limit. Timestamps accept either ISO 8601 strings or Unix epoch seconds (numeric). + Aggregate spend, tokens, and request volume for the dashboard Usage page. Range-bounded (default last 30 days, hard-capped): unlike the raw ``/v1/usage`` list, every aggregate is scoped to a bounded window so it stays served by the timestamp index. Returns grand totals, breakdowns by model / user / API key (top rows plus a reconciling ``other`` fold), and a UTC-bucketed time series. :param start_date: Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds) :type start_date: datetime @@ -238,10 +1402,14 @@ def list_usage_v1_usage_get_without_preload_content( :type end_date: datetime :param user_id: Filter to a single user :type user_id: str - :param skip: - :type skip: int - :param limit: - :type limit: int + :param status: Filter to a single status (e.g. 'success' or 'error') + :type status: str + :param model: Filter to a single model + :type model: str + :param endpoint: Filter to a single endpoint (e.g. '/v1/chat/completions') + :type endpoint: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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 @@ -264,12 +1432,14 @@ def list_usage_v1_usage_get_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._list_usage_v1_usage_get_serialize( + _param = self._usage_summary_v1_usage_summary_get_serialize( start_date=start_date, end_date=end_date, user_id=user_id, - skip=skip, - limit=limit, + status=status, + model=model, + endpoint=endpoint, + bucket=bucket, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -277,7 +1447,7 @@ def list_usage_v1_usage_get_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[UsageEntry]", + '200': "UsageSummary", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -287,13 +1457,15 @@ def list_usage_v1_usage_get_without_preload_content( return response_data.response - def _list_usage_v1_usage_get_serialize( + def _usage_summary_v1_usage_summary_get_serialize( self, start_date, end_date, user_id, - skip, - limit, + status, + model, + endpoint, + bucket, _request_auth, _content_type, _headers, @@ -346,13 +1518,21 @@ def _list_usage_v1_usage_get_serialize( _query_params.append(('user_id', user_id)) - if skip is not None: + if status is not None: - _query_params.append(('skip', skip)) + _query_params.append(('status', status)) - if limit is not None: + if model is not None: - _query_params.append(('limit', limit)) + _query_params.append(('model', model)) + + if endpoint is not None: + + _query_params.append(('endpoint', endpoint)) + + if bucket is not None: + + _query_params.append(('bucket', bucket)) # process the header parameters # process the form parameters @@ -370,12 +1550,13 @@ def _list_usage_v1_usage_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] return self.api_client.param_serialize( method='GET', - resource_path='/v1/usage', + resource_path='/v1/usage/summary', path_params=_path_params, query_params=_query_params, header_params=_header_params, diff --git a/src/otari/_client/api/users_api.py b/src/otari/_client/api/users_api.py index 1842a20..11ae43f 100644 --- a/src/otari/_client/api/users_api.py +++ b/src/otari/_client/api/users_api.py @@ -297,6 +297,7 @@ def _create_user_v1_users_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -561,6 +562,7 @@ def _delete_user_v1_users_user_id_delete_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -859,6 +861,7 @@ def _get_user_usage_v1_users_user_id_usage_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1123,6 +1126,7 @@ def _get_user_v1_users_user_id_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1406,6 +1410,7 @@ def _list_users_v1_users_get_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] @@ -1698,6 +1703,7 @@ def _update_user_v1_users_user_id_patch_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', 'ApiKeyAuth' ] diff --git a/src/otari/_client/configuration.py b/src/otari/_client/configuration.py index 63ef7be..38211c2 100644 --- a/src/otari/_client/configuration.py +++ b/src/otari/_client/configuration.py @@ -112,6 +112,7 @@ "AuthSettings", { "ApiKeyAuth": APIKeyAuthSetting, + "XApiKeyAuth": APIKeyAuthSetting, }, total=False, ) @@ -543,6 +544,15 @@ def auth_settings(self)-> AuthSettings: 'ApiKeyAuth', ), } + if 'XApiKeyAuth' in self.api_key: + auth['XApiKeyAuth'] = { + 'type': 'api_key', + 'in': 'header', + 'key': 'x-api-key', + 'value': self.get_api_key_with_prefix( + 'XApiKeyAuth', + ), + } return auth def to_debug_report(self) -> str: diff --git a/src/otari/_client/models/__init__.py b/src/otari/_client/models/__init__.py index e0a75c0..166a698 100644 --- a/src/otari/_client/models/__init__.py +++ b/src/otari/_client/models/__init__.py @@ -13,8 +13,11 @@ """ # 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_reset_log_response import BudgetResetLogResponse from otari._client.models.budget_response import BudgetResponse from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio from otari._client.models.cc_chat_completion_message import CCChatCompletionMessage @@ -48,6 +51,7 @@ from otari._client.models.chat_completion_request import ChatCompletionRequest from otari._client.models.chat_completion_request_tools_inner import ChatCompletionRequestToolsInner from otari._client.models.chat_message_input import ChatMessageInput +from otari._client.models.config_field import ConfigField from otari._client.models.content import Content from otari._client.models.content1 import Content1 from otari._client.models.content2 import Content2 @@ -68,10 +72,15 @@ from otari._client.models.create_embedding_response import CreateEmbeddingResponse from otari._client.models.create_key_request import CreateKeyRequest from otari._client.models.create_key_response import CreateKeyResponse +from otari._client.models.create_stored_provider_request import CreateStoredProviderRequest 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 @@ -83,6 +92,7 @@ from otari._client.models.input import Input from otari._client.models.input1 import Input1 from otari._client.models.key_info import KeyInfo +from otari._client.models.known_provider_schema import KnownProviderSchema from otari._client.models.location_inner import LocationInner from otari._client.models.mr_base64_pdf_source import MRBase64PDFSource from otari._client.models.mr_bash_code_execution_output_block import MRBashCodeExecutionOutputBlock @@ -157,12 +167,19 @@ 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_health_response import ProviderHealthResponse +from otari._client.models.provider_health_schema import ProviderHealthSchema +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 @@ -172,15 +189,32 @@ from otari._client.models.set_pricing_request import SetPricingRequest from otari._client.models.source import Source from otari._client.models.stop import Stop +from otari._client.models.stored_provider_response import StoredProviderResponse from otari._client.models.system import System +from otari._client.models.test_provider_request import TestProviderRequest +from otari._client.models.test_provider_response import TestProviderResponse +from otari._client.models.test_service_request import TestServiceRequest +from otari._client.models.test_service_response import TestServiceResponse from otari._client.models.tool_calls_inner import ToolCallsInner from otari._client.models.tool_choice import ToolChoice from otari._client.models.tool_choice1 import ToolChoice1 +from otari._client.models.tool_setting_field import ToolSettingField +from otari._client.models.tool_settings_response import ToolSettingsResponse 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_stored_provider_request import UpdateStoredProviderRequest +from otari._client.models.update_tool_settings_request import UpdateToolSettingsRequest from otari._client.models.update_user_request import UpdateUserRequest +from otari._client.models.usage_count import UsageCount from otari._client.models.usage_entry import UsageEntry +from otari._client.models.usage_group_row import UsageGroupRow from otari._client.models.usage_log_response import UsageLogResponse +from otari._client.models.usage_series_point import UsageSeriesPoint +from otari._client.models.usage_summary import UsageSummary +from otari._client.models.usage_totals import UsageTotals from otari._client.models.user_response import UserResponse from otari._client.models.validation_error import ValidationError +from otari._client.models.value import Value +from otari._client.models.value1 import Value1 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/budget_reset_log_response.py b/src/otari/_client/models/budget_reset_log_response.py new file mode 100644 index 0000000..7f86e81 --- /dev/null +++ b/src/otari/_client/models/budget_reset_log_response.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, 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 BudgetResetLogResponse(BaseModel): + """ + Response model for one budget reset event (per user). + """ # noqa: E501 + budget_id: StrictStr + id: StrictInt + next_reset_at: Optional[StrictStr] + previous_spend: Union[StrictFloat, StrictInt] + reset_at: StrictStr + user_id: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["budget_id", "id", "next_reset_at", "previous_spend", "reset_at", "user_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BudgetResetLogResponse 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 next_reset_at (nullable) is None + # and model_fields_set contains the field + if self.next_reset_at is None and "next_reset_at" in self.model_fields_set: + _dict['next_reset_at'] = None + + # set to None if user_id (nullable) is None + # and model_fields_set contains the field + if self.user_id is None and "user_id" in self.model_fields_set: + _dict['user_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BudgetResetLogResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "budget_id": obj.get("budget_id"), + "id": obj.get("id"), + "next_reset_at": obj.get("next_reset_at"), + "previous_spend": obj.get("previous_spend"), + "reset_at": obj.get("reset_at"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/budget_response.py b/src/otari/_client/models/budget_response.py index d96a9cf..fd4ed18 100644 --- a/src/otari/_client/models/budget_response.py +++ b/src/otari/_client/models/budget_response.py @@ -25,14 +25,18 @@ class BudgetResponse(BaseModel): """ - Response model for budget information. + Response model for budget information. ``max_budget`` is the per-user spending limit, and multiple users can share one budget, so the usage rollup is an aggregate over the users assigned to this budget: how many there are and their combined ``spend`` / ``reserved``. Assigning users to a budget is done through the users API (dashboard support lands with user management), so a fresh gateway reports zeros here. """ # noqa: E501 budget_duration_sec: Optional[StrictInt] budget_id: StrictStr created_at: StrictStr max_budget: Optional[Union[StrictFloat, StrictInt]] + name: Optional[StrictStr] + total_reserved: Optional[Union[StrictFloat, StrictInt]] = 0.0 + total_spend: Optional[Union[StrictFloat, StrictInt]] = 0.0 updated_at: StrictStr - __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "updated_at"] + user_count: Optional[StrictInt] = 0 + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "name", "total_reserved", "total_spend", "updated_at", "user_count"] model_config = ConfigDict( validate_by_name=True, @@ -83,6 +87,11 @@ def to_dict(self) -> Dict[str, Any]: if self.max_budget is None and "max_budget" in self.model_fields_set: _dict['max_budget'] = None + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + return _dict @classmethod @@ -99,7 +108,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "budget_id": obj.get("budget_id"), "created_at": obj.get("created_at"), "max_budget": obj.get("max_budget"), - "updated_at": obj.get("updated_at") + "name": obj.get("name"), + "total_reserved": obj.get("total_reserved") if obj.get("total_reserved") is not None else 0.0, + "total_spend": obj.get("total_spend") if obj.get("total_spend") is not None else 0.0, + "updated_at": obj.get("updated_at"), + "user_count": obj.get("user_count") if obj.get("user_count") is not None else 0 }) 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/config_field.py b/src/otari/_client/models/config_field.py new file mode 100644 index 0000000..fd09c13 --- /dev/null +++ b/src/otari/_client/models/config_field.py @@ -0,0 +1,140 @@ +# 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, field_validator +from typing import Any, ClassVar, Dict, List, Optional, Union +from otari._client.models.value import Value +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ConfigField(BaseModel): + """ + One effective config value surfaced to the dashboard's config viewer. + """ # noqa: E501 + description: Optional[StrictStr] = None + exclusive_minimum: Optional[Union[StrictFloat, StrictInt]] = None + group: StrictStr + key: StrictStr + minimum: Optional[Union[StrictFloat, StrictInt]] = None + options: Optional[List[StrictStr]] = None + settable: StrictBool + type: StrictStr + value: Optional[Value] + __properties: ClassVar[List[str]] = ["description", "exclusive_minimum", "group", "key", "minimum", "options", "settable", "type", "value"] + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['bool', 'int', 'float', 'str', 'list']): + raise ValueError("must be one of enum values ('bool', 'int', 'float', 'str', 'list')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ConfigField 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 value + if self.value: + _dict['value'] = self.value.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 exclusive_minimum (nullable) is None + # and model_fields_set contains the field + if self.exclusive_minimum is None and "exclusive_minimum" in self.model_fields_set: + _dict['exclusive_minimum'] = None + + # set to None if minimum (nullable) is None + # and model_fields_set contains the field + if self.minimum is None and "minimum" in self.model_fields_set: + _dict['minimum'] = None + + # set to None if options (nullable) is None + # and model_fields_set contains the field + if self.options is None and "options" in self.model_fields_set: + _dict['options'] = None + + # set to None if value (nullable) is None + # and model_fields_set contains the field + if self.value is None and "value" in self.model_fields_set: + _dict['value'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ConfigField from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "description": obj.get("description"), + "exclusive_minimum": obj.get("exclusive_minimum"), + "group": obj.get("group"), + "key": obj.get("key"), + "minimum": obj.get("minimum"), + "options": obj.get("options"), + "settable": obj.get("settable"), + "type": obj.get("type"), + "value": Value.from_dict(obj["value"]) if obj.get("value") is not None else None + }) + return _obj + + 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/create_budget_request.py b/src/otari/_client/models/create_budget_request.py index 25512a2..87acd46 100644 --- a/src/otari/_client/models/create_budget_request.py +++ b/src/otari/_client/models/create_budget_request.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from typing import Optional, Set @@ -30,7 +30,8 @@ class CreateBudgetRequest(BaseModel): """ # noqa: E501 budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)") max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = Field(default=None, description="Maximum spending limit") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget"] + name: Optional[StrictStr] = Field(default=None, description="Admin-facing label for the budget") + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name"] model_config = ConfigDict( validate_by_name=True, @@ -81,6 +82,11 @@ def to_dict(self) -> Dict[str, Any]: if self.max_budget is None and "max_budget" in self.model_fields_set: _dict['max_budget'] = None + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + return _dict @classmethod @@ -94,7 +100,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget") + "max_budget": obj.get("max_budget"), + "name": obj.get("name") }) return _obj diff --git a/src/otari/_client/models/create_key_request.py b/src/otari/_client/models/create_key_request.py index c43a498..9548568 100644 --- a/src/otari/_client/models/create_key_request.py +++ b/src/otari/_client/models/create_key_request.py @@ -28,11 +28,12 @@ class CreateKeyRequest(BaseModel): """ Request model for creating a new API key. """ # noqa: E501 + allowed_models: Optional[List[StrictStr]] = Field(default=None, description="Model allow-list: null = any model, [] = deny all, or canonical instance:model entries (with instance:* / instance:prefix* wildcards).") expires_at: Optional[datetime] = Field(default=None, description="Optional expiration timestamp") key_name: Optional[StrictStr] = Field(default=None, description="Optional name for the key") metadata: Optional[Dict[str, Any]] = Field(default=None, description="Optional metadata") user_id: Optional[StrictStr] = Field(default=None, description="Optional user ID to associate with this key") - __properties: ClassVar[List[str]] = ["expires_at", "key_name", "metadata", "user_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "expires_at", "key_name", "metadata", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -73,6 +74,11 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if expires_at (nullable) is None # and model_fields_set contains the field if self.expires_at is None and "expires_at" in self.model_fields_set: @@ -100,6 +106,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "allowed_models": obj.get("allowed_models"), "expires_at": obj.get("expires_at"), "key_name": obj.get("key_name"), "metadata": obj.get("metadata"), diff --git a/src/otari/_client/models/create_key_response.py b/src/otari/_client/models/create_key_response.py index f94f286..ccd104f 100644 --- a/src/otari/_client/models/create_key_response.py +++ b/src/otari/_client/models/create_key_response.py @@ -27,15 +27,17 @@ class CreateKeyResponse(BaseModel): """ Response model for creating a new API key. """ # noqa: E501 + allowed_models: Optional[List[StrictStr]] created_at: StrictStr expires_at: Optional[StrictStr] id: StrictStr is_active: StrictBool key: StrictStr key_name: Optional[StrictStr] + key_prefix: Optional[StrictStr] metadata: Dict[str, Any] user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["created_at", "expires_at", "id", "is_active", "key", "key_name", "metadata", "user_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "created_at", "expires_at", "id", "is_active", "key", "key_name", "key_prefix", "metadata", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -76,6 +78,11 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if expires_at (nullable) is None # and model_fields_set contains the field if self.expires_at is None and "expires_at" in self.model_fields_set: @@ -86,6 +93,11 @@ def to_dict(self) -> Dict[str, Any]: if self.key_name is None and "key_name" in self.model_fields_set: _dict['key_name'] = None + # set to None if key_prefix (nullable) is None + # and model_fields_set contains the field + if self.key_prefix is None and "key_prefix" in self.model_fields_set: + _dict['key_prefix'] = None + # set to None if user_id (nullable) is None # and model_fields_set contains the field if self.user_id is None and "user_id" in self.model_fields_set: @@ -103,12 +115,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "allowed_models": obj.get("allowed_models"), "created_at": obj.get("created_at"), "expires_at": obj.get("expires_at"), "id": obj.get("id"), "is_active": obj.get("is_active"), "key": obj.get("key"), "key_name": obj.get("key_name"), + "key_prefix": obj.get("key_prefix"), "metadata": obj.get("metadata"), "user_id": obj.get("user_id") }) diff --git a/src/otari/_client/models/create_stored_provider_request.py b/src/otari/_client/models/create_stored_provider_request.py new file mode 100644 index 0000000..9e61604 --- /dev/null +++ b/src/otari/_client/models/create_stored_provider_request.py @@ -0,0 +1,117 @@ +# 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 typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateStoredProviderRequest(BaseModel): + """ + Create a stored provider. ``api_key`` is write-only and requires OTARI_SECRET_KEY. + """ # noqa: E501 + api_base: Optional[StrictStr] = None + api_key: Optional[StrictStr] = Field(default=None, description="Provider API key. Stored encrypted; never returned.") + client_args: Optional[Dict[str, Any]] = None + instance: Annotated[str, Field(min_length=1, strict=True)] = Field(description="Routing key, e.g. 'openai' or a named instance like 'home_lab'.") + provider_type: Optional[StrictStr] = Field(default=None, description="any-llm implementation when the instance name is not itself one.") + __properties: ClassVar[List[str]] = ["api_base", "api_key", "client_args", "instance", "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 CreateStoredProviderRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # set to None if api_key (nullable) is None + # and model_fields_set contains the field + if self.api_key is None and "api_key" in self.model_fields_set: + _dict['api_key'] = None + + # set to None if client_args (nullable) is None + # and model_fields_set contains the field + if self.client_args is None and "client_args" in self.model_fields_set: + _dict['client_args'] = None + + # set to None if provider_type (nullable) is None + # and model_fields_set contains the field + if self.provider_type is None and "provider_type" in self.model_fields_set: + _dict['provider_type'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateStoredProviderRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "api_key": obj.get("api_key"), + "client_args": obj.get("client_args"), + "instance": obj.get("instance"), + "provider_type": obj.get("provider_type") + }) + return _obj + + diff --git a/src/otari/_client/models/create_user_request.py b/src/otari/_client/models/create_user_request.py index 168bd9a..9dfefec 100644 --- a/src/otari/_client/models/create_user_request.py +++ b/src/otari/_client/models/create_user_request.py @@ -28,11 +28,12 @@ class CreateUserRequest(BaseModel): Request model for creating a new user. """ # noqa: E501 alias: Optional[StrictStr] = Field(default=None, description="Optional admin-facing alias") + allowed_models: Optional[List[StrictStr]] = Field(default=None, description="Default model access-list this user's keys inherit; null = unrestricted, [] = deny all") blocked: Optional[StrictBool] = Field(default=False, description="Whether user is blocked") budget_id: Optional[StrictStr] = Field(default=None, description="Optional budget ID") metadata: Optional[Dict[str, Any]] = Field(default=None, description="Optional metadata") user_id: StrictStr = Field(description="Unique user identifier") - __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "metadata", "user_id"] + __properties: ClassVar[List[str]] = ["alias", "allowed_models", "blocked", "budget_id", "metadata", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -78,6 +79,11 @@ def to_dict(self) -> Dict[str, Any]: if self.alias is None and "alias" in self.model_fields_set: _dict['alias'] = None + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if budget_id (nullable) is None # and model_fields_set contains the field if self.budget_id is None and "budget_id" in self.model_fields_set: @@ -96,6 +102,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "alias": obj.get("alias"), + "allowed_models": obj.get("allowed_models"), "blocked": obj.get("blocked") if obj.get("blocked") is not None else False, "budget_id": obj.get("budget_id"), "metadata": obj.get("metadata"), 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..da2d9f1 --- /dev/null +++ b/src/otari/_client/models/gateway_settings.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, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List +from otari._client.models.config_field import ConfigField +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. The top-level flags are kept for the callers that read them directly (pricing warnings, the models/providers pages); ``config`` is the full read-only view with the settable/startup-only marking. + """ # noqa: E501 + config: List[ConfigField] + default_pricing: StrictBool + mode: StrictStr + model_discovery: StrictBool + require_pricing: StrictBool + version: StrictStr + __properties: ClassVar[List[str]] = ["config", "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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in config (list) + _items = [] + if self.config: + for _item_config in self.config: + if _item_config: + _items.append(_item_config.to_dict()) + _dict['config'] = _items + 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({ + "config": [ConfigField.from_dict(_item) for _item in obj["config"]] if obj.get("config") is not None else None, + "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/key_info.py b/src/otari/_client/models/key_info.py index b3f52f3..03478a6 100644 --- a/src/otari/_client/models/key_info.py +++ b/src/otari/_client/models/key_info.py @@ -27,15 +27,17 @@ class KeyInfo(BaseModel): """ Response model for key information. """ # noqa: E501 + allowed_models: Optional[List[StrictStr]] created_at: StrictStr expires_at: Optional[StrictStr] id: StrictStr is_active: StrictBool key_name: Optional[StrictStr] + key_prefix: Optional[StrictStr] last_used_at: Optional[StrictStr] metadata: Dict[str, Any] user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["created_at", "expires_at", "id", "is_active", "key_name", "last_used_at", "metadata", "user_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "created_at", "expires_at", "id", "is_active", "key_name", "key_prefix", "last_used_at", "metadata", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -76,6 +78,11 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if expires_at (nullable) is None # and model_fields_set contains the field if self.expires_at is None and "expires_at" in self.model_fields_set: @@ -86,6 +93,11 @@ def to_dict(self) -> Dict[str, Any]: if self.key_name is None and "key_name" in self.model_fields_set: _dict['key_name'] = None + # set to None if key_prefix (nullable) is None + # and model_fields_set contains the field + if self.key_prefix is None and "key_prefix" in self.model_fields_set: + _dict['key_prefix'] = None + # set to None if last_used_at (nullable) is None # and model_fields_set contains the field if self.last_used_at is None and "last_used_at" in self.model_fields_set: @@ -108,11 +120,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "allowed_models": obj.get("allowed_models"), "created_at": obj.get("created_at"), "expires_at": obj.get("expires_at"), "id": obj.get("id"), "is_active": obj.get("is_active"), "key_name": obj.get("key_name"), + "key_prefix": obj.get("key_prefix"), "last_used_at": obj.get("last_used_at"), "metadata": obj.get("metadata"), "user_id": obj.get("user_id") diff --git a/src/otari/_client/models/known_provider_schema.py b/src/otari/_client/models/known_provider_schema.py new file mode 100644 index 0000000..cab29bd --- /dev/null +++ b/src/otari/_client/models/known_provider_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, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class KnownProviderSchema(BaseModel): + """ + A provider the add-provider picker can offer, with autofill hints. + """ # noqa: E501 + default_api_base: Optional[StrictStr] = Field(default=None, description="Built-in endpoint; blank means the SDK's default.") + env_key: Optional[StrictStr] = Field(default=None, description="Env var the SDK reads this provider's key from.") + env_key_present: Optional[StrictBool] = Field(default=False, description="True when env_key is already set on the server, so a pasted key is optional (env fallback).") + id: StrictStr = Field(description="any-llm provider id, used as the default instance name.") + name: StrictStr = Field(description="Human-friendly display name.") + requires_api_key: StrictBool = Field(description="False for keyless local backends (Ollama, llama.cpp).") + __properties: ClassVar[List[str]] = ["default_api_base", "env_key", "env_key_present", "id", "name", "requires_api_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 KnownProviderSchema 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_api_base (nullable) is None + # and model_fields_set contains the field + if self.default_api_base is None and "default_api_base" in self.model_fields_set: + _dict['default_api_base'] = 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 KnownProviderSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "default_api_base": obj.get("default_api_base"), + "env_key": obj.get("env_key"), + "env_key_present": obj.get("env_key_present") if obj.get("env_key_present") is not None else False, + "id": obj.get("id"), + "name": obj.get("name"), + "requires_api_key": obj.get("requires_api_key") + }) + 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_health_response.py b/src/otari/_client/models/provider_health_response.py new file mode 100644 index 0000000..706c4b4 --- /dev/null +++ b/src/otari/_client/models/provider_health_response.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, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.provider_health_schema import ProviderHealthSchema +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ProviderHealthResponse(BaseModel): + """ + Provider connectivity across the whole gateway, for the health monitor. Carries per-provider results plus the ``healthy`` / ``total`` counts and the most recent ``checked_at`` so the overview page can render a summary tile without re-deriving them. + """ # noqa: E501 + checked_at: Optional[StrictStr] = Field(default=None, description="ISO 8601 time of the most recent per-provider check (null if none yet).") + healthy: StrictInt = Field(description="How many providers are currently reachable.") + providers: List[ProviderHealthSchema] + total: StrictInt = Field(description="How many providers are configured.") + __properties: ClassVar[List[str]] = ["checked_at", "healthy", "providers", "total"] + + 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 ProviderHealthResponse 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 + # set to None if checked_at (nullable) is None + # and model_fields_set contains the field + if self.checked_at is None and "checked_at" in self.model_fields_set: + _dict['checked_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ProviderHealthResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "checked_at": obj.get("checked_at"), + "healthy": obj.get("healthy"), + "providers": [ProviderHealthSchema.from_dict(_item) for _item in obj["providers"]] if obj.get("providers") is not None else None, + "total": obj.get("total") + }) + return _obj + + diff --git a/src/otari/_client/models/provider_health_schema.py b/src/otari/_client/models/provider_health_schema.py new file mode 100644 index 0000000..6cc1097 --- /dev/null +++ b/src/otari/_client/models/provider_health_schema.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, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ProviderHealthSchema(BaseModel): + """ + One provider instance's reachability, from the model-discovery test path. + """ # noqa: E501 + checked_at: Optional[StrictStr] = Field(default=None, description="ISO 8601 wall-clock time the provider's reachability was last checked (null if never).") + error: Optional[StrictStr] = Field(default=None, description="Sanitized provider error when unreachable.") + instance: StrictStr + model_count: StrictInt = Field(description="Number of models the last successful listing returned.") + ok: StrictBool = Field(description="True when the provider's credentials could list models.") + __properties: ClassVar[List[str]] = ["checked_at", "error", "instance", "model_count", "ok"] + + 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 ProviderHealthSchema 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 checked_at (nullable) is None + # and model_fields_set contains the field + if self.checked_at is None and "checked_at" in self.model_fields_set: + _dict['checked_at'] = None + + # 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 ProviderHealthSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "checked_at": obj.get("checked_at"), + "error": obj.get("error"), + "instance": obj.get("instance"), + "model_count": obj.get("model_count"), + "ok": obj.get("ok") + }) + 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/stored_provider_response.py b/src/otari/_client/models/stored_provider_response.py new file mode 100644 index 0000000..b9a0429 --- /dev/null +++ b/src/otari/_client/models/stored_provider_response.py @@ -0,0 +1,127 @@ +# 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, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class StoredProviderResponse(BaseModel): + """ + A runtime-stored provider. The API key is never returned, only ``last4``. + """ # noqa: E501 + api_base: Optional[StrictStr] = None + client_args: Optional[Dict[str, Any]] = None + created_at: Optional[StrictStr] = None + decryptable: Optional[StrictBool] = True + instance: StrictStr + last4: Optional[StrictStr] = None + provider_type: Optional[StrictStr] = None + updated_at: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["api_base", "client_args", "created_at", "decryptable", "instance", "last4", "provider_type", "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 StoredProviderResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # 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 last4 (nullable) is None + # and model_fields_set contains the field + if self.last4 is None and "last4" in self.model_fields_set: + _dict['last4'] = None + + # set to None if provider_type (nullable) is None + # and model_fields_set contains the field + if self.provider_type is None and "provider_type" in self.model_fields_set: + _dict['provider_type'] = 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 StoredProviderResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "client_args": obj.get("client_args"), + "created_at": obj.get("created_at"), + "decryptable": obj.get("decryptable") if obj.get("decryptable") is not None else True, + "instance": obj.get("instance"), + "last4": obj.get("last4"), + "provider_type": obj.get("provider_type"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/src/otari/_client/models/test_provider_request.py b/src/otari/_client/models/test_provider_request.py new file mode 100644 index 0000000..d534fc2 --- /dev/null +++ b/src/otari/_client/models/test_provider_request.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 typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class TestProviderRequest(BaseModel): + """ + Credentials to test before saving (from the add-provider form). + """ # noqa: E501 + api_base: Optional[StrictStr] = None + api_key: Optional[StrictStr] = None + client_args: Optional[Dict[str, Any]] = None + instance: Optional[StrictStr] = Field(default=None, description="Provider/instance name; the impl when no provider_type.") + provider_type: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["api_base", "api_key", "client_args", "instance", "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 TestProviderRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # set to None if api_key (nullable) is None + # and model_fields_set contains the field + if self.api_key is None and "api_key" in self.model_fields_set: + _dict['api_key'] = None + + # set to None if client_args (nullable) is None + # and model_fields_set contains the field + if self.client_args is None and "client_args" in self.model_fields_set: + _dict['client_args'] = None + + # set to None if instance (nullable) is None + # and model_fields_set contains the field + if self.instance is None and "instance" in self.model_fields_set: + _dict['instance'] = None + + # set to None if provider_type (nullable) is None + # and model_fields_set contains the field + if self.provider_type is None and "provider_type" in self.model_fields_set: + _dict['provider_type'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TestProviderRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "api_key": obj.get("api_key"), + "client_args": obj.get("client_args"), + "instance": obj.get("instance"), + "provider_type": obj.get("provider_type") + }) + return _obj + + diff --git a/src/otari/_client/models/test_provider_response.py b/src/otari/_client/models/test_provider_response.py new file mode 100644 index 0000000..33455e8 --- /dev/null +++ b/src/otari/_client/models/test_provider_response.py @@ -0,0 +1,97 @@ +# 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, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class TestProviderResponse(BaseModel): + """ + Result of a live provider connection test. + """ # noqa: E501 + error: Optional[StrictStr] = None + model_count: StrictInt + ok: StrictBool + __properties: ClassVar[List[str]] = ["error", "model_count", "ok"] + + 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 TestProviderResponse 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 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 TestProviderResponse 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"), + "model_count": obj.get("model_count"), + "ok": obj.get("ok") + }) + return _obj + + diff --git a/src/otari/_client/models/test_service_request.py b/src/otari/_client/models/test_service_request.py new file mode 100644 index 0000000..0ed30fa --- /dev/null +++ b/src/otari/_client/models/test_service_request.py @@ -0,0 +1,88 @@ +# 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 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class TestServiceRequest(BaseModel): + """ + A (typically unsaved) URL to probe for reachability. + """ # noqa: E501 + url: StrictStr + __properties: ClassVar[List[str]] = ["url"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of TestServiceRequest 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 TestServiceRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "url": obj.get("url") + }) + return _obj + + diff --git a/src/otari/_client/models/test_service_response.py b/src/otari/_client/models/test_service_response.py new file mode 100644 index 0000000..e67f722 --- /dev/null +++ b/src/otari/_client/models/test_service_response.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, 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 TestServiceResponse(BaseModel): + """ + TestServiceResponse + """ # noqa: E501 + ok: StrictBool + reason: StrictStr + __properties: ClassVar[List[str]] = ["ok", "reason"] + + 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 TestServiceResponse 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 TestServiceResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "ok": obj.get("ok"), + "reason": obj.get("reason") + }) + return _obj + + diff --git a/src/otari/_client/models/tool_setting_field.py b/src/otari/_client/models/tool_setting_field.py new file mode 100644 index 0000000..66ee072 --- /dev/null +++ b/src/otari/_client/models/tool_setting_field.py @@ -0,0 +1,124 @@ +# 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, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.value1 import Value1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ToolSettingField(BaseModel): + """ + One editable tool/guardrail field surfaced to the dashboard. + """ # noqa: E501 + description: Optional[StrictStr] = None + key: StrictStr + service: StrictStr + type: StrictStr + value: Optional[Value1] + __properties: ClassVar[List[str]] = ["description", "key", "service", "type", "value"] + + @field_validator('service') + def service_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['web_search', 'sandbox', 'guardrails']): + raise ValueError("must be one of enum values ('web_search', 'sandbox', 'guardrails')") + return value + + @field_validator('type') + def type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['url', 'str', 'int', 'bool']): + raise ValueError("must be one of enum values ('url', 'str', 'int', 'bool')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ToolSettingField 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 value + if self.value: + _dict['value'] = self.value.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 value (nullable) is None + # and model_fields_set contains the field + if self.value is None and "value" in self.model_fields_set: + _dict['value'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ToolSettingField from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "description": obj.get("description"), + "key": obj.get("key"), + "service": obj.get("service"), + "type": obj.get("type"), + "value": Value1.from_dict(obj["value"]) if obj.get("value") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/tool_settings_response.py b/src/otari/_client/models/tool_settings_response.py new file mode 100644 index 0000000..1fe2ff3 --- /dev/null +++ b/src/otari/_client/models/tool_settings_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.tool_setting_field import ToolSettingField +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ToolSettingsResponse(BaseModel): + """ + The effective value of every editable tool/guardrail field. + """ # noqa: E501 + fields: List[ToolSettingField] + __properties: ClassVar[List[str]] = ["fields"] + + 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 ToolSettingsResponse 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 fields (list) + _items = [] + if self.fields: + for _item_fields in self.fields: + if _item_fields: + _items.append(_item_fields.to_dict()) + _dict['fields'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ToolSettingsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "fields": [ToolSettingField.from_dict(_item) for _item in obj["fields"]] if obj.get("fields") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/update_budget_request.py b/src/otari/_client/models/update_budget_request.py index b43962d..2fa9f67 100644 --- a/src/otari/_client/models/update_budget_request.py +++ b/src/otari/_client/models/update_budget_request.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from typing import Optional, Set @@ -30,7 +30,8 @@ class UpdateBudgetRequest(BaseModel): """ # noqa: E501 budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = None max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget"] + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name"] model_config = ConfigDict( validate_by_name=True, @@ -81,6 +82,11 @@ def to_dict(self) -> Dict[str, Any]: if self.max_budget is None and "max_budget" in self.model_fields_set: _dict['max_budget'] = None + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + return _dict @classmethod @@ -94,7 +100,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget") + "max_budget": obj.get("max_budget"), + "name": obj.get("name") }) return _obj diff --git a/src/otari/_client/models/update_key_request.py b/src/otari/_client/models/update_key_request.py index a2bfbff..fde5bce 100644 --- a/src/otari/_client/models/update_key_request.py +++ b/src/otari/_client/models/update_key_request.py @@ -28,11 +28,12 @@ class UpdateKeyRequest(BaseModel): """ Request model for updating a key. """ # noqa: E501 + allowed_models: Optional[List[StrictStr]] = None expires_at: Optional[datetime] = None is_active: Optional[StrictBool] = None key_name: Optional[StrictStr] = None metadata: Optional[Dict[str, Any]] = None - __properties: ClassVar[List[str]] = ["expires_at", "is_active", "key_name", "metadata"] + __properties: ClassVar[List[str]] = ["allowed_models", "expires_at", "is_active", "key_name", "metadata"] model_config = ConfigDict( validate_by_name=True, @@ -73,6 +74,11 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if expires_at (nullable) is None # and model_fields_set contains the field if self.expires_at is None and "expires_at" in self.model_fields_set: @@ -105,6 +111,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "allowed_models": obj.get("allowed_models"), "expires_at": obj.get("expires_at"), "is_active": obj.get("is_active"), "key_name": obj.get("key_name"), 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..17f58e7 --- /dev/null +++ b/src/otari/_client/models/update_settings_request.py @@ -0,0 +1,212 @@ +# 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, field_validator +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateSettingsRequest(BaseModel): + """ + Change one or more runtime settings. Omitted fields are left unchanged. Only the hot-changeable subset is accepted; startup-only fields are not settable over the API (they are display-only in the dashboard). + """ # noqa: E501 + budget_estimate_default_output_tokens: Optional[Annotated[int, Field(strict=True, ge=0)]] = None + default_pricing: Optional[StrictBool] = None + file_understanding_enabled: Optional[StrictBool] = None + model_cache_ttl_seconds: Optional[Annotated[int, Field(strict=True, ge=0)]] = None + model_discovery: Optional[StrictBool] = None + model_discovery_negative_ttl_seconds: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None + model_discovery_timeout_seconds: Optional[Union[Annotated[float, Field(strict=True, gt=0.0)], Annotated[int, Field(strict=True, gt=0)]]] = None + models_dev_cache_ttl_seconds: Optional[Annotated[int, Field(strict=True, ge=0)]] = None + models_dev_metadata: Optional[StrictBool] = None + reject_user_mismatch: Optional[StrictBool] = None + require_pricing: Optional[StrictBool] = None + stream_missing_usage_policy: Optional[StrictStr] = None + vision_describe_max_tokens: Optional[Annotated[int, Field(strict=True, gt=0)]] = None + vision_describe_model: Optional[StrictStr] = None + vision_strategy: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["budget_estimate_default_output_tokens", "default_pricing", "file_understanding_enabled", "model_cache_ttl_seconds", "model_discovery", "model_discovery_negative_ttl_seconds", "model_discovery_timeout_seconds", "models_dev_cache_ttl_seconds", "models_dev_metadata", "reject_user_mismatch", "require_pricing", "stream_missing_usage_policy", "vision_describe_max_tokens", "vision_describe_model", "vision_strategy"] + + @field_validator('stream_missing_usage_policy') + def stream_missing_usage_policy_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['estimate', 'fail', 'allow_free']): + raise ValueError("must be one of enum values ('estimate', 'fail', 'allow_free')") + return value + + @field_validator('vision_strategy') + def vision_strategy_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['describe', 'ocr', 'off']): + raise ValueError("must be one of enum values ('describe', 'ocr', 'off')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of 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 budget_estimate_default_output_tokens (nullable) is None + # and model_fields_set contains the field + if self.budget_estimate_default_output_tokens is None and "budget_estimate_default_output_tokens" in self.model_fields_set: + _dict['budget_estimate_default_output_tokens'] = None + + # 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 file_understanding_enabled (nullable) is None + # and model_fields_set contains the field + if self.file_understanding_enabled is None and "file_understanding_enabled" in self.model_fields_set: + _dict['file_understanding_enabled'] = None + + # set to None if model_cache_ttl_seconds (nullable) is None + # and model_fields_set contains the field + if self.model_cache_ttl_seconds is None and "model_cache_ttl_seconds" in self.model_fields_set: + _dict['model_cache_ttl_seconds'] = 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 + + # set to None if model_discovery_negative_ttl_seconds (nullable) is None + # and model_fields_set contains the field + if self.model_discovery_negative_ttl_seconds is None and "model_discovery_negative_ttl_seconds" in self.model_fields_set: + _dict['model_discovery_negative_ttl_seconds'] = None + + # set to None if model_discovery_timeout_seconds (nullable) is None + # and model_fields_set contains the field + if self.model_discovery_timeout_seconds is None and "model_discovery_timeout_seconds" in self.model_fields_set: + _dict['model_discovery_timeout_seconds'] = None + + # set to None if models_dev_cache_ttl_seconds (nullable) is None + # and model_fields_set contains the field + if self.models_dev_cache_ttl_seconds is None and "models_dev_cache_ttl_seconds" in self.model_fields_set: + _dict['models_dev_cache_ttl_seconds'] = None + + # set to None if models_dev_metadata (nullable) is None + # and model_fields_set contains the field + if self.models_dev_metadata is None and "models_dev_metadata" in self.model_fields_set: + _dict['models_dev_metadata'] = None + + # set to None if reject_user_mismatch (nullable) is None + # and model_fields_set contains the field + if self.reject_user_mismatch is None and "reject_user_mismatch" in self.model_fields_set: + _dict['reject_user_mismatch'] = None + + # set to None if require_pricing (nullable) is None + # and model_fields_set contains the field + if self.require_pricing is None and "require_pricing" in self.model_fields_set: + _dict['require_pricing'] = None + + # set to None if stream_missing_usage_policy (nullable) is None + # and model_fields_set contains the field + if self.stream_missing_usage_policy is None and "stream_missing_usage_policy" in self.model_fields_set: + _dict['stream_missing_usage_policy'] = None + + # set to None if vision_describe_max_tokens (nullable) is None + # and model_fields_set contains the field + if self.vision_describe_max_tokens is None and "vision_describe_max_tokens" in self.model_fields_set: + _dict['vision_describe_max_tokens'] = None + + # set to None if vision_describe_model (nullable) is None + # and model_fields_set contains the field + if self.vision_describe_model is None and "vision_describe_model" in self.model_fields_set: + _dict['vision_describe_model'] = None + + # set to None if vision_strategy (nullable) is None + # and model_fields_set contains the field + if self.vision_strategy is None and "vision_strategy" in self.model_fields_set: + _dict['vision_strategy'] = 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({ + "budget_estimate_default_output_tokens": obj.get("budget_estimate_default_output_tokens"), + "default_pricing": obj.get("default_pricing"), + "file_understanding_enabled": obj.get("file_understanding_enabled"), + "model_cache_ttl_seconds": obj.get("model_cache_ttl_seconds"), + "model_discovery": obj.get("model_discovery"), + "model_discovery_negative_ttl_seconds": obj.get("model_discovery_negative_ttl_seconds"), + "model_discovery_timeout_seconds": obj.get("model_discovery_timeout_seconds"), + "models_dev_cache_ttl_seconds": obj.get("models_dev_cache_ttl_seconds"), + "models_dev_metadata": obj.get("models_dev_metadata"), + "reject_user_mismatch": obj.get("reject_user_mismatch"), + "require_pricing": obj.get("require_pricing"), + "stream_missing_usage_policy": obj.get("stream_missing_usage_policy"), + "vision_describe_max_tokens": obj.get("vision_describe_max_tokens"), + "vision_describe_model": obj.get("vision_describe_model"), + "vision_strategy": obj.get("vision_strategy") + }) + return _obj + + diff --git a/src/otari/_client/models/update_stored_provider_request.py b/src/otari/_client/models/update_stored_provider_request.py new file mode 100644 index 0000000..7a37245 --- /dev/null +++ b/src/otari/_client/models/update_stored_provider_request.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 typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateStoredProviderRequest(BaseModel): + """ + Update a stored provider. Omitted fields are unchanged; ``api_key`` rotates in place. + """ # noqa: E501 + api_base: Optional[StrictStr] = None + api_key: Optional[StrictStr] = Field(default=None, description="New API key. Omit to keep the existing one. Never returned.") + client_args: Optional[Dict[str, Any]] = None + expected_updated_at: Optional[StrictStr] = Field(default=None, description="Optimistic concurrency: if set, the update 412s unless it matches the stored updated_at.") + provider_type: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["api_base", "api_key", "client_args", "expected_updated_at", "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 UpdateStoredProviderRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if api_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # set to None if api_key (nullable) is None + # and model_fields_set contains the field + if self.api_key is None and "api_key" in self.model_fields_set: + _dict['api_key'] = None + + # set to None if client_args (nullable) is None + # and model_fields_set contains the field + if self.client_args is None and "client_args" in self.model_fields_set: + _dict['client_args'] = None + + # set to None if expected_updated_at (nullable) is None + # and model_fields_set contains the field + if self.expected_updated_at is None and "expected_updated_at" in self.model_fields_set: + _dict['expected_updated_at'] = None + + # set to None if provider_type (nullable) is None + # and model_fields_set contains the field + if self.provider_type is None and "provider_type" in self.model_fields_set: + _dict['provider_type'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateStoredProviderRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "api_key": obj.get("api_key"), + "client_args": obj.get("client_args"), + "expected_updated_at": obj.get("expected_updated_at"), + "provider_type": obj.get("provider_type") + }) + return _obj + + diff --git a/src/otari/_client/models/update_tool_settings_request.py b/src/otari/_client/models/update_tool_settings_request.py new file mode 100644 index 0000000..3b56f74 --- /dev/null +++ b/src/otari/_client/models/update_tool_settings_request.py @@ -0,0 +1,143 @@ +# 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 typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateToolSettingsRequest(BaseModel): + """ + Change one or more tool settings. Omitted fields are left unchanged; an explicit ``null`` clears a field back to the configured env/YAML default. + """ # noqa: E501 + guardrails_url: Optional[StrictStr] = None + sandbox_purpose_hint: Optional[StrictStr] = None + sandbox_url: Optional[StrictStr] = None + web_search_engines: Optional[StrictStr] = None + web_search_extract: Optional[StrictBool] = None + web_search_max_results: Optional[Annotated[int, Field(strict=True, ge=1)]] = None + web_search_purpose_hint: Optional[StrictStr] = None + web_search_url: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["guardrails_url", "sandbox_purpose_hint", "sandbox_url", "web_search_engines", "web_search_extract", "web_search_max_results", "web_search_purpose_hint", "web_search_url"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UpdateToolSettingsRequest 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 guardrails_url (nullable) is None + # and model_fields_set contains the field + if self.guardrails_url is None and "guardrails_url" in self.model_fields_set: + _dict['guardrails_url'] = None + + # set to None if sandbox_purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.sandbox_purpose_hint is None and "sandbox_purpose_hint" in self.model_fields_set: + _dict['sandbox_purpose_hint'] = None + + # set to None if sandbox_url (nullable) is None + # and model_fields_set contains the field + if self.sandbox_url is None and "sandbox_url" in self.model_fields_set: + _dict['sandbox_url'] = None + + # set to None if web_search_engines (nullable) is None + # and model_fields_set contains the field + if self.web_search_engines is None and "web_search_engines" in self.model_fields_set: + _dict['web_search_engines'] = None + + # set to None if web_search_extract (nullable) is None + # and model_fields_set contains the field + if self.web_search_extract is None and "web_search_extract" in self.model_fields_set: + _dict['web_search_extract'] = None + + # set to None if web_search_max_results (nullable) is None + # and model_fields_set contains the field + if self.web_search_max_results is None and "web_search_max_results" in self.model_fields_set: + _dict['web_search_max_results'] = None + + # set to None if web_search_purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.web_search_purpose_hint is None and "web_search_purpose_hint" in self.model_fields_set: + _dict['web_search_purpose_hint'] = None + + # set to None if web_search_url (nullable) is None + # and model_fields_set contains the field + if self.web_search_url is None and "web_search_url" in self.model_fields_set: + _dict['web_search_url'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateToolSettingsRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "guardrails_url": obj.get("guardrails_url"), + "sandbox_purpose_hint": obj.get("sandbox_purpose_hint"), + "sandbox_url": obj.get("sandbox_url"), + "web_search_engines": obj.get("web_search_engines"), + "web_search_extract": obj.get("web_search_extract"), + "web_search_max_results": obj.get("web_search_max_results"), + "web_search_purpose_hint": obj.get("web_search_purpose_hint"), + "web_search_url": obj.get("web_search_url") + }) + return _obj + + diff --git a/src/otari/_client/models/update_user_request.py b/src/otari/_client/models/update_user_request.py index 6a90add..7003d12 100644 --- a/src/otari/_client/models/update_user_request.py +++ b/src/otari/_client/models/update_user_request.py @@ -28,10 +28,11 @@ class UpdateUserRequest(BaseModel): Request model for updating a user. """ # noqa: E501 alias: Optional[StrictStr] = None + allowed_models: Optional[List[StrictStr]] = None blocked: Optional[StrictBool] = None budget_id: Optional[StrictStr] = None metadata: Optional[Dict[str, Any]] = None - __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "metadata"] + __properties: ClassVar[List[str]] = ["alias", "allowed_models", "blocked", "budget_id", "metadata"] model_config = ConfigDict( validate_by_name=True, @@ -77,6 +78,11 @@ def to_dict(self) -> Dict[str, Any]: if self.alias is None and "alias" in self.model_fields_set: _dict['alias'] = None + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if blocked (nullable) is None # and model_fields_set contains the field if self.blocked is None and "blocked" in self.model_fields_set: @@ -105,6 +111,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "alias": obj.get("alias"), + "allowed_models": obj.get("allowed_models"), "blocked": obj.get("blocked"), "budget_id": obj.get("budget_id"), "metadata": obj.get("metadata") diff --git a/src/otari/_client/models/usage_count.py b/src/otari/_client/models/usage_count.py new file mode 100644 index 0000000..493e412 --- /dev/null +++ b/src/otari/_client/models/usage_count.py @@ -0,0 +1,88 @@ +# 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, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageCount(BaseModel): + """ + Total number of usage logs matching a set of filters. + """ # noqa: E501 + total: StrictInt + __properties: ClassVar[List[str]] = ["total"] + + 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 UsageCount 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 UsageCount from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "total": obj.get("total") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_entry.py b/src/otari/_client/models/usage_entry.py index 307ae09..3c5418e 100644 --- a/src/otari/_client/models/usage_entry.py +++ b/src/otari/_client/models/usage_entry.py @@ -35,6 +35,7 @@ class UsageEntry(BaseModel): endpoint: StrictStr error_message: Optional[StrictStr] id: StrictStr + latency_ms: Optional[StrictInt] model: StrictStr prompt_tokens: Optional[StrictInt] provider: Optional[StrictStr] @@ -42,7 +43,7 @@ class UsageEntry(BaseModel): timestamp: StrictStr total_tokens: Optional[StrictInt] user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["api_key_id", "cache_read_tokens", "cache_write_tokens", "completion_tokens", "cost", "endpoint", "error_message", "id", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] + __properties: ClassVar[List[str]] = ["api_key_id", "cache_read_tokens", "cache_write_tokens", "completion_tokens", "cost", "endpoint", "error_message", "id", "latency_ms", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -113,6 +114,11 @@ def to_dict(self) -> Dict[str, Any]: if self.error_message is None and "error_message" in self.model_fields_set: _dict['error_message'] = None + # set to None if latency_ms (nullable) is None + # and model_fields_set contains the field + if self.latency_ms is None and "latency_ms" in self.model_fields_set: + _dict['latency_ms'] = None + # set to None if prompt_tokens (nullable) is None # and model_fields_set contains the field if self.prompt_tokens is None and "prompt_tokens" in self.model_fields_set: @@ -153,6 +159,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "endpoint": obj.get("endpoint"), "error_message": obj.get("error_message"), "id": obj.get("id"), + "latency_ms": obj.get("latency_ms"), "model": obj.get("model"), "prompt_tokens": obj.get("prompt_tokens"), "provider": obj.get("provider"), diff --git a/src/otari/_client/models/usage_group_row.py b/src/otari/_client/models/usage_group_row.py new file mode 100644 index 0000000..6b367d2 --- /dev/null +++ b/src/otari/_client/models/usage_group_row.py @@ -0,0 +1,101 @@ +# 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 UsageGroupRow(BaseModel): + """ + One breakdown row (a model, a user, or an API key). ``key`` is None both for the synthesized fold row (``is_other=True``) and for a real group whose column was NULL (e.g. usage from a since-deleted user, with ``is_other=False``). ``is_other`` disambiguates the two so the UI does not mislabel deleted-user usage as the fold. + """ # noqa: E501 + cost: Union[StrictFloat, StrictInt] + is_other: Optional[StrictBool] = False + key: Optional[StrictStr] + requests: StrictInt + tokens: StrictInt + __properties: ClassVar[List[str]] = ["cost", "is_other", "key", "requests", "tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageGroupRow 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 key (nullable) is None + # and model_fields_set contains the field + if self.key is None and "key" in self.model_fields_set: + _dict['key'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UsageGroupRow from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cost": obj.get("cost"), + "is_other": obj.get("is_other") if obj.get("is_other") is not None else False, + "key": obj.get("key"), + "requests": obj.get("requests"), + "tokens": obj.get("tokens") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_log_response.py b/src/otari/_client/models/usage_log_response.py index 518d444..7c010db 100644 --- a/src/otari/_client/models/usage_log_response.py +++ b/src/otari/_client/models/usage_log_response.py @@ -33,6 +33,7 @@ class UsageLogResponse(BaseModel): endpoint: StrictStr error_message: Optional[StrictStr] id: StrictStr + latency_ms: Optional[StrictInt] model: StrictStr prompt_tokens: Optional[StrictInt] provider: Optional[StrictStr] @@ -40,7 +41,7 @@ class UsageLogResponse(BaseModel): timestamp: StrictStr total_tokens: Optional[StrictInt] user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["api_key_id", "completion_tokens", "cost", "endpoint", "error_message", "id", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] + __properties: ClassVar[List[str]] = ["api_key_id", "completion_tokens", "cost", "endpoint", "error_message", "id", "latency_ms", "model", "prompt_tokens", "provider", "status", "timestamp", "total_tokens", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -101,6 +102,11 @@ def to_dict(self) -> Dict[str, Any]: if self.error_message is None and "error_message" in self.model_fields_set: _dict['error_message'] = None + # set to None if latency_ms (nullable) is None + # and model_fields_set contains the field + if self.latency_ms is None and "latency_ms" in self.model_fields_set: + _dict['latency_ms'] = None + # set to None if prompt_tokens (nullable) is None # and model_fields_set contains the field if self.prompt_tokens is None and "prompt_tokens" in self.model_fields_set: @@ -139,6 +145,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "endpoint": obj.get("endpoint"), "error_message": obj.get("error_message"), "id": obj.get("id"), + "latency_ms": obj.get("latency_ms"), "model": obj.get("model"), "prompt_tokens": obj.get("prompt_tokens"), "provider": obj.get("provider"), diff --git a/src/otari/_client/models/usage_series_point.py b/src/otari/_client/models/usage_series_point.py new file mode 100644 index 0000000..081fde4 --- /dev/null +++ b/src/otari/_client/models/usage_series_point.py @@ -0,0 +1,94 @@ +# 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, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageSeriesPoint(BaseModel): + """ + One time bucket. ``bucket_start`` is canonical ISO-8601 UTC (``...Z``), identical across SQLite and PostgreSQL for the same underlying instant. + """ # noqa: E501 + bucket_start: StrictStr + cost: Union[StrictFloat, StrictInt] + requests: StrictInt + tokens: StrictInt + __properties: ClassVar[List[str]] = ["bucket_start", "cost", "requests", "tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageSeriesPoint 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 UsageSeriesPoint from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bucket_start": obj.get("bucket_start"), + "cost": obj.get("cost"), + "requests": obj.get("requests"), + "tokens": obj.get("tokens") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_summary.py b/src/otari/_client/models/usage_summary.py new file mode 100644 index 0000000..c8ef178 --- /dev/null +++ b/src/otari/_client/models/usage_summary.py @@ -0,0 +1,143 @@ +# 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, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.usage_group_row import UsageGroupRow +from otari._client.models.usage_series_point import UsageSeriesPoint +from otari._client.models.usage_totals import UsageTotals +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageSummary(BaseModel): + """ + Aggregate spend/volume for the Usage & analytics page. + """ # noqa: E501 + bucket: StrictStr + by_api_key: List[UsageGroupRow] + by_model: List[UsageGroupRow] + by_user: List[UsageGroupRow] + end_date: StrictStr + series: List[UsageSeriesPoint] + start_date: StrictStr + totals: UsageTotals + __properties: ClassVar[List[str]] = ["bucket", "by_api_key", "by_model", "by_user", "end_date", "series", "start_date", "totals"] + + @field_validator('bucket') + def bucket_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['hour', 'day']): + raise ValueError("must be one of enum values ('hour', 'day')") + return value + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageSummary 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 by_api_key (list) + _items = [] + if self.by_api_key: + for _item_by_api_key in self.by_api_key: + if _item_by_api_key: + _items.append(_item_by_api_key.to_dict()) + _dict['by_api_key'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in by_model (list) + _items = [] + if self.by_model: + for _item_by_model in self.by_model: + if _item_by_model: + _items.append(_item_by_model.to_dict()) + _dict['by_model'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in by_user (list) + _items = [] + if self.by_user: + for _item_by_user in self.by_user: + if _item_by_user: + _items.append(_item_by_user.to_dict()) + _dict['by_user'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in series (list) + _items = [] + if self.series: + for _item_series in self.series: + if _item_series: + _items.append(_item_series.to_dict()) + _dict['series'] = _items + # override the default output from pydantic by calling `to_dict()` of totals + if self.totals: + _dict['totals'] = self.totals.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UsageSummary from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bucket": obj.get("bucket"), + "by_api_key": [UsageGroupRow.from_dict(_item) for _item in obj["by_api_key"]] if obj.get("by_api_key") is not None else None, + "by_model": [UsageGroupRow.from_dict(_item) for _item in obj["by_model"]] if obj.get("by_model") is not None else None, + "by_user": [UsageGroupRow.from_dict(_item) for _item in obj["by_user"]] if obj.get("by_user") is not None else None, + "end_date": obj.get("end_date"), + "series": [UsageSeriesPoint.from_dict(_item) for _item in obj["series"]] if obj.get("series") is not None else None, + "start_date": obj.get("start_date"), + "totals": UsageTotals.from_dict(obj["totals"]) if obj.get("totals") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/usage_totals.py b/src/otari/_client/models/usage_totals.py new file mode 100644 index 0000000..b03cb15 --- /dev/null +++ b/src/otari/_client/models/usage_totals.py @@ -0,0 +1,109 @@ +# 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, StrictFloat, StrictInt +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UsageTotals(BaseModel): + """ + Grand totals over the filtered window. + """ # noqa: E501 + avg_latency_ms: Optional[Union[StrictFloat, StrictInt]] + cache_read_tokens: StrictInt + cache_write_tokens: StrictInt + completion_tokens: StrictInt + cost: Union[StrictFloat, StrictInt] + error_count: StrictInt + prompt_tokens: StrictInt + request_count: StrictInt + total_tokens: StrictInt + __properties: ClassVar[List[str]] = ["avg_latency_ms", "cache_read_tokens", "cache_write_tokens", "completion_tokens", "cost", "error_count", "prompt_tokens", "request_count", "total_tokens"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UsageTotals 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 avg_latency_ms (nullable) is None + # and model_fields_set contains the field + if self.avg_latency_ms is None and "avg_latency_ms" in self.model_fields_set: + _dict['avg_latency_ms'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UsageTotals from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "avg_latency_ms": obj.get("avg_latency_ms"), + "cache_read_tokens": obj.get("cache_read_tokens"), + "cache_write_tokens": obj.get("cache_write_tokens"), + "completion_tokens": obj.get("completion_tokens"), + "cost": obj.get("cost"), + "error_count": obj.get("error_count"), + "prompt_tokens": obj.get("prompt_tokens"), + "request_count": obj.get("request_count"), + "total_tokens": obj.get("total_tokens") + }) + return _obj + + diff --git a/src/otari/_client/models/user_response.py b/src/otari/_client/models/user_response.py index f6344c0..1c4b71d 100644 --- a/src/otari/_client/models/user_response.py +++ b/src/otari/_client/models/user_response.py @@ -28,6 +28,7 @@ class UserResponse(BaseModel): Response model for user information. """ # noqa: E501 alias: Optional[StrictStr] + allowed_models: Optional[List[StrictStr]] blocked: StrictBool budget_id: Optional[StrictStr] budget_started_at: Optional[StrictStr] @@ -38,7 +39,7 @@ class UserResponse(BaseModel): spend: Union[StrictFloat, StrictInt] updated_at: StrictStr user_id: StrictStr - __properties: ClassVar[List[str]] = ["alias", "blocked", "budget_id", "budget_started_at", "created_at", "metadata", "next_budget_reset_at", "reserved", "spend", "updated_at", "user_id"] + __properties: ClassVar[List[str]] = ["alias", "allowed_models", "blocked", "budget_id", "budget_started_at", "created_at", "metadata", "next_budget_reset_at", "reserved", "spend", "updated_at", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -84,6 +85,11 @@ def to_dict(self) -> Dict[str, Any]: if self.alias is None and "alias" in self.model_fields_set: _dict['alias'] = None + # set to None if allowed_models (nullable) is None + # and model_fields_set contains the field + if self.allowed_models is None and "allowed_models" in self.model_fields_set: + _dict['allowed_models'] = None + # set to None if budget_id (nullable) is None # and model_fields_set contains the field if self.budget_id is None and "budget_id" in self.model_fields_set: @@ -112,6 +118,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "alias": obj.get("alias"), + "allowed_models": obj.get("allowed_models"), "blocked": obj.get("blocked"), "budget_id": obj.get("budget_id"), "budget_started_at": obj.get("budget_started_at"), diff --git a/src/otari/_client/models/value.py b/src/otari/_client/models/value.py new file mode 100644 index 0000000..b701844 --- /dev/null +++ b/src/otari/_client/models/value.py @@ -0,0 +1,195 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, ValidationError, field_validator +from typing import List, Optional, Union +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +VALUE_ANY_OF_SCHEMAS = ["List[str]", "bool", "float", "int", "str"] + +class Value(BaseModel): + """ + Value + """ + + # data type: bool + anyof_schema_1_validator: Optional[StrictBool] = None + # data type: int + anyof_schema_2_validator: Optional[StrictInt] = None + # data type: float + anyof_schema_3_validator: Optional[Union[StrictFloat, StrictInt]] = None + # data type: str + anyof_schema_4_validator: Optional[StrictStr] = None + # data type: List[str] + anyof_schema_5_validator: Optional[List[StrictStr]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[List[str], bool, float, int, str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "List[str]", "bool", "float", "int", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = Value.model_construct() + error_messages = [] + # validate data type: bool + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: int + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: float + try: + instance.anyof_schema_3_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: str + try: + instance.anyof_schema_4_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: List[str] + try: + instance.anyof_schema_5_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Value with anyOf schemas: List[str], bool, float, int, str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # deserialize data into bool + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into int + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into float + try: + # validation + instance.anyof_schema_3_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_3_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into str + try: + # validation + instance.anyof_schema_4_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_4_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into List[str] + try: + # validation + instance.anyof_schema_5_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_5_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Value with anyOf schemas: List[str], bool, float, int, str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], List[str], bool, float, int, str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/value1.py b/src/otari/_client/models/value1.py new file mode 100644 index 0000000..38b23a2 --- /dev/null +++ b/src/otari/_client/models/value1.py @@ -0,0 +1,161 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, ValidationError, field_validator +from typing import Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +VALUE1_ANY_OF_SCHEMAS = ["bool", "int", "str"] + +class Value1(BaseModel): + """ + Value1 + """ + + # data type: bool + anyof_schema_1_validator: Optional[StrictBool] = None + # data type: int + anyof_schema_2_validator: Optional[StrictInt] = None + # data type: str + anyof_schema_3_validator: Optional[StrictStr] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[bool, int, str]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "bool", "int", "str" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = Value1.model_construct() + error_messages = [] + # validate data type: bool + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: int + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: str + try: + instance.anyof_schema_3_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Value1 with anyOf schemas: bool, int, str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # deserialize data into bool + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into int + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into str + try: + # validation + instance.anyof_schema_3_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_3_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Value1 with anyOf schemas: bool, int, str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], bool, int, str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + +