mirror of
https://github.com/wassname/openrouter-python-sdk-retry-errors.git
synced 2026-08-01 12:40:23 +08:00
first commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
from .types import Hooks
|
||||
|
||||
|
||||
# This file is only ever generated once on the first generation and then is free to be modified.
|
||||
# Any hooks you wish to add should be registered in the init_hooks function. Feel free to define them
|
||||
# in this file or in separate files in the hooks folder.
|
||||
|
||||
|
||||
def init_hooks(hooks: Hooks):
|
||||
# pylint: disable=unused-argument
|
||||
"""Add hooks by calling hooks.register{sdk_init/before_request/after_success/after_error}Hook
|
||||
with an instance of a hook that implements that specific Hook interface
|
||||
Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance"""
|
||||
@@ -0,0 +1,17 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from ._version import (
|
||||
__title__,
|
||||
__version__,
|
||||
__openapi_doc_version__,
|
||||
__gen_version__,
|
||||
__user_agent__,
|
||||
)
|
||||
from .sdk import *
|
||||
from .sdkconfiguration import *
|
||||
|
||||
|
||||
VERSION: str = __version__
|
||||
OPENAPI_DOC_VERSION = __openapi_doc_version__
|
||||
SPEAKEASY_GENERATOR_VERSION = __gen_version__
|
||||
USER_AGENT = __user_agent__
|
||||
@@ -0,0 +1,5 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from .sdkhooks import *
|
||||
from .types import *
|
||||
from .registration import *
|
||||
@@ -0,0 +1,13 @@
|
||||
from .types import Hooks
|
||||
|
||||
|
||||
# This file is only ever generated once on the first generation and then is free to be modified.
|
||||
# Any hooks you wish to add should be registered in the init_hooks function. Feel free to define them
|
||||
# in this file or in separate files in the hooks folder.
|
||||
|
||||
|
||||
def init_hooks(hooks: Hooks):
|
||||
# pylint: disable=unused-argument
|
||||
"""Add hooks by calling hooks.register{sdk_init/before_request/after_success/after_error}Hook
|
||||
with an instance of a hook that implements that specific Hook interface
|
||||
Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance"""
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import httpx
|
||||
from .types import (
|
||||
SDKInitHook,
|
||||
BeforeRequestContext,
|
||||
BeforeRequestHook,
|
||||
AfterSuccessContext,
|
||||
AfterSuccessHook,
|
||||
AfterErrorContext,
|
||||
AfterErrorHook,
|
||||
Hooks,
|
||||
)
|
||||
from .registration import init_hooks
|
||||
from typing import List, Optional, Tuple
|
||||
from openrouter.sdkconfiguration import SDKConfiguration
|
||||
|
||||
|
||||
class SDKHooks(Hooks):
|
||||
def __init__(self) -> None:
|
||||
self.sdk_init_hooks: List[SDKInitHook] = []
|
||||
self.before_request_hooks: List[BeforeRequestHook] = []
|
||||
self.after_success_hooks: List[AfterSuccessHook] = []
|
||||
self.after_error_hooks: List[AfterErrorHook] = []
|
||||
init_hooks(self)
|
||||
|
||||
def register_sdk_init_hook(self, hook: SDKInitHook) -> None:
|
||||
self.sdk_init_hooks.append(hook)
|
||||
|
||||
def register_before_request_hook(self, hook: BeforeRequestHook) -> None:
|
||||
self.before_request_hooks.append(hook)
|
||||
|
||||
def register_after_success_hook(self, hook: AfterSuccessHook) -> None:
|
||||
self.after_success_hooks.append(hook)
|
||||
|
||||
def register_after_error_hook(self, hook: AfterErrorHook) -> None:
|
||||
self.after_error_hooks.append(hook)
|
||||
|
||||
def sdk_init(self, config: SDKConfiguration) -> SDKConfiguration:
|
||||
for hook in self.sdk_init_hooks:
|
||||
config = hook.sdk_init(config)
|
||||
return config
|
||||
|
||||
def before_request(
|
||||
self, hook_ctx: BeforeRequestContext, request: httpx.Request
|
||||
) -> httpx.Request:
|
||||
for hook in self.before_request_hooks:
|
||||
out = hook.before_request(hook_ctx, request)
|
||||
if isinstance(out, Exception):
|
||||
raise out
|
||||
request = out
|
||||
|
||||
return request
|
||||
|
||||
def after_success(
|
||||
self, hook_ctx: AfterSuccessContext, response: httpx.Response
|
||||
) -> httpx.Response:
|
||||
for hook in self.after_success_hooks:
|
||||
out = hook.after_success(hook_ctx, response)
|
||||
if isinstance(out, Exception):
|
||||
raise out
|
||||
response = out
|
||||
return response
|
||||
|
||||
def after_error(
|
||||
self,
|
||||
hook_ctx: AfterErrorContext,
|
||||
response: Optional[httpx.Response],
|
||||
error: Optional[Exception],
|
||||
) -> Tuple[Optional[httpx.Response], Optional[Exception]]:
|
||||
for hook in self.after_error_hooks:
|
||||
result = hook.after_error(hook_ctx, response, error)
|
||||
if isinstance(result, Exception):
|
||||
raise result
|
||||
response, error = result
|
||||
return response, error
|
||||
@@ -0,0 +1,112 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import httpx
|
||||
from openrouter.sdkconfiguration import SDKConfiguration
|
||||
from typing import Any, Callable, List, Optional, Tuple, Union
|
||||
|
||||
|
||||
class HookContext:
|
||||
config: SDKConfiguration
|
||||
base_url: str
|
||||
operation_id: str
|
||||
oauth2_scopes: Optional[List[str]] = None
|
||||
security_source: Optional[Union[Any, Callable[[], Any]]] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: SDKConfiguration,
|
||||
base_url: str,
|
||||
operation_id: str,
|
||||
oauth2_scopes: Optional[List[str]],
|
||||
security_source: Optional[Union[Any, Callable[[], Any]]],
|
||||
):
|
||||
self.config = config
|
||||
self.base_url = base_url
|
||||
self.operation_id = operation_id
|
||||
self.oauth2_scopes = oauth2_scopes
|
||||
self.security_source = security_source
|
||||
|
||||
|
||||
class BeforeRequestContext(HookContext):
|
||||
def __init__(self, hook_ctx: HookContext):
|
||||
super().__init__(
|
||||
hook_ctx.config,
|
||||
hook_ctx.base_url,
|
||||
hook_ctx.operation_id,
|
||||
hook_ctx.oauth2_scopes,
|
||||
hook_ctx.security_source,
|
||||
)
|
||||
|
||||
|
||||
class AfterSuccessContext(HookContext):
|
||||
def __init__(self, hook_ctx: HookContext):
|
||||
super().__init__(
|
||||
hook_ctx.config,
|
||||
hook_ctx.base_url,
|
||||
hook_ctx.operation_id,
|
||||
hook_ctx.oauth2_scopes,
|
||||
hook_ctx.security_source,
|
||||
)
|
||||
|
||||
|
||||
class AfterErrorContext(HookContext):
|
||||
def __init__(self, hook_ctx: HookContext):
|
||||
super().__init__(
|
||||
hook_ctx.config,
|
||||
hook_ctx.base_url,
|
||||
hook_ctx.operation_id,
|
||||
hook_ctx.oauth2_scopes,
|
||||
hook_ctx.security_source,
|
||||
)
|
||||
|
||||
|
||||
class SDKInitHook(ABC):
|
||||
@abstractmethod
|
||||
def sdk_init(self, config: SDKConfiguration) -> SDKConfiguration:
|
||||
pass
|
||||
|
||||
|
||||
class BeforeRequestHook(ABC):
|
||||
@abstractmethod
|
||||
def before_request(
|
||||
self, hook_ctx: BeforeRequestContext, request: httpx.Request
|
||||
) -> Union[httpx.Request, Exception]:
|
||||
pass
|
||||
|
||||
|
||||
class AfterSuccessHook(ABC):
|
||||
@abstractmethod
|
||||
def after_success(
|
||||
self, hook_ctx: AfterSuccessContext, response: httpx.Response
|
||||
) -> Union[httpx.Response, Exception]:
|
||||
pass
|
||||
|
||||
|
||||
class AfterErrorHook(ABC):
|
||||
@abstractmethod
|
||||
def after_error(
|
||||
self,
|
||||
hook_ctx: AfterErrorContext,
|
||||
response: Optional[httpx.Response],
|
||||
error: Optional[Exception],
|
||||
) -> Union[Tuple[Optional[httpx.Response], Optional[Exception]], Exception]:
|
||||
pass
|
||||
|
||||
|
||||
class Hooks(ABC):
|
||||
@abstractmethod
|
||||
def register_sdk_init_hook(self, hook: SDKInitHook):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def register_before_request_hook(self, hook: BeforeRequestHook):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def register_after_success_hook(self, hook: AfterSuccessHook):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def register_after_error_hook(self, hook: AfterErrorHook):
|
||||
pass
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import importlib.metadata
|
||||
|
||||
__title__: str = "openrouter"
|
||||
__version__: str = "0.1.2"
|
||||
__openapi_doc_version__: str = "1.0.0"
|
||||
__gen_version__: str = "2.687.1"
|
||||
__user_agent__: str = "speakeasy-sdk/python 0.1.2 2.687.1 1.0.0 openrouter"
|
||||
|
||||
try:
|
||||
if __package__ is not None:
|
||||
__version__ = importlib.metadata.version(__package__)
|
||||
except importlib.metadata.PackageNotFoundError:
|
||||
pass
|
||||
@@ -0,0 +1,358 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from .sdkconfiguration import SDKConfiguration
|
||||
import httpx
|
||||
from openrouter import errors, models, utils
|
||||
from openrouter._hooks import (
|
||||
AfterErrorContext,
|
||||
AfterSuccessContext,
|
||||
BeforeRequestContext,
|
||||
)
|
||||
from openrouter.utils import RetryConfig, SerializedRequestBody, get_body_content
|
||||
from typing import Callable, List, Mapping, Optional, Tuple
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
|
||||
class BaseSDK:
|
||||
sdk_configuration: SDKConfiguration
|
||||
|
||||
def __init__(self, sdk_config: SDKConfiguration) -> None:
|
||||
self.sdk_configuration = sdk_config
|
||||
|
||||
def _get_url(self, base_url, url_variables):
|
||||
sdk_url, sdk_variables = self.sdk_configuration.get_server_details()
|
||||
|
||||
if base_url is None:
|
||||
base_url = sdk_url
|
||||
|
||||
if url_variables is None:
|
||||
url_variables = sdk_variables
|
||||
|
||||
return utils.template_url(base_url, url_variables)
|
||||
|
||||
def _build_request_async(
|
||||
self,
|
||||
method,
|
||||
path,
|
||||
base_url,
|
||||
url_variables,
|
||||
request,
|
||||
request_body_required,
|
||||
request_has_path_params,
|
||||
request_has_query_params,
|
||||
user_agent_header,
|
||||
accept_header_value,
|
||||
_globals=None,
|
||||
security=None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
get_serialized_body: Optional[
|
||||
Callable[[], Optional[SerializedRequestBody]]
|
||||
] = None,
|
||||
url_override: Optional[str] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> httpx.Request:
|
||||
client = self.sdk_configuration.async_client
|
||||
return self._build_request_with_client(
|
||||
client,
|
||||
method,
|
||||
path,
|
||||
base_url,
|
||||
url_variables,
|
||||
request,
|
||||
request_body_required,
|
||||
request_has_path_params,
|
||||
request_has_query_params,
|
||||
user_agent_header,
|
||||
accept_header_value,
|
||||
_globals,
|
||||
security,
|
||||
timeout_ms,
|
||||
get_serialized_body,
|
||||
url_override,
|
||||
http_headers,
|
||||
)
|
||||
|
||||
def _build_request(
|
||||
self,
|
||||
method,
|
||||
path,
|
||||
base_url,
|
||||
url_variables,
|
||||
request,
|
||||
request_body_required,
|
||||
request_has_path_params,
|
||||
request_has_query_params,
|
||||
user_agent_header,
|
||||
accept_header_value,
|
||||
_globals=None,
|
||||
security=None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
get_serialized_body: Optional[
|
||||
Callable[[], Optional[SerializedRequestBody]]
|
||||
] = None,
|
||||
url_override: Optional[str] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> httpx.Request:
|
||||
client = self.sdk_configuration.client
|
||||
return self._build_request_with_client(
|
||||
client,
|
||||
method,
|
||||
path,
|
||||
base_url,
|
||||
url_variables,
|
||||
request,
|
||||
request_body_required,
|
||||
request_has_path_params,
|
||||
request_has_query_params,
|
||||
user_agent_header,
|
||||
accept_header_value,
|
||||
_globals,
|
||||
security,
|
||||
timeout_ms,
|
||||
get_serialized_body,
|
||||
url_override,
|
||||
http_headers,
|
||||
)
|
||||
|
||||
def _build_request_with_client(
|
||||
self,
|
||||
client,
|
||||
method,
|
||||
path,
|
||||
base_url,
|
||||
url_variables,
|
||||
request,
|
||||
request_body_required,
|
||||
request_has_path_params,
|
||||
request_has_query_params,
|
||||
user_agent_header,
|
||||
accept_header_value,
|
||||
_globals=None,
|
||||
security=None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
get_serialized_body: Optional[
|
||||
Callable[[], Optional[SerializedRequestBody]]
|
||||
] = None,
|
||||
url_override: Optional[str] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> httpx.Request:
|
||||
query_params = {}
|
||||
|
||||
url = url_override
|
||||
if url is None:
|
||||
url = utils.generate_url(
|
||||
self._get_url(base_url, url_variables),
|
||||
path,
|
||||
request if request_has_path_params else None,
|
||||
_globals if request_has_path_params else None,
|
||||
)
|
||||
|
||||
query_params = utils.get_query_params(
|
||||
request if request_has_query_params else None,
|
||||
_globals if request_has_query_params else None,
|
||||
)
|
||||
else:
|
||||
# Pick up the query parameter from the override so they can be
|
||||
# preserved when building the request later on (necessary as of
|
||||
# httpx 0.28).
|
||||
parsed_override = urlparse(str(url_override))
|
||||
query_params = parse_qs(parsed_override.query, keep_blank_values=True)
|
||||
|
||||
headers = utils.get_headers(request, _globals)
|
||||
headers["Accept"] = accept_header_value
|
||||
headers[user_agent_header] = self.sdk_configuration.user_agent
|
||||
|
||||
if security is not None:
|
||||
if callable(security):
|
||||
security = security()
|
||||
security = utils.get_security_from_env(security, models.Security)
|
||||
if security is not None:
|
||||
security_headers, security_query_params = utils.get_security(security)
|
||||
headers = {**headers, **security_headers}
|
||||
query_params = {**query_params, **security_query_params}
|
||||
|
||||
serialized_request_body = SerializedRequestBody()
|
||||
if get_serialized_body is not None:
|
||||
rb = get_serialized_body()
|
||||
if request_body_required and rb is None:
|
||||
raise ValueError("request body is required")
|
||||
|
||||
if rb is not None:
|
||||
serialized_request_body = rb
|
||||
|
||||
if (
|
||||
serialized_request_body.media_type is not None
|
||||
and serialized_request_body.media_type
|
||||
not in (
|
||||
"multipart/form-data",
|
||||
"multipart/mixed",
|
||||
)
|
||||
):
|
||||
headers["content-type"] = serialized_request_body.media_type
|
||||
|
||||
if http_headers is not None:
|
||||
for header, value in http_headers.items():
|
||||
headers[header] = value
|
||||
|
||||
timeout = timeout_ms / 1000 if timeout_ms is not None else None
|
||||
|
||||
return client.build_request(
|
||||
method,
|
||||
url,
|
||||
params=query_params,
|
||||
content=serialized_request_body.content,
|
||||
data=serialized_request_body.data,
|
||||
files=serialized_request_body.files,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
)
|
||||
|
||||
def do_request(
|
||||
self,
|
||||
hook_ctx,
|
||||
request,
|
||||
error_status_codes,
|
||||
stream=False,
|
||||
retry_config: Optional[Tuple[RetryConfig, List[str]]] = None,
|
||||
) -> httpx.Response:
|
||||
client = self.sdk_configuration.client
|
||||
logger = self.sdk_configuration.debug_logger
|
||||
|
||||
hooks = self.sdk_configuration.__dict__["_hooks"]
|
||||
|
||||
def do():
|
||||
http_res = None
|
||||
try:
|
||||
req = hooks.before_request(BeforeRequestContext(hook_ctx), request)
|
||||
logger.debug(
|
||||
"Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
||||
req.method,
|
||||
req.url,
|
||||
req.headers,
|
||||
get_body_content(req),
|
||||
)
|
||||
|
||||
if client is None:
|
||||
raise ValueError("client is required")
|
||||
|
||||
http_res = client.send(req, stream=stream)
|
||||
except Exception as e:
|
||||
_, e = hooks.after_error(AfterErrorContext(hook_ctx), None, e)
|
||||
if e is not None:
|
||||
logger.debug("Request Exception", exc_info=True)
|
||||
raise e
|
||||
|
||||
if http_res is None:
|
||||
logger.debug("Raising no response SDK error")
|
||||
raise errors.NoResponseError("No response received")
|
||||
|
||||
logger.debug(
|
||||
"Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
||||
http_res.status_code,
|
||||
http_res.url,
|
||||
http_res.headers,
|
||||
"<streaming response>" if stream else http_res.text,
|
||||
)
|
||||
|
||||
if utils.match_status_codes(error_status_codes, http_res.status_code):
|
||||
result, err = hooks.after_error(
|
||||
AfterErrorContext(hook_ctx), http_res, None
|
||||
)
|
||||
if err is not None:
|
||||
logger.debug("Request Exception", exc_info=True)
|
||||
raise err
|
||||
if result is not None:
|
||||
http_res = result
|
||||
else:
|
||||
logger.debug("Raising unexpected SDK error")
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"Unexpected error occurred", http_res
|
||||
)
|
||||
|
||||
return http_res
|
||||
|
||||
if retry_config is not None:
|
||||
http_res = utils.retry(do, utils.Retries(retry_config[0], retry_config[1]))
|
||||
else:
|
||||
http_res = do()
|
||||
|
||||
if not utils.match_status_codes(error_status_codes, http_res.status_code):
|
||||
http_res = hooks.after_success(AfterSuccessContext(hook_ctx), http_res)
|
||||
|
||||
return http_res
|
||||
|
||||
async def do_request_async(
|
||||
self,
|
||||
hook_ctx,
|
||||
request,
|
||||
error_status_codes,
|
||||
stream=False,
|
||||
retry_config: Optional[Tuple[RetryConfig, List[str]]] = None,
|
||||
) -> httpx.Response:
|
||||
client = self.sdk_configuration.async_client
|
||||
logger = self.sdk_configuration.debug_logger
|
||||
|
||||
hooks = self.sdk_configuration.__dict__["_hooks"]
|
||||
|
||||
async def do():
|
||||
http_res = None
|
||||
try:
|
||||
req = hooks.before_request(BeforeRequestContext(hook_ctx), request)
|
||||
logger.debug(
|
||||
"Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
||||
req.method,
|
||||
req.url,
|
||||
req.headers,
|
||||
get_body_content(req),
|
||||
)
|
||||
|
||||
if client is None:
|
||||
raise ValueError("client is required")
|
||||
|
||||
http_res = await client.send(req, stream=stream)
|
||||
except Exception as e:
|
||||
_, e = hooks.after_error(AfterErrorContext(hook_ctx), None, e)
|
||||
if e is not None:
|
||||
logger.debug("Request Exception", exc_info=True)
|
||||
raise e
|
||||
|
||||
if http_res is None:
|
||||
logger.debug("Raising no response SDK error")
|
||||
raise errors.NoResponseError("No response received")
|
||||
|
||||
logger.debug(
|
||||
"Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s",
|
||||
http_res.status_code,
|
||||
http_res.url,
|
||||
http_res.headers,
|
||||
"<streaming response>" if stream else http_res.text,
|
||||
)
|
||||
|
||||
if utils.match_status_codes(error_status_codes, http_res.status_code):
|
||||
result, err = hooks.after_error(
|
||||
AfterErrorContext(hook_ctx), http_res, None
|
||||
)
|
||||
if err is not None:
|
||||
logger.debug("Request Exception", exc_info=True)
|
||||
raise err
|
||||
if result is not None:
|
||||
http_res = result
|
||||
else:
|
||||
logger.debug("Raising unexpected SDK error")
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"Unexpected error occurred", http_res
|
||||
)
|
||||
|
||||
return http_res
|
||||
|
||||
if retry_config is not None:
|
||||
http_res = await utils.retry_async(
|
||||
do, utils.Retries(retry_config[0], retry_config[1])
|
||||
)
|
||||
else:
|
||||
http_res = await do()
|
||||
|
||||
if not utils.match_status_codes(error_status_codes, http_res.status_code):
|
||||
http_res = hooks.after_success(AfterSuccessContext(hook_ctx), http_res)
|
||||
|
||||
return http_res
|
||||
@@ -0,0 +1,987 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from .basesdk import BaseSDK
|
||||
from openrouter import errors, models, utils
|
||||
from openrouter._hooks import HookContext
|
||||
from openrouter.types import OptionalNullable, UNSET
|
||||
from openrouter.utils import eventstreaming, get_security_from_env
|
||||
from openrouter.utils.unmarshal_json_response import unmarshal_json_response
|
||||
from typing import Any, Dict, List, Mapping, Optional, Union
|
||||
|
||||
|
||||
class Chat(BaseSDK):
|
||||
r"""Chat completion operations"""
|
||||
|
||||
def complete(
|
||||
self,
|
||||
*,
|
||||
messages: Union[
|
||||
List[models.ChatCompletionMessageParam],
|
||||
List[models.ChatCompletionMessageParamTypedDict],
|
||||
],
|
||||
model: Optional[str] = None,
|
||||
frequency_penalty: OptionalNullable[float] = UNSET,
|
||||
logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
|
||||
logprobs: OptionalNullable[bool] = UNSET,
|
||||
top_logprobs: OptionalNullable[float] = UNSET,
|
||||
max_completion_tokens: OptionalNullable[float] = UNSET,
|
||||
max_tokens: OptionalNullable[float] = UNSET,
|
||||
metadata: Optional[Dict[str, str]] = None,
|
||||
presence_penalty: OptionalNullable[float] = UNSET,
|
||||
reasoning: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsReasoning,
|
||||
models.ChatCompletionCreateParamsReasoningTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
response_format: Optional[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsResponseFormatUnion,
|
||||
models.ChatCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
seed: OptionalNullable[int] = UNSET,
|
||||
stop: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsStop,
|
||||
models.ChatCompletionCreateParamsStopTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
stream: OptionalNullable[bool] = False,
|
||||
stream_options: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsStreamOptions,
|
||||
models.ChatCompletionCreateParamsStreamOptionsTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
temperature: OptionalNullable[float] = 1,
|
||||
tool_choice: Optional[
|
||||
Union[
|
||||
models.ChatCompletionToolChoiceOption,
|
||||
models.ChatCompletionToolChoiceOptionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
tools: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionTool],
|
||||
List[models.ChatCompletionToolTypedDict],
|
||||
]
|
||||
] = None,
|
||||
top_p: OptionalNullable[float] = 1,
|
||||
user: Optional[str] = None,
|
||||
models_llm: OptionalNullable[List[str]] = UNSET,
|
||||
reasoning_effort: OptionalNullable[
|
||||
models.ChatCompletionCreateParamsReasoningEffort
|
||||
] = UNSET,
|
||||
provider: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsProvider,
|
||||
models.ChatCompletionCreateParamsProviderTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
plugins: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionCreateParamsPluginUnion],
|
||||
List[models.ChatCompletionCreateParamsPluginUnionTypedDict],
|
||||
]
|
||||
] = None,
|
||||
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
||||
server_url: Optional[str] = None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> models.ChatCompletion:
|
||||
r"""Create a chat completion
|
||||
|
||||
Creates a model response for the given chat conversation. Supports both streaming and non-streaming modes.
|
||||
|
||||
:param messages: List of messages for the conversation
|
||||
:param model: Model to use for completion
|
||||
:param frequency_penalty: Frequency penalty (-2.0 to 2.0)
|
||||
:param logit_bias: Token logit bias adjustments
|
||||
:param logprobs: Return log probabilities
|
||||
:param top_logprobs: Number of top log probabilities to return (0-20)
|
||||
:param max_completion_tokens: Maximum tokens in completion
|
||||
:param max_tokens: Maximum tokens (deprecated, use max_completion_tokens)
|
||||
:param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
|
||||
:param presence_penalty: Presence penalty (-2.0 to 2.0)
|
||||
:param reasoning: Reasoning configuration
|
||||
:param response_format: Response format configuration
|
||||
:param seed: Random seed for deterministic outputs
|
||||
:param stop: Stop sequences (up to 4)
|
||||
:param stream: Enable streaming response
|
||||
:param stream_options:
|
||||
:param temperature: Sampling temperature (0-2)
|
||||
:param tool_choice: Tool choice configuration
|
||||
:param tools: Available tools for function calling
|
||||
:param top_p: Nucleus sampling parameter (0-1)
|
||||
:param user: Unique user identifier
|
||||
:param models_llm: Order of models to fallback to for this request
|
||||
:param reasoning_effort: Reasoning effort
|
||||
:param provider: When multiple model providers are available, optionally indicate your routing preference.
|
||||
:param plugins: Plugins you want to enable for this request, including their settings.
|
||||
:param retries: Override the default retry configuration for this method
|
||||
:param server_url: Override the default server URL for this method
|
||||
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
||||
:param http_headers: Additional headers to set or replace on requests.
|
||||
"""
|
||||
base_url = None
|
||||
url_variables = None
|
||||
if timeout_ms is None:
|
||||
timeout_ms = self.sdk_configuration.timeout_ms
|
||||
|
||||
if server_url is not None:
|
||||
base_url = server_url
|
||||
else:
|
||||
base_url = self._get_url(base_url, url_variables)
|
||||
|
||||
request = models.ChatCompletionCreateParams(
|
||||
messages=utils.get_pydantic_model(
|
||||
messages, List[models.ChatCompletionMessageParam]
|
||||
),
|
||||
model=model,
|
||||
frequency_penalty=frequency_penalty,
|
||||
logit_bias=logit_bias,
|
||||
logprobs=logprobs,
|
||||
top_logprobs=top_logprobs,
|
||||
max_completion_tokens=max_completion_tokens,
|
||||
max_tokens=max_tokens,
|
||||
metadata=metadata,
|
||||
presence_penalty=presence_penalty,
|
||||
reasoning=utils.get_pydantic_model(
|
||||
reasoning, OptionalNullable[models.ChatCompletionCreateParamsReasoning]
|
||||
),
|
||||
response_format=utils.get_pydantic_model(
|
||||
response_format,
|
||||
Optional[models.ChatCompletionCreateParamsResponseFormatUnion],
|
||||
),
|
||||
seed=seed,
|
||||
stop=stop,
|
||||
stream=stream,
|
||||
stream_options=utils.get_pydantic_model(
|
||||
stream_options,
|
||||
OptionalNullable[models.ChatCompletionCreateParamsStreamOptions],
|
||||
),
|
||||
temperature=temperature,
|
||||
tool_choice=utils.get_pydantic_model(
|
||||
tool_choice, Optional[models.ChatCompletionToolChoiceOption]
|
||||
),
|
||||
tools=utils.get_pydantic_model(
|
||||
tools, Optional[List[models.ChatCompletionTool]]
|
||||
),
|
||||
top_p=top_p,
|
||||
user=user,
|
||||
models_llm=models_llm,
|
||||
reasoning_effort=reasoning_effort,
|
||||
provider=utils.get_pydantic_model(
|
||||
provider, OptionalNullable[models.ChatCompletionCreateParamsProvider]
|
||||
),
|
||||
plugins=utils.get_pydantic_model(
|
||||
plugins, Optional[List[models.ChatCompletionCreateParamsPluginUnion]]
|
||||
),
|
||||
)
|
||||
|
||||
req = self._build_request(
|
||||
method="POST",
|
||||
path="/chat/completions",
|
||||
base_url=base_url,
|
||||
url_variables=url_variables,
|
||||
request=request,
|
||||
request_body_required=True,
|
||||
request_has_path_params=False,
|
||||
request_has_query_params=True,
|
||||
user_agent_header="user-agent",
|
||||
accept_header_value="application/json",
|
||||
http_headers=http_headers,
|
||||
security=self.sdk_configuration.security,
|
||||
get_serialized_body=lambda: utils.serialize_request_body(
|
||||
request, False, False, "json", models.ChatCompletionCreateParams
|
||||
),
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
|
||||
if retries == UNSET:
|
||||
if self.sdk_configuration.retry_config is not UNSET:
|
||||
retries = self.sdk_configuration.retry_config
|
||||
|
||||
retry_config = None
|
||||
if isinstance(retries, utils.RetryConfig):
|
||||
retry_config = (retries, ["429", "500", "502", "503", "504"])
|
||||
|
||||
http_res = self.do_request(
|
||||
hook_ctx=HookContext(
|
||||
config=self.sdk_configuration,
|
||||
base_url=base_url or "",
|
||||
operation_id="createChatCompletion",
|
||||
oauth2_scopes=[],
|
||||
security_source=get_security_from_env(
|
||||
self.sdk_configuration.security, models.Security
|
||||
),
|
||||
),
|
||||
request=req,
|
||||
error_status_codes=["400", "401", "429", "4XX", "500", "5XX"],
|
||||
retry_config=retry_config,
|
||||
)
|
||||
|
||||
response_data: Any = None
|
||||
if utils.match_response(http_res, "200", "application/json"):
|
||||
return unmarshal_json_response(models.ChatCompletion, http_res)
|
||||
if utils.match_response(http_res, ["400", "401", "429"], "application/json"):
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res)
|
||||
if utils.match_response(http_res, "500", "application/json"):
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res)
|
||||
if utils.match_response(http_res, "4XX", "*"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
if utils.match_response(http_res, "5XX", "*"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
|
||||
raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
|
||||
|
||||
async def complete_async(
|
||||
self,
|
||||
*,
|
||||
messages: Union[
|
||||
List[models.ChatCompletionMessageParam],
|
||||
List[models.ChatCompletionMessageParamTypedDict],
|
||||
],
|
||||
model: Optional[str] = None,
|
||||
frequency_penalty: OptionalNullable[float] = UNSET,
|
||||
logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
|
||||
logprobs: OptionalNullable[bool] = UNSET,
|
||||
top_logprobs: OptionalNullable[float] = UNSET,
|
||||
max_completion_tokens: OptionalNullable[float] = UNSET,
|
||||
max_tokens: OptionalNullable[float] = UNSET,
|
||||
metadata: Optional[Dict[str, str]] = None,
|
||||
presence_penalty: OptionalNullable[float] = UNSET,
|
||||
reasoning: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsReasoning,
|
||||
models.ChatCompletionCreateParamsReasoningTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
response_format: Optional[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsResponseFormatUnion,
|
||||
models.ChatCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
seed: OptionalNullable[int] = UNSET,
|
||||
stop: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsStop,
|
||||
models.ChatCompletionCreateParamsStopTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
stream: OptionalNullable[bool] = False,
|
||||
stream_options: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsStreamOptions,
|
||||
models.ChatCompletionCreateParamsStreamOptionsTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
temperature: OptionalNullable[float] = 1,
|
||||
tool_choice: Optional[
|
||||
Union[
|
||||
models.ChatCompletionToolChoiceOption,
|
||||
models.ChatCompletionToolChoiceOptionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
tools: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionTool],
|
||||
List[models.ChatCompletionToolTypedDict],
|
||||
]
|
||||
] = None,
|
||||
top_p: OptionalNullable[float] = 1,
|
||||
user: Optional[str] = None,
|
||||
models_llm: OptionalNullable[List[str]] = UNSET,
|
||||
reasoning_effort: OptionalNullable[
|
||||
models.ChatCompletionCreateParamsReasoningEffort
|
||||
] = UNSET,
|
||||
provider: OptionalNullable[
|
||||
Union[
|
||||
models.ChatCompletionCreateParamsProvider,
|
||||
models.ChatCompletionCreateParamsProviderTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
plugins: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionCreateParamsPluginUnion],
|
||||
List[models.ChatCompletionCreateParamsPluginUnionTypedDict],
|
||||
]
|
||||
] = None,
|
||||
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
||||
server_url: Optional[str] = None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> models.ChatCompletion:
|
||||
r"""Create a chat completion
|
||||
|
||||
Creates a model response for the given chat conversation. Supports both streaming and non-streaming modes.
|
||||
|
||||
:param messages: List of messages for the conversation
|
||||
:param model: Model to use for completion
|
||||
:param frequency_penalty: Frequency penalty (-2.0 to 2.0)
|
||||
:param logit_bias: Token logit bias adjustments
|
||||
:param logprobs: Return log probabilities
|
||||
:param top_logprobs: Number of top log probabilities to return (0-20)
|
||||
:param max_completion_tokens: Maximum tokens in completion
|
||||
:param max_tokens: Maximum tokens (deprecated, use max_completion_tokens)
|
||||
:param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
|
||||
:param presence_penalty: Presence penalty (-2.0 to 2.0)
|
||||
:param reasoning: Reasoning configuration
|
||||
:param response_format: Response format configuration
|
||||
:param seed: Random seed for deterministic outputs
|
||||
:param stop: Stop sequences (up to 4)
|
||||
:param stream: Enable streaming response
|
||||
:param stream_options:
|
||||
:param temperature: Sampling temperature (0-2)
|
||||
:param tool_choice: Tool choice configuration
|
||||
:param tools: Available tools for function calling
|
||||
:param top_p: Nucleus sampling parameter (0-1)
|
||||
:param user: Unique user identifier
|
||||
:param models_llm: Order of models to fallback to for this request
|
||||
:param reasoning_effort: Reasoning effort
|
||||
:param provider: When multiple model providers are available, optionally indicate your routing preference.
|
||||
:param plugins: Plugins you want to enable for this request, including their settings.
|
||||
:param retries: Override the default retry configuration for this method
|
||||
:param server_url: Override the default server URL for this method
|
||||
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
||||
:param http_headers: Additional headers to set or replace on requests.
|
||||
"""
|
||||
base_url = None
|
||||
url_variables = None
|
||||
if timeout_ms is None:
|
||||
timeout_ms = self.sdk_configuration.timeout_ms
|
||||
|
||||
if server_url is not None:
|
||||
base_url = server_url
|
||||
else:
|
||||
base_url = self._get_url(base_url, url_variables)
|
||||
|
||||
request = models.ChatCompletionCreateParams(
|
||||
messages=utils.get_pydantic_model(
|
||||
messages, List[models.ChatCompletionMessageParam]
|
||||
),
|
||||
model=model,
|
||||
frequency_penalty=frequency_penalty,
|
||||
logit_bias=logit_bias,
|
||||
logprobs=logprobs,
|
||||
top_logprobs=top_logprobs,
|
||||
max_completion_tokens=max_completion_tokens,
|
||||
max_tokens=max_tokens,
|
||||
metadata=metadata,
|
||||
presence_penalty=presence_penalty,
|
||||
reasoning=utils.get_pydantic_model(
|
||||
reasoning, OptionalNullable[models.ChatCompletionCreateParamsReasoning]
|
||||
),
|
||||
response_format=utils.get_pydantic_model(
|
||||
response_format,
|
||||
Optional[models.ChatCompletionCreateParamsResponseFormatUnion],
|
||||
),
|
||||
seed=seed,
|
||||
stop=stop,
|
||||
stream=stream,
|
||||
stream_options=utils.get_pydantic_model(
|
||||
stream_options,
|
||||
OptionalNullable[models.ChatCompletionCreateParamsStreamOptions],
|
||||
),
|
||||
temperature=temperature,
|
||||
tool_choice=utils.get_pydantic_model(
|
||||
tool_choice, Optional[models.ChatCompletionToolChoiceOption]
|
||||
),
|
||||
tools=utils.get_pydantic_model(
|
||||
tools, Optional[List[models.ChatCompletionTool]]
|
||||
),
|
||||
top_p=top_p,
|
||||
user=user,
|
||||
models_llm=models_llm,
|
||||
reasoning_effort=reasoning_effort,
|
||||
provider=utils.get_pydantic_model(
|
||||
provider, OptionalNullable[models.ChatCompletionCreateParamsProvider]
|
||||
),
|
||||
plugins=utils.get_pydantic_model(
|
||||
plugins, Optional[List[models.ChatCompletionCreateParamsPluginUnion]]
|
||||
),
|
||||
)
|
||||
|
||||
req = self._build_request_async(
|
||||
method="POST",
|
||||
path="/chat/completions",
|
||||
base_url=base_url,
|
||||
url_variables=url_variables,
|
||||
request=request,
|
||||
request_body_required=True,
|
||||
request_has_path_params=False,
|
||||
request_has_query_params=True,
|
||||
user_agent_header="user-agent",
|
||||
accept_header_value="application/json",
|
||||
http_headers=http_headers,
|
||||
security=self.sdk_configuration.security,
|
||||
get_serialized_body=lambda: utils.serialize_request_body(
|
||||
request, False, False, "json", models.ChatCompletionCreateParams
|
||||
),
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
|
||||
if retries == UNSET:
|
||||
if self.sdk_configuration.retry_config is not UNSET:
|
||||
retries = self.sdk_configuration.retry_config
|
||||
|
||||
retry_config = None
|
||||
if isinstance(retries, utils.RetryConfig):
|
||||
retry_config = (retries, ["429", "500", "502", "503", "504"])
|
||||
|
||||
http_res = await self.do_request_async(
|
||||
hook_ctx=HookContext(
|
||||
config=self.sdk_configuration,
|
||||
base_url=base_url or "",
|
||||
operation_id="createChatCompletion",
|
||||
oauth2_scopes=[],
|
||||
security_source=get_security_from_env(
|
||||
self.sdk_configuration.security, models.Security
|
||||
),
|
||||
),
|
||||
request=req,
|
||||
error_status_codes=["400", "401", "429", "4XX", "500", "5XX"],
|
||||
retry_config=retry_config,
|
||||
)
|
||||
|
||||
response_data: Any = None
|
||||
if utils.match_response(http_res, "200", "application/json"):
|
||||
return unmarshal_json_response(models.ChatCompletion, http_res)
|
||||
if utils.match_response(http_res, ["400", "401", "429"], "application/json"):
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res)
|
||||
if utils.match_response(http_res, "500", "application/json"):
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res)
|
||||
if utils.match_response(http_res, "4XX", "*"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
if utils.match_response(http_res, "5XX", "*"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
|
||||
raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
|
||||
|
||||
def complete_stream(
|
||||
self,
|
||||
*,
|
||||
messages: Union[
|
||||
List[models.ChatCompletionMessageParam],
|
||||
List[models.ChatCompletionMessageParamTypedDict],
|
||||
],
|
||||
model: Optional[str] = None,
|
||||
frequency_penalty: OptionalNullable[float] = UNSET,
|
||||
logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
|
||||
logprobs: OptionalNullable[bool] = UNSET,
|
||||
top_logprobs: OptionalNullable[float] = UNSET,
|
||||
max_completion_tokens: OptionalNullable[float] = UNSET,
|
||||
max_tokens: OptionalNullable[float] = UNSET,
|
||||
metadata: Optional[Dict[str, str]] = None,
|
||||
presence_penalty: OptionalNullable[float] = UNSET,
|
||||
reasoning: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsReasoning,
|
||||
models.ChatStreamCompletionCreateParamsReasoningTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
response_format: Optional[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsResponseFormatUnion,
|
||||
models.ChatStreamCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
seed: OptionalNullable[int] = UNSET,
|
||||
stop: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsStop,
|
||||
models.ChatStreamCompletionCreateParamsStopTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
stream: Optional[bool] = True,
|
||||
stream_options: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsStreamOptions,
|
||||
models.ChatStreamCompletionCreateParamsStreamOptionsTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
temperature: OptionalNullable[float] = 1,
|
||||
tool_choice: Optional[
|
||||
Union[
|
||||
models.ChatCompletionToolChoiceOption,
|
||||
models.ChatCompletionToolChoiceOptionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
tools: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionTool],
|
||||
List[models.ChatCompletionToolTypedDict],
|
||||
]
|
||||
] = None,
|
||||
top_p: OptionalNullable[float] = 1,
|
||||
user: Optional[str] = None,
|
||||
models_llm: OptionalNullable[List[str]] = UNSET,
|
||||
reasoning_effort: OptionalNullable[
|
||||
models.ChatStreamCompletionCreateParamsReasoningEffort
|
||||
] = UNSET,
|
||||
provider: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsProvider,
|
||||
models.ChatStreamCompletionCreateParamsProviderTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
plugins: Optional[
|
||||
Union[
|
||||
List[models.ChatStreamCompletionCreateParamsPluginUnion],
|
||||
List[models.ChatStreamCompletionCreateParamsPluginUnionTypedDict],
|
||||
]
|
||||
] = None,
|
||||
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
||||
server_url: Optional[str] = None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> eventstreaming.EventStream[models.StreamChatCompletionResponseBody]:
|
||||
r"""Create a chat completion
|
||||
|
||||
Creates a model response for the given chat conversation. Supports both streaming and non-streaming modes.
|
||||
|
||||
:param messages: List of messages for the conversation
|
||||
:param model: Model to use for completion
|
||||
:param frequency_penalty: Frequency penalty (-2.0 to 2.0)
|
||||
:param logit_bias: Token logit bias adjustments
|
||||
:param logprobs: Return log probabilities
|
||||
:param top_logprobs: Number of top log probabilities to return (0-20)
|
||||
:param max_completion_tokens: Maximum tokens in completion
|
||||
:param max_tokens: Maximum tokens (deprecated, use max_completion_tokens)
|
||||
:param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
|
||||
:param presence_penalty: Presence penalty (-2.0 to 2.0)
|
||||
:param reasoning: Reasoning configuration
|
||||
:param response_format: Response format configuration
|
||||
:param seed: Random seed for deterministic outputs
|
||||
:param stop: Stop sequences (up to 4)
|
||||
:param stream: Enable streaming response
|
||||
:param stream_options:
|
||||
:param temperature: Sampling temperature (0-2)
|
||||
:param tool_choice: Tool choice configuration
|
||||
:param tools: Available tools for function calling
|
||||
:param top_p: Nucleus sampling parameter (0-1)
|
||||
:param user: Unique user identifier
|
||||
:param models_llm: Order of models to fallback to for this request
|
||||
:param reasoning_effort: Reasoning effort
|
||||
:param provider: When multiple model providers are available, optionally indicate your routing preference.
|
||||
:param plugins: Plugins you want to enable for this request, including their settings.
|
||||
:param retries: Override the default retry configuration for this method
|
||||
:param server_url: Override the default server URL for this method
|
||||
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
||||
:param http_headers: Additional headers to set or replace on requests.
|
||||
"""
|
||||
base_url = None
|
||||
url_variables = None
|
||||
if timeout_ms is None:
|
||||
timeout_ms = self.sdk_configuration.timeout_ms
|
||||
|
||||
if server_url is not None:
|
||||
base_url = server_url
|
||||
else:
|
||||
base_url = self._get_url(base_url, url_variables)
|
||||
|
||||
request = models.ChatStreamCompletionCreateParams(
|
||||
messages=utils.get_pydantic_model(
|
||||
messages, List[models.ChatCompletionMessageParam]
|
||||
),
|
||||
model=model,
|
||||
frequency_penalty=frequency_penalty,
|
||||
logit_bias=logit_bias,
|
||||
logprobs=logprobs,
|
||||
top_logprobs=top_logprobs,
|
||||
max_completion_tokens=max_completion_tokens,
|
||||
max_tokens=max_tokens,
|
||||
metadata=metadata,
|
||||
presence_penalty=presence_penalty,
|
||||
reasoning=utils.get_pydantic_model(
|
||||
reasoning,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsReasoning],
|
||||
),
|
||||
response_format=utils.get_pydantic_model(
|
||||
response_format,
|
||||
Optional[models.ChatStreamCompletionCreateParamsResponseFormatUnion],
|
||||
),
|
||||
seed=seed,
|
||||
stop=stop,
|
||||
stream=stream,
|
||||
stream_options=utils.get_pydantic_model(
|
||||
stream_options,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsStreamOptions],
|
||||
),
|
||||
temperature=temperature,
|
||||
tool_choice=utils.get_pydantic_model(
|
||||
tool_choice, Optional[models.ChatCompletionToolChoiceOption]
|
||||
),
|
||||
tools=utils.get_pydantic_model(
|
||||
tools, Optional[List[models.ChatCompletionTool]]
|
||||
),
|
||||
top_p=top_p,
|
||||
user=user,
|
||||
models_llm=models_llm,
|
||||
reasoning_effort=reasoning_effort,
|
||||
provider=utils.get_pydantic_model(
|
||||
provider,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsProvider],
|
||||
),
|
||||
plugins=utils.get_pydantic_model(
|
||||
plugins,
|
||||
Optional[List[models.ChatStreamCompletionCreateParamsPluginUnion]],
|
||||
),
|
||||
)
|
||||
|
||||
req = self._build_request(
|
||||
method="POST",
|
||||
path="/chat/completions#stream",
|
||||
base_url=base_url,
|
||||
url_variables=url_variables,
|
||||
request=request,
|
||||
request_body_required=True,
|
||||
request_has_path_params=False,
|
||||
request_has_query_params=True,
|
||||
user_agent_header="user-agent",
|
||||
accept_header_value="text/event-stream",
|
||||
http_headers=http_headers,
|
||||
security=self.sdk_configuration.security,
|
||||
get_serialized_body=lambda: utils.serialize_request_body(
|
||||
request, False, False, "json", models.ChatStreamCompletionCreateParams
|
||||
),
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
|
||||
if retries == UNSET:
|
||||
if self.sdk_configuration.retry_config is not UNSET:
|
||||
retries = self.sdk_configuration.retry_config
|
||||
|
||||
retry_config = None
|
||||
if isinstance(retries, utils.RetryConfig):
|
||||
retry_config = (retries, ["429", "500", "502", "503", "504"])
|
||||
|
||||
http_res = self.do_request(
|
||||
hook_ctx=HookContext(
|
||||
config=self.sdk_configuration,
|
||||
base_url=base_url or "",
|
||||
operation_id="streamChatCompletion",
|
||||
oauth2_scopes=[],
|
||||
security_source=get_security_from_env(
|
||||
self.sdk_configuration.security, models.Security
|
||||
),
|
||||
),
|
||||
request=req,
|
||||
error_status_codes=["400", "401", "429", "4XX", "500", "5XX"],
|
||||
stream=True,
|
||||
retry_config=retry_config,
|
||||
)
|
||||
|
||||
response_data: Any = None
|
||||
if utils.match_response(http_res, "200", "text/event-stream"):
|
||||
return eventstreaming.EventStream(
|
||||
http_res,
|
||||
lambda raw: utils.unmarshal_json(
|
||||
raw, models.StreamChatCompletionResponseBody
|
||||
),
|
||||
sentinel="[DONE]",
|
||||
)
|
||||
if utils.match_response(http_res, ["400", "401", "429"], "application/json"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res, http_res_text
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res, http_res_text)
|
||||
if utils.match_response(http_res, "500", "application/json"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res, http_res_text
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res, http_res_text)
|
||||
if utils.match_response(http_res, "4XX", "*"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
if utils.match_response(http_res, "5XX", "*"):
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
|
||||
http_res_text = utils.stream_to_text(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"Unexpected response received", http_res, http_res_text
|
||||
)
|
||||
|
||||
async def complete_stream_async(
|
||||
self,
|
||||
*,
|
||||
messages: Union[
|
||||
List[models.ChatCompletionMessageParam],
|
||||
List[models.ChatCompletionMessageParamTypedDict],
|
||||
],
|
||||
model: Optional[str] = None,
|
||||
frequency_penalty: OptionalNullable[float] = UNSET,
|
||||
logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
|
||||
logprobs: OptionalNullable[bool] = UNSET,
|
||||
top_logprobs: OptionalNullable[float] = UNSET,
|
||||
max_completion_tokens: OptionalNullable[float] = UNSET,
|
||||
max_tokens: OptionalNullable[float] = UNSET,
|
||||
metadata: Optional[Dict[str, str]] = None,
|
||||
presence_penalty: OptionalNullable[float] = UNSET,
|
||||
reasoning: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsReasoning,
|
||||
models.ChatStreamCompletionCreateParamsReasoningTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
response_format: Optional[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsResponseFormatUnion,
|
||||
models.ChatStreamCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
seed: OptionalNullable[int] = UNSET,
|
||||
stop: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsStop,
|
||||
models.ChatStreamCompletionCreateParamsStopTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
stream: Optional[bool] = True,
|
||||
stream_options: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsStreamOptions,
|
||||
models.ChatStreamCompletionCreateParamsStreamOptionsTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
temperature: OptionalNullable[float] = 1,
|
||||
tool_choice: Optional[
|
||||
Union[
|
||||
models.ChatCompletionToolChoiceOption,
|
||||
models.ChatCompletionToolChoiceOptionTypedDict,
|
||||
]
|
||||
] = None,
|
||||
tools: Optional[
|
||||
Union[
|
||||
List[models.ChatCompletionTool],
|
||||
List[models.ChatCompletionToolTypedDict],
|
||||
]
|
||||
] = None,
|
||||
top_p: OptionalNullable[float] = 1,
|
||||
user: Optional[str] = None,
|
||||
models_llm: OptionalNullable[List[str]] = UNSET,
|
||||
reasoning_effort: OptionalNullable[
|
||||
models.ChatStreamCompletionCreateParamsReasoningEffort
|
||||
] = UNSET,
|
||||
provider: OptionalNullable[
|
||||
Union[
|
||||
models.ChatStreamCompletionCreateParamsProvider,
|
||||
models.ChatStreamCompletionCreateParamsProviderTypedDict,
|
||||
]
|
||||
] = UNSET,
|
||||
plugins: Optional[
|
||||
Union[
|
||||
List[models.ChatStreamCompletionCreateParamsPluginUnion],
|
||||
List[models.ChatStreamCompletionCreateParamsPluginUnionTypedDict],
|
||||
]
|
||||
] = None,
|
||||
retries: OptionalNullable[utils.RetryConfig] = UNSET,
|
||||
server_url: Optional[str] = None,
|
||||
timeout_ms: Optional[int] = None,
|
||||
http_headers: Optional[Mapping[str, str]] = None,
|
||||
) -> eventstreaming.EventStreamAsync[models.StreamChatCompletionResponseBody]:
|
||||
r"""Create a chat completion
|
||||
|
||||
Creates a model response for the given chat conversation. Supports both streaming and non-streaming modes.
|
||||
|
||||
:param messages: List of messages for the conversation
|
||||
:param model: Model to use for completion
|
||||
:param frequency_penalty: Frequency penalty (-2.0 to 2.0)
|
||||
:param logit_bias: Token logit bias adjustments
|
||||
:param logprobs: Return log probabilities
|
||||
:param top_logprobs: Number of top log probabilities to return (0-20)
|
||||
:param max_completion_tokens: Maximum tokens in completion
|
||||
:param max_tokens: Maximum tokens (deprecated, use max_completion_tokens)
|
||||
:param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
|
||||
:param presence_penalty: Presence penalty (-2.0 to 2.0)
|
||||
:param reasoning: Reasoning configuration
|
||||
:param response_format: Response format configuration
|
||||
:param seed: Random seed for deterministic outputs
|
||||
:param stop: Stop sequences (up to 4)
|
||||
:param stream: Enable streaming response
|
||||
:param stream_options:
|
||||
:param temperature: Sampling temperature (0-2)
|
||||
:param tool_choice: Tool choice configuration
|
||||
:param tools: Available tools for function calling
|
||||
:param top_p: Nucleus sampling parameter (0-1)
|
||||
:param user: Unique user identifier
|
||||
:param models_llm: Order of models to fallback to for this request
|
||||
:param reasoning_effort: Reasoning effort
|
||||
:param provider: When multiple model providers are available, optionally indicate your routing preference.
|
||||
:param plugins: Plugins you want to enable for this request, including their settings.
|
||||
:param retries: Override the default retry configuration for this method
|
||||
:param server_url: Override the default server URL for this method
|
||||
:param timeout_ms: Override the default request timeout configuration for this method in milliseconds
|
||||
:param http_headers: Additional headers to set or replace on requests.
|
||||
"""
|
||||
base_url = None
|
||||
url_variables = None
|
||||
if timeout_ms is None:
|
||||
timeout_ms = self.sdk_configuration.timeout_ms
|
||||
|
||||
if server_url is not None:
|
||||
base_url = server_url
|
||||
else:
|
||||
base_url = self._get_url(base_url, url_variables)
|
||||
|
||||
request = models.ChatStreamCompletionCreateParams(
|
||||
messages=utils.get_pydantic_model(
|
||||
messages, List[models.ChatCompletionMessageParam]
|
||||
),
|
||||
model=model,
|
||||
frequency_penalty=frequency_penalty,
|
||||
logit_bias=logit_bias,
|
||||
logprobs=logprobs,
|
||||
top_logprobs=top_logprobs,
|
||||
max_completion_tokens=max_completion_tokens,
|
||||
max_tokens=max_tokens,
|
||||
metadata=metadata,
|
||||
presence_penalty=presence_penalty,
|
||||
reasoning=utils.get_pydantic_model(
|
||||
reasoning,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsReasoning],
|
||||
),
|
||||
response_format=utils.get_pydantic_model(
|
||||
response_format,
|
||||
Optional[models.ChatStreamCompletionCreateParamsResponseFormatUnion],
|
||||
),
|
||||
seed=seed,
|
||||
stop=stop,
|
||||
stream=stream,
|
||||
stream_options=utils.get_pydantic_model(
|
||||
stream_options,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsStreamOptions],
|
||||
),
|
||||
temperature=temperature,
|
||||
tool_choice=utils.get_pydantic_model(
|
||||
tool_choice, Optional[models.ChatCompletionToolChoiceOption]
|
||||
),
|
||||
tools=utils.get_pydantic_model(
|
||||
tools, Optional[List[models.ChatCompletionTool]]
|
||||
),
|
||||
top_p=top_p,
|
||||
user=user,
|
||||
models_llm=models_llm,
|
||||
reasoning_effort=reasoning_effort,
|
||||
provider=utils.get_pydantic_model(
|
||||
provider,
|
||||
OptionalNullable[models.ChatStreamCompletionCreateParamsProvider],
|
||||
),
|
||||
plugins=utils.get_pydantic_model(
|
||||
plugins,
|
||||
Optional[List[models.ChatStreamCompletionCreateParamsPluginUnion]],
|
||||
),
|
||||
)
|
||||
|
||||
req = self._build_request_async(
|
||||
method="POST",
|
||||
path="/chat/completions#stream",
|
||||
base_url=base_url,
|
||||
url_variables=url_variables,
|
||||
request=request,
|
||||
request_body_required=True,
|
||||
request_has_path_params=False,
|
||||
request_has_query_params=True,
|
||||
user_agent_header="user-agent",
|
||||
accept_header_value="text/event-stream",
|
||||
http_headers=http_headers,
|
||||
security=self.sdk_configuration.security,
|
||||
get_serialized_body=lambda: utils.serialize_request_body(
|
||||
request, False, False, "json", models.ChatStreamCompletionCreateParams
|
||||
),
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
|
||||
if retries == UNSET:
|
||||
if self.sdk_configuration.retry_config is not UNSET:
|
||||
retries = self.sdk_configuration.retry_config
|
||||
|
||||
retry_config = None
|
||||
if isinstance(retries, utils.RetryConfig):
|
||||
retry_config = (retries, ["429", "500", "502", "503", "504"])
|
||||
|
||||
http_res = await self.do_request_async(
|
||||
hook_ctx=HookContext(
|
||||
config=self.sdk_configuration,
|
||||
base_url=base_url or "",
|
||||
operation_id="streamChatCompletion",
|
||||
oauth2_scopes=[],
|
||||
security_source=get_security_from_env(
|
||||
self.sdk_configuration.security, models.Security
|
||||
),
|
||||
),
|
||||
request=req,
|
||||
error_status_codes=["400", "401", "429", "4XX", "500", "5XX"],
|
||||
stream=True,
|
||||
retry_config=retry_config,
|
||||
)
|
||||
|
||||
response_data: Any = None
|
||||
if utils.match_response(http_res, "200", "text/event-stream"):
|
||||
return eventstreaming.EventStreamAsync(
|
||||
http_res,
|
||||
lambda raw: utils.unmarshal_json(
|
||||
raw, models.StreamChatCompletionResponseBody
|
||||
),
|
||||
sentinel="[DONE]",
|
||||
)
|
||||
if utils.match_response(http_res, ["400", "401", "429"], "application/json"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res, http_res_text
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res, http_res_text)
|
||||
if utils.match_response(http_res, "500", "application/json"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
response_data = unmarshal_json_response(
|
||||
errors.ChatCompletionErrorData, http_res, http_res_text
|
||||
)
|
||||
raise errors.ChatCompletionError(response_data, http_res, http_res_text)
|
||||
if utils.match_response(http_res, "4XX", "*"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
if utils.match_response(http_res, "5XX", "*"):
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"API error occurred", http_res, http_res_text
|
||||
)
|
||||
|
||||
http_res_text = await utils.stream_to_text_async(http_res)
|
||||
raise errors.OpenRouterDefaultError(
|
||||
"Unexpected response received", http_res, http_res_text
|
||||
)
|
||||
@@ -0,0 +1,56 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from importlib import import_module
|
||||
import builtins
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .chatcompletionerror import ChatCompletionError, ChatCompletionErrorData
|
||||
from .no_response_error import NoResponseError
|
||||
from .openrouterdefaulterror import OpenRouterDefaultError
|
||||
from .openroutererror import OpenRouterError
|
||||
from .responsevalidationerror import ResponseValidationError
|
||||
|
||||
__all__ = [
|
||||
"ChatCompletionError",
|
||||
"ChatCompletionErrorData",
|
||||
"NoResponseError",
|
||||
"OpenRouterDefaultError",
|
||||
"OpenRouterError",
|
||||
"ResponseValidationError",
|
||||
]
|
||||
|
||||
_dynamic_imports: dict[str, str] = {
|
||||
"ChatCompletionError": ".chatcompletionerror",
|
||||
"ChatCompletionErrorData": ".chatcompletionerror",
|
||||
"NoResponseError": ".no_response_error",
|
||||
"OpenRouterDefaultError": ".openrouterdefaulterror",
|
||||
"OpenRouterError": ".openroutererror",
|
||||
"ResponseValidationError": ".responsevalidationerror",
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(attr_name: str) -> object:
|
||||
module_name = _dynamic_imports.get(attr_name)
|
||||
if module_name is None:
|
||||
raise AttributeError(
|
||||
f"No {attr_name} found in _dynamic_imports for module name -> {__name__} "
|
||||
)
|
||||
|
||||
try:
|
||||
module = import_module(module_name, __package__)
|
||||
result = getattr(module, attr_name)
|
||||
return result
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
f"Failed to import {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
except AttributeError as e:
|
||||
raise AttributeError(
|
||||
f"Failed to get {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
|
||||
|
||||
def __dir__():
|
||||
lazy_attrs = builtins.list(_dynamic_imports.keys())
|
||||
return builtins.sorted(lazy_attrs)
|
||||
@@ -0,0 +1,30 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
import httpx
|
||||
from openrouter.errors import OpenRouterError
|
||||
from openrouter.models import chatcompletionerror as models_chatcompletionerror
|
||||
from openrouter.types import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class ChatCompletionErrorData(BaseModel):
|
||||
error: models_chatcompletionerror.Error
|
||||
r"""Error object structure"""
|
||||
|
||||
|
||||
class ChatCompletionError(OpenRouterError):
|
||||
r"""Chat completion error response"""
|
||||
|
||||
data: ChatCompletionErrorData
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data: ChatCompletionErrorData,
|
||||
raw_response: httpx.Response,
|
||||
body: Optional[str] = None,
|
||||
):
|
||||
fallback = body or raw_response.text
|
||||
message = str(data.error.message) or fallback
|
||||
super().__init__(message, raw_response, body)
|
||||
self.data = data
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
class NoResponseError(Exception):
|
||||
"""Error raised when no HTTP response is received from the server."""
|
||||
|
||||
message: str
|
||||
|
||||
def __init__(self, message: str = "No response received"):
|
||||
self.message = message
|
||||
super().__init__(message)
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import httpx
|
||||
from typing import Optional
|
||||
|
||||
from openrouter.errors import OpenRouterError
|
||||
|
||||
MAX_MESSAGE_LEN = 10_000
|
||||
|
||||
|
||||
class OpenRouterDefaultError(OpenRouterError):
|
||||
"""The fallback error class if no more specific error class is matched."""
|
||||
|
||||
def __init__(
|
||||
self, message: str, raw_response: httpx.Response, body: Optional[str] = None
|
||||
):
|
||||
body_display = body or raw_response.text or '""'
|
||||
|
||||
if message:
|
||||
message += ": "
|
||||
message += f"Status {raw_response.status_code}"
|
||||
|
||||
headers = raw_response.headers
|
||||
content_type = headers.get("content-type", '""')
|
||||
if content_type != "application/json":
|
||||
if " " in content_type:
|
||||
content_type = f'"{content_type}"'
|
||||
message += f" Content-Type {content_type}"
|
||||
|
||||
if len(body_display) > MAX_MESSAGE_LEN:
|
||||
truncated = body_display[:MAX_MESSAGE_LEN]
|
||||
remaining = len(body_display) - MAX_MESSAGE_LEN
|
||||
body_display = f"{truncated}...and {remaining} more chars"
|
||||
|
||||
message += f". Body: {body_display}"
|
||||
message = message.strip()
|
||||
|
||||
super().__init__(message, raw_response, body)
|
||||
@@ -0,0 +1,26 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import httpx
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class OpenRouterError(Exception):
|
||||
"""The base class for all HTTP error responses."""
|
||||
|
||||
message: str
|
||||
status_code: int
|
||||
body: str
|
||||
headers: httpx.Headers
|
||||
raw_response: httpx.Response
|
||||
|
||||
def __init__(
|
||||
self, message: str, raw_response: httpx.Response, body: Optional[str] = None
|
||||
):
|
||||
self.message = message
|
||||
self.status_code = raw_response.status_code
|
||||
self.body = body if body is not None else raw_response.text
|
||||
self.headers = raw_response.headers
|
||||
self.raw_response = raw_response
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
@@ -0,0 +1,25 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import httpx
|
||||
from typing import Optional
|
||||
|
||||
from openrouter.errors import OpenRouterError
|
||||
|
||||
|
||||
class ResponseValidationError(OpenRouterError):
|
||||
"""Error raised when there is a type mismatch between the response data and the expected Pydantic model."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
raw_response: httpx.Response,
|
||||
cause: Exception,
|
||||
body: Optional[str] = None,
|
||||
):
|
||||
message = f"{message}: {cause}"
|
||||
super().__init__(message, raw_response, body)
|
||||
|
||||
@property
|
||||
def cause(self):
|
||||
"""Normally the Pydantic ValidationError"""
|
||||
return self.__cause__
|
||||
@@ -0,0 +1,126 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
# pyright: reportReturnType = false
|
||||
import asyncio
|
||||
from typing_extensions import Protocol, runtime_checkable
|
||||
import httpx
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class HttpClient(Protocol):
|
||||
def send(
|
||||
self,
|
||||
request: httpx.Request,
|
||||
*,
|
||||
stream: bool = False,
|
||||
auth: Union[
|
||||
httpx._types.AuthTypes, httpx._client.UseClientDefault, None
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
follow_redirects: Union[
|
||||
bool, httpx._client.UseClientDefault
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
) -> httpx.Response:
|
||||
pass
|
||||
|
||||
def build_request(
|
||||
self,
|
||||
method: str,
|
||||
url: httpx._types.URLTypes,
|
||||
*,
|
||||
content: Optional[httpx._types.RequestContent] = None,
|
||||
data: Optional[httpx._types.RequestData] = None,
|
||||
files: Optional[httpx._types.RequestFiles] = None,
|
||||
json: Optional[Any] = None,
|
||||
params: Optional[httpx._types.QueryParamTypes] = None,
|
||||
headers: Optional[httpx._types.HeaderTypes] = None,
|
||||
cookies: Optional[httpx._types.CookieTypes] = None,
|
||||
timeout: Union[
|
||||
httpx._types.TimeoutTypes, httpx._client.UseClientDefault
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
extensions: Optional[httpx._types.RequestExtensions] = None,
|
||||
) -> httpx.Request:
|
||||
pass
|
||||
|
||||
def close(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class AsyncHttpClient(Protocol):
|
||||
async def send(
|
||||
self,
|
||||
request: httpx.Request,
|
||||
*,
|
||||
stream: bool = False,
|
||||
auth: Union[
|
||||
httpx._types.AuthTypes, httpx._client.UseClientDefault, None
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
follow_redirects: Union[
|
||||
bool, httpx._client.UseClientDefault
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
) -> httpx.Response:
|
||||
pass
|
||||
|
||||
def build_request(
|
||||
self,
|
||||
method: str,
|
||||
url: httpx._types.URLTypes,
|
||||
*,
|
||||
content: Optional[httpx._types.RequestContent] = None,
|
||||
data: Optional[httpx._types.RequestData] = None,
|
||||
files: Optional[httpx._types.RequestFiles] = None,
|
||||
json: Optional[Any] = None,
|
||||
params: Optional[httpx._types.QueryParamTypes] = None,
|
||||
headers: Optional[httpx._types.HeaderTypes] = None,
|
||||
cookies: Optional[httpx._types.CookieTypes] = None,
|
||||
timeout: Union[
|
||||
httpx._types.TimeoutTypes, httpx._client.UseClientDefault
|
||||
] = httpx.USE_CLIENT_DEFAULT,
|
||||
extensions: Optional[httpx._types.RequestExtensions] = None,
|
||||
) -> httpx.Request:
|
||||
pass
|
||||
|
||||
async def aclose(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class ClientOwner(Protocol):
|
||||
client: Union[HttpClient, None]
|
||||
async_client: Union[AsyncHttpClient, None]
|
||||
|
||||
|
||||
def close_clients(
|
||||
owner: ClientOwner,
|
||||
sync_client: Union[HttpClient, None],
|
||||
sync_client_supplied: bool,
|
||||
async_client: Union[AsyncHttpClient, None],
|
||||
async_client_supplied: bool,
|
||||
) -> None:
|
||||
"""
|
||||
A finalizer function that is meant to be used with weakref.finalize to close
|
||||
httpx clients used by an SDK so that underlying resources can be garbage
|
||||
collected.
|
||||
"""
|
||||
|
||||
# Unset the client/async_client properties so there are no more references
|
||||
# to them from the owning SDK instance and they can be reaped.
|
||||
owner.client = None
|
||||
owner.async_client = None
|
||||
|
||||
if sync_client is not None and not sync_client_supplied:
|
||||
try:
|
||||
sync_client.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if async_client is not None and not async_client_supplied:
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
asyncio.run_coroutine_threadsafe(async_client.aclose(), loop)
|
||||
except RuntimeError:
|
||||
try:
|
||||
asyncio.run(async_client.aclose())
|
||||
except RuntimeError:
|
||||
# best effort
|
||||
pass
|
||||
@@ -0,0 +1,957 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from importlib import import_module
|
||||
import builtins
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .annotationdetail import AnnotationDetail, AnnotationDetailTypedDict
|
||||
from .chatcompletion import (
|
||||
ChatCompletion,
|
||||
ChatCompletionObject,
|
||||
ChatCompletionTypedDict,
|
||||
)
|
||||
from .chatcompletionassistantmessageparam import (
|
||||
ChatCompletionAssistantMessageParam,
|
||||
ChatCompletionAssistantMessageParamContent,
|
||||
ChatCompletionAssistantMessageParamContentTypedDict,
|
||||
ChatCompletionAssistantMessageParamRole,
|
||||
ChatCompletionAssistantMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletionchoice import (
|
||||
ChatCompletionChoice,
|
||||
ChatCompletionChoiceFinishReason,
|
||||
ChatCompletionChoiceTypedDict,
|
||||
)
|
||||
from .chatcompletionchunk import (
|
||||
ChatCompletionChunk,
|
||||
ChatCompletionChunkObject,
|
||||
ChatCompletionChunkTypedDict,
|
||||
)
|
||||
from .chatcompletionchunkchoice import (
|
||||
ChatCompletionChunkChoice,
|
||||
ChatCompletionChunkChoiceFinishReason,
|
||||
ChatCompletionChunkChoiceTypedDict,
|
||||
)
|
||||
from .chatcompletionchunkchoicedelta import (
|
||||
ChatCompletionChunkChoiceDelta,
|
||||
ChatCompletionChunkChoiceDeltaRole,
|
||||
ChatCompletionChunkChoiceDeltaTypedDict,
|
||||
)
|
||||
from .chatcompletionchunkchoicedeltatoolcall import (
|
||||
ChatCompletionChunkChoiceDeltaToolCall,
|
||||
ChatCompletionChunkChoiceDeltaToolCallFunction,
|
||||
ChatCompletionChunkChoiceDeltaToolCallFunctionTypedDict,
|
||||
ChatCompletionChunkChoiceDeltaToolCallType,
|
||||
ChatCompletionChunkChoiceDeltaToolCallTypedDict,
|
||||
)
|
||||
from .chatcompletioncontentpart import (
|
||||
ChatCompletionContentPart,
|
||||
ChatCompletionContentPartTypedDict,
|
||||
)
|
||||
from .chatcompletioncontentpartaudio import (
|
||||
ChatCompletionContentPartAudio,
|
||||
ChatCompletionContentPartAudioFormat,
|
||||
ChatCompletionContentPartAudioType,
|
||||
ChatCompletionContentPartAudioTypedDict,
|
||||
InputAudio,
|
||||
InputAudioTypedDict,
|
||||
)
|
||||
from .chatcompletioncontentpartimage import (
|
||||
ChatCompletionContentPartImage,
|
||||
ChatCompletionContentPartImageImageURL,
|
||||
ChatCompletionContentPartImageImageURLTypedDict,
|
||||
ChatCompletionContentPartImageType,
|
||||
ChatCompletionContentPartImageTypedDict,
|
||||
Detail,
|
||||
)
|
||||
from .chatcompletioncontentparttext import (
|
||||
ChatCompletionContentPartText,
|
||||
ChatCompletionContentPartTextType,
|
||||
ChatCompletionContentPartTextTypedDict,
|
||||
)
|
||||
from .chatcompletioncreateparams import (
|
||||
ChatCompletionCreateParams,
|
||||
ChatCompletionCreateParamsAudio,
|
||||
ChatCompletionCreateParamsAudioTypedDict,
|
||||
ChatCompletionCreateParamsCompletion,
|
||||
ChatCompletionCreateParamsCompletionTypedDict,
|
||||
ChatCompletionCreateParamsDataCollection,
|
||||
ChatCompletionCreateParamsEffort,
|
||||
ChatCompletionCreateParamsEngine,
|
||||
ChatCompletionCreateParamsIDChainOfThought,
|
||||
ChatCompletionCreateParamsIDFileParser,
|
||||
ChatCompletionCreateParamsIDModeration,
|
||||
ChatCompletionCreateParamsIDWeb,
|
||||
ChatCompletionCreateParamsIgnoreEnum,
|
||||
ChatCompletionCreateParamsIgnoreUnion,
|
||||
ChatCompletionCreateParamsIgnoreUnionTypedDict,
|
||||
ChatCompletionCreateParamsImage,
|
||||
ChatCompletionCreateParamsImageTypedDict,
|
||||
ChatCompletionCreateParamsJSONSchema,
|
||||
ChatCompletionCreateParamsJSONSchemaTypedDict,
|
||||
ChatCompletionCreateParamsMaxPrice,
|
||||
ChatCompletionCreateParamsMaxPriceTypedDict,
|
||||
ChatCompletionCreateParamsOnlyEnum,
|
||||
ChatCompletionCreateParamsOnlyUnion,
|
||||
ChatCompletionCreateParamsOnlyUnionTypedDict,
|
||||
ChatCompletionCreateParamsOrderEnum,
|
||||
ChatCompletionCreateParamsOrderUnion,
|
||||
ChatCompletionCreateParamsOrderUnionTypedDict,
|
||||
ChatCompletionCreateParamsPdf,
|
||||
ChatCompletionCreateParamsPdfEngine,
|
||||
ChatCompletionCreateParamsPdfTypedDict,
|
||||
ChatCompletionCreateParamsPluginChainOfThought,
|
||||
ChatCompletionCreateParamsPluginChainOfThoughtTypedDict,
|
||||
ChatCompletionCreateParamsPluginFileParser,
|
||||
ChatCompletionCreateParamsPluginFileParserTypedDict,
|
||||
ChatCompletionCreateParamsPluginModeration,
|
||||
ChatCompletionCreateParamsPluginModerationTypedDict,
|
||||
ChatCompletionCreateParamsPluginUnion,
|
||||
ChatCompletionCreateParamsPluginUnionTypedDict,
|
||||
ChatCompletionCreateParamsPluginWeb,
|
||||
ChatCompletionCreateParamsPluginWebTypedDict,
|
||||
ChatCompletionCreateParamsPrompt,
|
||||
ChatCompletionCreateParamsPromptTypedDict,
|
||||
ChatCompletionCreateParamsProvider,
|
||||
ChatCompletionCreateParamsProviderTypedDict,
|
||||
ChatCompletionCreateParamsQuantization,
|
||||
ChatCompletionCreateParamsReasoning,
|
||||
ChatCompletionCreateParamsReasoningEffort,
|
||||
ChatCompletionCreateParamsReasoningTypedDict,
|
||||
ChatCompletionCreateParamsRequest,
|
||||
ChatCompletionCreateParamsRequestTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatGrammar,
|
||||
ChatCompletionCreateParamsResponseFormatGrammarTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatJSONObject,
|
||||
ChatCompletionCreateParamsResponseFormatJSONObjectTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatJSONSchema,
|
||||
ChatCompletionCreateParamsResponseFormatJSONSchemaTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatPython,
|
||||
ChatCompletionCreateParamsResponseFormatPythonTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatText,
|
||||
ChatCompletionCreateParamsResponseFormatTextTypedDict,
|
||||
ChatCompletionCreateParamsResponseFormatUnion,
|
||||
ChatCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
ChatCompletionCreateParamsSort,
|
||||
ChatCompletionCreateParamsStop,
|
||||
ChatCompletionCreateParamsStopTypedDict,
|
||||
ChatCompletionCreateParamsStreamOptions,
|
||||
ChatCompletionCreateParamsStreamOptionsTypedDict,
|
||||
ChatCompletionCreateParamsTypeGrammar,
|
||||
ChatCompletionCreateParamsTypeJSONObject,
|
||||
ChatCompletionCreateParamsTypeJSONSchema,
|
||||
ChatCompletionCreateParamsTypePython,
|
||||
ChatCompletionCreateParamsTypeText,
|
||||
ChatCompletionCreateParamsTypedDict,
|
||||
)
|
||||
from .chatcompletionerror import Error, ErrorTypedDict
|
||||
from .chatcompletionmessage import (
|
||||
ChatCompletionMessage,
|
||||
ChatCompletionMessageRole,
|
||||
ChatCompletionMessageTypedDict,
|
||||
)
|
||||
from .chatcompletionmessageparam import (
|
||||
ChatCompletionMessageParam,
|
||||
ChatCompletionMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletionmessagetoolcall import (
|
||||
ChatCompletionMessageToolCall,
|
||||
ChatCompletionMessageToolCallFunction,
|
||||
ChatCompletionMessageToolCallFunctionTypedDict,
|
||||
ChatCompletionMessageToolCallType,
|
||||
ChatCompletionMessageToolCallTypedDict,
|
||||
)
|
||||
from .chatcompletionnamedtoolchoice import (
|
||||
ChatCompletionNamedToolChoice,
|
||||
ChatCompletionNamedToolChoiceFunction,
|
||||
ChatCompletionNamedToolChoiceFunctionTypedDict,
|
||||
ChatCompletionNamedToolChoiceType,
|
||||
ChatCompletionNamedToolChoiceTypedDict,
|
||||
)
|
||||
from .chatcompletionsystemmessageparam import (
|
||||
ChatCompletionSystemMessageParam,
|
||||
ChatCompletionSystemMessageParamContent,
|
||||
ChatCompletionSystemMessageParamContentTypedDict,
|
||||
ChatCompletionSystemMessageParamRole,
|
||||
ChatCompletionSystemMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletiontokenlogprob import (
|
||||
ChatCompletionTokenLogprob,
|
||||
ChatCompletionTokenLogprobTypedDict,
|
||||
TopLogprob,
|
||||
TopLogprobTypedDict,
|
||||
)
|
||||
from .chatcompletiontokenlogprobs import (
|
||||
ChatCompletionTokenLogprobs,
|
||||
ChatCompletionTokenLogprobsTypedDict,
|
||||
)
|
||||
from .chatcompletiontool import (
|
||||
ChatCompletionTool,
|
||||
ChatCompletionToolFunction,
|
||||
ChatCompletionToolFunctionTypedDict,
|
||||
ChatCompletionToolType,
|
||||
ChatCompletionToolTypedDict,
|
||||
Parameters,
|
||||
ParametersTypedDict,
|
||||
)
|
||||
from .chatcompletiontoolchoiceoption import (
|
||||
ChatCompletionToolChoiceOption,
|
||||
ChatCompletionToolChoiceOptionAuto,
|
||||
ChatCompletionToolChoiceOptionNone,
|
||||
ChatCompletionToolChoiceOptionRequired,
|
||||
ChatCompletionToolChoiceOptionTypedDict,
|
||||
)
|
||||
from .chatcompletiontoolmessageparam import (
|
||||
ChatCompletionToolMessageParam,
|
||||
ChatCompletionToolMessageParamContent,
|
||||
ChatCompletionToolMessageParamContentTypedDict,
|
||||
ChatCompletionToolMessageParamRole,
|
||||
ChatCompletionToolMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletionusermessageparam import (
|
||||
ChatCompletionUserMessageParam,
|
||||
ChatCompletionUserMessageParamContent,
|
||||
ChatCompletionUserMessageParamContentTypedDict,
|
||||
ChatCompletionUserMessageParamRole,
|
||||
ChatCompletionUserMessageParamTypedDict,
|
||||
)
|
||||
from .chatstreamcompletioncreateparams import (
|
||||
ChatStreamCompletionCreateParams,
|
||||
ChatStreamCompletionCreateParamsAudio,
|
||||
ChatStreamCompletionCreateParamsAudioTypedDict,
|
||||
ChatStreamCompletionCreateParamsCompletion,
|
||||
ChatStreamCompletionCreateParamsCompletionTypedDict,
|
||||
ChatStreamCompletionCreateParamsDataCollection,
|
||||
ChatStreamCompletionCreateParamsEffort,
|
||||
ChatStreamCompletionCreateParamsEngine,
|
||||
ChatStreamCompletionCreateParamsIDChainOfThought,
|
||||
ChatStreamCompletionCreateParamsIDFileParser,
|
||||
ChatStreamCompletionCreateParamsIDModeration,
|
||||
ChatStreamCompletionCreateParamsIDWeb,
|
||||
ChatStreamCompletionCreateParamsIgnoreEnum,
|
||||
ChatStreamCompletionCreateParamsIgnoreUnion,
|
||||
ChatStreamCompletionCreateParamsIgnoreUnionTypedDict,
|
||||
ChatStreamCompletionCreateParamsImage,
|
||||
ChatStreamCompletionCreateParamsImageTypedDict,
|
||||
ChatStreamCompletionCreateParamsJSONSchema,
|
||||
ChatStreamCompletionCreateParamsJSONSchemaTypedDict,
|
||||
ChatStreamCompletionCreateParamsMaxPrice,
|
||||
ChatStreamCompletionCreateParamsMaxPriceTypedDict,
|
||||
ChatStreamCompletionCreateParamsOnlyEnum,
|
||||
ChatStreamCompletionCreateParamsOnlyUnion,
|
||||
ChatStreamCompletionCreateParamsOnlyUnionTypedDict,
|
||||
ChatStreamCompletionCreateParamsOrderEnum,
|
||||
ChatStreamCompletionCreateParamsOrderUnion,
|
||||
ChatStreamCompletionCreateParamsOrderUnionTypedDict,
|
||||
ChatStreamCompletionCreateParamsPdf,
|
||||
ChatStreamCompletionCreateParamsPdfEngine,
|
||||
ChatStreamCompletionCreateParamsPdfTypedDict,
|
||||
ChatStreamCompletionCreateParamsPluginChainOfThought,
|
||||
ChatStreamCompletionCreateParamsPluginChainOfThoughtTypedDict,
|
||||
ChatStreamCompletionCreateParamsPluginFileParser,
|
||||
ChatStreamCompletionCreateParamsPluginFileParserTypedDict,
|
||||
ChatStreamCompletionCreateParamsPluginModeration,
|
||||
ChatStreamCompletionCreateParamsPluginModerationTypedDict,
|
||||
ChatStreamCompletionCreateParamsPluginUnion,
|
||||
ChatStreamCompletionCreateParamsPluginUnionTypedDict,
|
||||
ChatStreamCompletionCreateParamsPluginWeb,
|
||||
ChatStreamCompletionCreateParamsPluginWebTypedDict,
|
||||
ChatStreamCompletionCreateParamsPrompt,
|
||||
ChatStreamCompletionCreateParamsPromptTypedDict,
|
||||
ChatStreamCompletionCreateParamsProvider,
|
||||
ChatStreamCompletionCreateParamsProviderTypedDict,
|
||||
ChatStreamCompletionCreateParamsQuantization,
|
||||
ChatStreamCompletionCreateParamsReasoning,
|
||||
ChatStreamCompletionCreateParamsReasoningEffort,
|
||||
ChatStreamCompletionCreateParamsReasoningTypedDict,
|
||||
ChatStreamCompletionCreateParamsRequest,
|
||||
ChatStreamCompletionCreateParamsRequestTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatGrammar,
|
||||
ChatStreamCompletionCreateParamsResponseFormatGrammarTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatJSONObject,
|
||||
ChatStreamCompletionCreateParamsResponseFormatJSONObjectTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatJSONSchema,
|
||||
ChatStreamCompletionCreateParamsResponseFormatJSONSchemaTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatPython,
|
||||
ChatStreamCompletionCreateParamsResponseFormatPythonTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatText,
|
||||
ChatStreamCompletionCreateParamsResponseFormatTextTypedDict,
|
||||
ChatStreamCompletionCreateParamsResponseFormatUnion,
|
||||
ChatStreamCompletionCreateParamsResponseFormatUnionTypedDict,
|
||||
ChatStreamCompletionCreateParamsSort,
|
||||
ChatStreamCompletionCreateParamsStop,
|
||||
ChatStreamCompletionCreateParamsStopTypedDict,
|
||||
ChatStreamCompletionCreateParamsStreamOptions,
|
||||
ChatStreamCompletionCreateParamsStreamOptionsTypedDict,
|
||||
ChatStreamCompletionCreateParamsTypeGrammar,
|
||||
ChatStreamCompletionCreateParamsTypeJSONObject,
|
||||
ChatStreamCompletionCreateParamsTypeJSONSchema,
|
||||
ChatStreamCompletionCreateParamsTypePython,
|
||||
ChatStreamCompletionCreateParamsTypeText,
|
||||
ChatStreamCompletionCreateParamsTypedDict,
|
||||
)
|
||||
from .completionusage import (
|
||||
CompletionTokensDetails,
|
||||
CompletionTokensDetailsTypedDict,
|
||||
CompletionUsage,
|
||||
CompletionUsageTypedDict,
|
||||
PromptTokensDetails,
|
||||
PromptTokensDetailsTypedDict,
|
||||
)
|
||||
from .fileannotationdetail import (
|
||||
ContentImageURL,
|
||||
ContentImageURLTypedDict,
|
||||
ContentText,
|
||||
ContentTextTypedDict,
|
||||
ContentTypeImageURL,
|
||||
ContentTypeText,
|
||||
File,
|
||||
FileAnnotationDetail,
|
||||
FileAnnotationDetailContentUnion,
|
||||
FileAnnotationDetailContentUnionTypedDict,
|
||||
FileAnnotationDetailImageURL,
|
||||
FileAnnotationDetailImageURLTypedDict,
|
||||
FileAnnotationDetailTypedDict,
|
||||
FileTypedDict,
|
||||
TypeFile,
|
||||
)
|
||||
from .reasoningdetail import ReasoningDetail, ReasoningDetailTypedDict
|
||||
from .reasoningdetailencrypted import (
|
||||
ReasoningDetailEncrypted,
|
||||
ReasoningDetailEncryptedFormat,
|
||||
ReasoningDetailEncryptedType,
|
||||
ReasoningDetailEncryptedTypedDict,
|
||||
)
|
||||
from .reasoningdetailsummary import (
|
||||
ReasoningDetailSummary,
|
||||
ReasoningDetailSummaryFormat,
|
||||
ReasoningDetailSummaryType,
|
||||
ReasoningDetailSummaryTypedDict,
|
||||
)
|
||||
from .reasoningdetailtext import (
|
||||
ReasoningDetailText,
|
||||
ReasoningDetailTextFormat,
|
||||
ReasoningDetailTextType,
|
||||
ReasoningDetailTextTypedDict,
|
||||
)
|
||||
from .responseformatjsonschemaschema import (
|
||||
ResponseFormatJSONSchemaSchema,
|
||||
ResponseFormatJSONSchemaSchemaTypedDict,
|
||||
)
|
||||
from .security import Security, SecurityTypedDict
|
||||
from .streamchatcompletionop import (
|
||||
StreamChatCompletionResponseBody,
|
||||
StreamChatCompletionResponseBodyTypedDict,
|
||||
)
|
||||
from .urlcitationannotationdetail import (
|
||||
URLCitation,
|
||||
URLCitationAnnotationDetail,
|
||||
URLCitationAnnotationDetailType,
|
||||
URLCitationAnnotationDetailTypedDict,
|
||||
URLCitationTypedDict,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"AnnotationDetail",
|
||||
"AnnotationDetailTypedDict",
|
||||
"ChatCompletion",
|
||||
"ChatCompletionAssistantMessageParam",
|
||||
"ChatCompletionAssistantMessageParamContent",
|
||||
"ChatCompletionAssistantMessageParamContentTypedDict",
|
||||
"ChatCompletionAssistantMessageParamRole",
|
||||
"ChatCompletionAssistantMessageParamTypedDict",
|
||||
"ChatCompletionChoice",
|
||||
"ChatCompletionChoiceFinishReason",
|
||||
"ChatCompletionChoiceTypedDict",
|
||||
"ChatCompletionChunk",
|
||||
"ChatCompletionChunkChoice",
|
||||
"ChatCompletionChunkChoiceDelta",
|
||||
"ChatCompletionChunkChoiceDeltaRole",
|
||||
"ChatCompletionChunkChoiceDeltaToolCall",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallFunction",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallFunctionTypedDict",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallType",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallTypedDict",
|
||||
"ChatCompletionChunkChoiceDeltaTypedDict",
|
||||
"ChatCompletionChunkChoiceFinishReason",
|
||||
"ChatCompletionChunkChoiceTypedDict",
|
||||
"ChatCompletionChunkObject",
|
||||
"ChatCompletionChunkTypedDict",
|
||||
"ChatCompletionContentPart",
|
||||
"ChatCompletionContentPartAudio",
|
||||
"ChatCompletionContentPartAudioFormat",
|
||||
"ChatCompletionContentPartAudioType",
|
||||
"ChatCompletionContentPartAudioTypedDict",
|
||||
"ChatCompletionContentPartImage",
|
||||
"ChatCompletionContentPartImageImageURL",
|
||||
"ChatCompletionContentPartImageImageURLTypedDict",
|
||||
"ChatCompletionContentPartImageType",
|
||||
"ChatCompletionContentPartImageTypedDict",
|
||||
"ChatCompletionContentPartText",
|
||||
"ChatCompletionContentPartTextType",
|
||||
"ChatCompletionContentPartTextTypedDict",
|
||||
"ChatCompletionContentPartTypedDict",
|
||||
"ChatCompletionCreateParams",
|
||||
"ChatCompletionCreateParamsAudio",
|
||||
"ChatCompletionCreateParamsAudioTypedDict",
|
||||
"ChatCompletionCreateParamsCompletion",
|
||||
"ChatCompletionCreateParamsCompletionTypedDict",
|
||||
"ChatCompletionCreateParamsDataCollection",
|
||||
"ChatCompletionCreateParamsEffort",
|
||||
"ChatCompletionCreateParamsEngine",
|
||||
"ChatCompletionCreateParamsIDChainOfThought",
|
||||
"ChatCompletionCreateParamsIDFileParser",
|
||||
"ChatCompletionCreateParamsIDModeration",
|
||||
"ChatCompletionCreateParamsIDWeb",
|
||||
"ChatCompletionCreateParamsIgnoreEnum",
|
||||
"ChatCompletionCreateParamsIgnoreUnion",
|
||||
"ChatCompletionCreateParamsIgnoreUnionTypedDict",
|
||||
"ChatCompletionCreateParamsImage",
|
||||
"ChatCompletionCreateParamsImageTypedDict",
|
||||
"ChatCompletionCreateParamsJSONSchema",
|
||||
"ChatCompletionCreateParamsJSONSchemaTypedDict",
|
||||
"ChatCompletionCreateParamsMaxPrice",
|
||||
"ChatCompletionCreateParamsMaxPriceTypedDict",
|
||||
"ChatCompletionCreateParamsOnlyEnum",
|
||||
"ChatCompletionCreateParamsOnlyUnion",
|
||||
"ChatCompletionCreateParamsOnlyUnionTypedDict",
|
||||
"ChatCompletionCreateParamsOrderEnum",
|
||||
"ChatCompletionCreateParamsOrderUnion",
|
||||
"ChatCompletionCreateParamsOrderUnionTypedDict",
|
||||
"ChatCompletionCreateParamsPdf",
|
||||
"ChatCompletionCreateParamsPdfEngine",
|
||||
"ChatCompletionCreateParamsPdfTypedDict",
|
||||
"ChatCompletionCreateParamsPluginChainOfThought",
|
||||
"ChatCompletionCreateParamsPluginChainOfThoughtTypedDict",
|
||||
"ChatCompletionCreateParamsPluginFileParser",
|
||||
"ChatCompletionCreateParamsPluginFileParserTypedDict",
|
||||
"ChatCompletionCreateParamsPluginModeration",
|
||||
"ChatCompletionCreateParamsPluginModerationTypedDict",
|
||||
"ChatCompletionCreateParamsPluginUnion",
|
||||
"ChatCompletionCreateParamsPluginUnionTypedDict",
|
||||
"ChatCompletionCreateParamsPluginWeb",
|
||||
"ChatCompletionCreateParamsPluginWebTypedDict",
|
||||
"ChatCompletionCreateParamsPrompt",
|
||||
"ChatCompletionCreateParamsPromptTypedDict",
|
||||
"ChatCompletionCreateParamsProvider",
|
||||
"ChatCompletionCreateParamsProviderTypedDict",
|
||||
"ChatCompletionCreateParamsQuantization",
|
||||
"ChatCompletionCreateParamsReasoning",
|
||||
"ChatCompletionCreateParamsReasoningEffort",
|
||||
"ChatCompletionCreateParamsReasoningTypedDict",
|
||||
"ChatCompletionCreateParamsRequest",
|
||||
"ChatCompletionCreateParamsRequestTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatGrammar",
|
||||
"ChatCompletionCreateParamsResponseFormatGrammarTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONObject",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONObjectTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONSchema",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONSchemaTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatPython",
|
||||
"ChatCompletionCreateParamsResponseFormatPythonTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatText",
|
||||
"ChatCompletionCreateParamsResponseFormatTextTypedDict",
|
||||
"ChatCompletionCreateParamsResponseFormatUnion",
|
||||
"ChatCompletionCreateParamsResponseFormatUnionTypedDict",
|
||||
"ChatCompletionCreateParamsSort",
|
||||
"ChatCompletionCreateParamsStop",
|
||||
"ChatCompletionCreateParamsStopTypedDict",
|
||||
"ChatCompletionCreateParamsStreamOptions",
|
||||
"ChatCompletionCreateParamsStreamOptionsTypedDict",
|
||||
"ChatCompletionCreateParamsTypeGrammar",
|
||||
"ChatCompletionCreateParamsTypeJSONObject",
|
||||
"ChatCompletionCreateParamsTypeJSONSchema",
|
||||
"ChatCompletionCreateParamsTypePython",
|
||||
"ChatCompletionCreateParamsTypeText",
|
||||
"ChatCompletionCreateParamsTypedDict",
|
||||
"ChatCompletionMessage",
|
||||
"ChatCompletionMessageParam",
|
||||
"ChatCompletionMessageParamTypedDict",
|
||||
"ChatCompletionMessageRole",
|
||||
"ChatCompletionMessageToolCall",
|
||||
"ChatCompletionMessageToolCallFunction",
|
||||
"ChatCompletionMessageToolCallFunctionTypedDict",
|
||||
"ChatCompletionMessageToolCallType",
|
||||
"ChatCompletionMessageToolCallTypedDict",
|
||||
"ChatCompletionMessageTypedDict",
|
||||
"ChatCompletionNamedToolChoice",
|
||||
"ChatCompletionNamedToolChoiceFunction",
|
||||
"ChatCompletionNamedToolChoiceFunctionTypedDict",
|
||||
"ChatCompletionNamedToolChoiceType",
|
||||
"ChatCompletionNamedToolChoiceTypedDict",
|
||||
"ChatCompletionObject",
|
||||
"ChatCompletionSystemMessageParam",
|
||||
"ChatCompletionSystemMessageParamContent",
|
||||
"ChatCompletionSystemMessageParamContentTypedDict",
|
||||
"ChatCompletionSystemMessageParamRole",
|
||||
"ChatCompletionSystemMessageParamTypedDict",
|
||||
"ChatCompletionTokenLogprob",
|
||||
"ChatCompletionTokenLogprobTypedDict",
|
||||
"ChatCompletionTokenLogprobs",
|
||||
"ChatCompletionTokenLogprobsTypedDict",
|
||||
"ChatCompletionTool",
|
||||
"ChatCompletionToolChoiceOption",
|
||||
"ChatCompletionToolChoiceOptionAuto",
|
||||
"ChatCompletionToolChoiceOptionNone",
|
||||
"ChatCompletionToolChoiceOptionRequired",
|
||||
"ChatCompletionToolChoiceOptionTypedDict",
|
||||
"ChatCompletionToolFunction",
|
||||
"ChatCompletionToolFunctionTypedDict",
|
||||
"ChatCompletionToolMessageParam",
|
||||
"ChatCompletionToolMessageParamContent",
|
||||
"ChatCompletionToolMessageParamContentTypedDict",
|
||||
"ChatCompletionToolMessageParamRole",
|
||||
"ChatCompletionToolMessageParamTypedDict",
|
||||
"ChatCompletionToolType",
|
||||
"ChatCompletionToolTypedDict",
|
||||
"ChatCompletionTypedDict",
|
||||
"ChatCompletionUserMessageParam",
|
||||
"ChatCompletionUserMessageParamContent",
|
||||
"ChatCompletionUserMessageParamContentTypedDict",
|
||||
"ChatCompletionUserMessageParamRole",
|
||||
"ChatCompletionUserMessageParamTypedDict",
|
||||
"ChatStreamCompletionCreateParams",
|
||||
"ChatStreamCompletionCreateParamsAudio",
|
||||
"ChatStreamCompletionCreateParamsAudioTypedDict",
|
||||
"ChatStreamCompletionCreateParamsCompletion",
|
||||
"ChatStreamCompletionCreateParamsCompletionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsDataCollection",
|
||||
"ChatStreamCompletionCreateParamsEffort",
|
||||
"ChatStreamCompletionCreateParamsEngine",
|
||||
"ChatStreamCompletionCreateParamsIDChainOfThought",
|
||||
"ChatStreamCompletionCreateParamsIDFileParser",
|
||||
"ChatStreamCompletionCreateParamsIDModeration",
|
||||
"ChatStreamCompletionCreateParamsIDWeb",
|
||||
"ChatStreamCompletionCreateParamsIgnoreEnum",
|
||||
"ChatStreamCompletionCreateParamsIgnoreUnion",
|
||||
"ChatStreamCompletionCreateParamsIgnoreUnionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsImage",
|
||||
"ChatStreamCompletionCreateParamsImageTypedDict",
|
||||
"ChatStreamCompletionCreateParamsJSONSchema",
|
||||
"ChatStreamCompletionCreateParamsJSONSchemaTypedDict",
|
||||
"ChatStreamCompletionCreateParamsMaxPrice",
|
||||
"ChatStreamCompletionCreateParamsMaxPriceTypedDict",
|
||||
"ChatStreamCompletionCreateParamsOnlyEnum",
|
||||
"ChatStreamCompletionCreateParamsOnlyUnion",
|
||||
"ChatStreamCompletionCreateParamsOnlyUnionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsOrderEnum",
|
||||
"ChatStreamCompletionCreateParamsOrderUnion",
|
||||
"ChatStreamCompletionCreateParamsOrderUnionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPdf",
|
||||
"ChatStreamCompletionCreateParamsPdfEngine",
|
||||
"ChatStreamCompletionCreateParamsPdfTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPluginChainOfThought",
|
||||
"ChatStreamCompletionCreateParamsPluginChainOfThoughtTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPluginFileParser",
|
||||
"ChatStreamCompletionCreateParamsPluginFileParserTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPluginModeration",
|
||||
"ChatStreamCompletionCreateParamsPluginModerationTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPluginUnion",
|
||||
"ChatStreamCompletionCreateParamsPluginUnionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPluginWeb",
|
||||
"ChatStreamCompletionCreateParamsPluginWebTypedDict",
|
||||
"ChatStreamCompletionCreateParamsPrompt",
|
||||
"ChatStreamCompletionCreateParamsPromptTypedDict",
|
||||
"ChatStreamCompletionCreateParamsProvider",
|
||||
"ChatStreamCompletionCreateParamsProviderTypedDict",
|
||||
"ChatStreamCompletionCreateParamsQuantization",
|
||||
"ChatStreamCompletionCreateParamsReasoning",
|
||||
"ChatStreamCompletionCreateParamsReasoningEffort",
|
||||
"ChatStreamCompletionCreateParamsReasoningTypedDict",
|
||||
"ChatStreamCompletionCreateParamsRequest",
|
||||
"ChatStreamCompletionCreateParamsRequestTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatGrammar",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatGrammarTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONObject",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONObjectTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONSchema",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONSchemaTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatPython",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatPythonTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatText",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatTextTypedDict",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatUnion",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatUnionTypedDict",
|
||||
"ChatStreamCompletionCreateParamsSort",
|
||||
"ChatStreamCompletionCreateParamsStop",
|
||||
"ChatStreamCompletionCreateParamsStopTypedDict",
|
||||
"ChatStreamCompletionCreateParamsStreamOptions",
|
||||
"ChatStreamCompletionCreateParamsStreamOptionsTypedDict",
|
||||
"ChatStreamCompletionCreateParamsTypeGrammar",
|
||||
"ChatStreamCompletionCreateParamsTypeJSONObject",
|
||||
"ChatStreamCompletionCreateParamsTypeJSONSchema",
|
||||
"ChatStreamCompletionCreateParamsTypePython",
|
||||
"ChatStreamCompletionCreateParamsTypeText",
|
||||
"ChatStreamCompletionCreateParamsTypedDict",
|
||||
"CompletionTokensDetails",
|
||||
"CompletionTokensDetailsTypedDict",
|
||||
"CompletionUsage",
|
||||
"CompletionUsageTypedDict",
|
||||
"ContentImageURL",
|
||||
"ContentImageURLTypedDict",
|
||||
"ContentText",
|
||||
"ContentTextTypedDict",
|
||||
"ContentTypeImageURL",
|
||||
"ContentTypeText",
|
||||
"Detail",
|
||||
"Error",
|
||||
"ErrorTypedDict",
|
||||
"File",
|
||||
"FileAnnotationDetail",
|
||||
"FileAnnotationDetailContentUnion",
|
||||
"FileAnnotationDetailContentUnionTypedDict",
|
||||
"FileAnnotationDetailImageURL",
|
||||
"FileAnnotationDetailImageURLTypedDict",
|
||||
"FileAnnotationDetailTypedDict",
|
||||
"FileTypedDict",
|
||||
"InputAudio",
|
||||
"InputAudioTypedDict",
|
||||
"Parameters",
|
||||
"ParametersTypedDict",
|
||||
"PromptTokensDetails",
|
||||
"PromptTokensDetailsTypedDict",
|
||||
"ReasoningDetail",
|
||||
"ReasoningDetailEncrypted",
|
||||
"ReasoningDetailEncryptedFormat",
|
||||
"ReasoningDetailEncryptedType",
|
||||
"ReasoningDetailEncryptedTypedDict",
|
||||
"ReasoningDetailSummary",
|
||||
"ReasoningDetailSummaryFormat",
|
||||
"ReasoningDetailSummaryType",
|
||||
"ReasoningDetailSummaryTypedDict",
|
||||
"ReasoningDetailText",
|
||||
"ReasoningDetailTextFormat",
|
||||
"ReasoningDetailTextType",
|
||||
"ReasoningDetailTextTypedDict",
|
||||
"ReasoningDetailTypedDict",
|
||||
"ResponseFormatJSONSchemaSchema",
|
||||
"ResponseFormatJSONSchemaSchemaTypedDict",
|
||||
"Security",
|
||||
"SecurityTypedDict",
|
||||
"StreamChatCompletionResponseBody",
|
||||
"StreamChatCompletionResponseBodyTypedDict",
|
||||
"TopLogprob",
|
||||
"TopLogprobTypedDict",
|
||||
"TypeFile",
|
||||
"URLCitation",
|
||||
"URLCitationAnnotationDetail",
|
||||
"URLCitationAnnotationDetailType",
|
||||
"URLCitationAnnotationDetailTypedDict",
|
||||
"URLCitationTypedDict",
|
||||
]
|
||||
|
||||
_dynamic_imports: dict[str, str] = {
|
||||
"AnnotationDetail": ".annotationdetail",
|
||||
"AnnotationDetailTypedDict": ".annotationdetail",
|
||||
"ChatCompletion": ".chatcompletion",
|
||||
"ChatCompletionObject": ".chatcompletion",
|
||||
"ChatCompletionTypedDict": ".chatcompletion",
|
||||
"ChatCompletionAssistantMessageParam": ".chatcompletionassistantmessageparam",
|
||||
"ChatCompletionAssistantMessageParamContent": ".chatcompletionassistantmessageparam",
|
||||
"ChatCompletionAssistantMessageParamContentTypedDict": ".chatcompletionassistantmessageparam",
|
||||
"ChatCompletionAssistantMessageParamRole": ".chatcompletionassistantmessageparam",
|
||||
"ChatCompletionAssistantMessageParamTypedDict": ".chatcompletionassistantmessageparam",
|
||||
"ChatCompletionChoice": ".chatcompletionchoice",
|
||||
"ChatCompletionChoiceFinishReason": ".chatcompletionchoice",
|
||||
"ChatCompletionChoiceTypedDict": ".chatcompletionchoice",
|
||||
"ChatCompletionChunk": ".chatcompletionchunk",
|
||||
"ChatCompletionChunkObject": ".chatcompletionchunk",
|
||||
"ChatCompletionChunkTypedDict": ".chatcompletionchunk",
|
||||
"ChatCompletionChunkChoice": ".chatcompletionchunkchoice",
|
||||
"ChatCompletionChunkChoiceFinishReason": ".chatcompletionchunkchoice",
|
||||
"ChatCompletionChunkChoiceTypedDict": ".chatcompletionchunkchoice",
|
||||
"ChatCompletionChunkChoiceDelta": ".chatcompletionchunkchoicedelta",
|
||||
"ChatCompletionChunkChoiceDeltaRole": ".chatcompletionchunkchoicedelta",
|
||||
"ChatCompletionChunkChoiceDeltaTypedDict": ".chatcompletionchunkchoicedelta",
|
||||
"ChatCompletionChunkChoiceDeltaToolCall": ".chatcompletionchunkchoicedeltatoolcall",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallFunction": ".chatcompletionchunkchoicedeltatoolcall",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallFunctionTypedDict": ".chatcompletionchunkchoicedeltatoolcall",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallType": ".chatcompletionchunkchoicedeltatoolcall",
|
||||
"ChatCompletionChunkChoiceDeltaToolCallTypedDict": ".chatcompletionchunkchoicedeltatoolcall",
|
||||
"ChatCompletionContentPart": ".chatcompletioncontentpart",
|
||||
"ChatCompletionContentPartTypedDict": ".chatcompletioncontentpart",
|
||||
"ChatCompletionContentPartAudio": ".chatcompletioncontentpartaudio",
|
||||
"ChatCompletionContentPartAudioFormat": ".chatcompletioncontentpartaudio",
|
||||
"ChatCompletionContentPartAudioType": ".chatcompletioncontentpartaudio",
|
||||
"ChatCompletionContentPartAudioTypedDict": ".chatcompletioncontentpartaudio",
|
||||
"InputAudio": ".chatcompletioncontentpartaudio",
|
||||
"InputAudioTypedDict": ".chatcompletioncontentpartaudio",
|
||||
"ChatCompletionContentPartImage": ".chatcompletioncontentpartimage",
|
||||
"ChatCompletionContentPartImageImageURL": ".chatcompletioncontentpartimage",
|
||||
"ChatCompletionContentPartImageImageURLTypedDict": ".chatcompletioncontentpartimage",
|
||||
"ChatCompletionContentPartImageType": ".chatcompletioncontentpartimage",
|
||||
"ChatCompletionContentPartImageTypedDict": ".chatcompletioncontentpartimage",
|
||||
"Detail": ".chatcompletioncontentpartimage",
|
||||
"ChatCompletionContentPartText": ".chatcompletioncontentparttext",
|
||||
"ChatCompletionContentPartTextType": ".chatcompletioncontentparttext",
|
||||
"ChatCompletionContentPartTextTypedDict": ".chatcompletioncontentparttext",
|
||||
"ChatCompletionCreateParams": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsAudio": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsAudioTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsCompletion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsCompletionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsDataCollection": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsEffort": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsEngine": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIDChainOfThought": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIDFileParser": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIDModeration": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIDWeb": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIgnoreEnum": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIgnoreUnion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsIgnoreUnionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsImage": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsImageTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsJSONSchema": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsJSONSchemaTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsMaxPrice": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsMaxPriceTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOnlyEnum": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOnlyUnion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOnlyUnionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOrderEnum": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOrderUnion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsOrderUnionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPdf": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPdfEngine": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPdfTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginChainOfThought": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginChainOfThoughtTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginFileParser": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginFileParserTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginModeration": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginModerationTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginUnion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginUnionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginWeb": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPluginWebTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPrompt": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsPromptTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsProvider": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsProviderTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsQuantization": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsReasoning": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsReasoningEffort": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsReasoningTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsRequest": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsRequestTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatGrammar": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatGrammarTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONObject": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONObjectTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONSchema": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatJSONSchemaTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatPython": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatPythonTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatText": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatTextTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatUnion": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsResponseFormatUnionTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsSort": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsStop": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsStopTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsStreamOptions": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsStreamOptionsTypedDict": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypeGrammar": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypeJSONObject": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypeJSONSchema": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypePython": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypeText": ".chatcompletioncreateparams",
|
||||
"ChatCompletionCreateParamsTypedDict": ".chatcompletioncreateparams",
|
||||
"Error": ".chatcompletionerror",
|
||||
"ErrorTypedDict": ".chatcompletionerror",
|
||||
"ChatCompletionMessage": ".chatcompletionmessage",
|
||||
"ChatCompletionMessageRole": ".chatcompletionmessage",
|
||||
"ChatCompletionMessageTypedDict": ".chatcompletionmessage",
|
||||
"ChatCompletionMessageParam": ".chatcompletionmessageparam",
|
||||
"ChatCompletionMessageParamTypedDict": ".chatcompletionmessageparam",
|
||||
"ChatCompletionMessageToolCall": ".chatcompletionmessagetoolcall",
|
||||
"ChatCompletionMessageToolCallFunction": ".chatcompletionmessagetoolcall",
|
||||
"ChatCompletionMessageToolCallFunctionTypedDict": ".chatcompletionmessagetoolcall",
|
||||
"ChatCompletionMessageToolCallType": ".chatcompletionmessagetoolcall",
|
||||
"ChatCompletionMessageToolCallTypedDict": ".chatcompletionmessagetoolcall",
|
||||
"ChatCompletionNamedToolChoice": ".chatcompletionnamedtoolchoice",
|
||||
"ChatCompletionNamedToolChoiceFunction": ".chatcompletionnamedtoolchoice",
|
||||
"ChatCompletionNamedToolChoiceFunctionTypedDict": ".chatcompletionnamedtoolchoice",
|
||||
"ChatCompletionNamedToolChoiceType": ".chatcompletionnamedtoolchoice",
|
||||
"ChatCompletionNamedToolChoiceTypedDict": ".chatcompletionnamedtoolchoice",
|
||||
"ChatCompletionSystemMessageParam": ".chatcompletionsystemmessageparam",
|
||||
"ChatCompletionSystemMessageParamContent": ".chatcompletionsystemmessageparam",
|
||||
"ChatCompletionSystemMessageParamContentTypedDict": ".chatcompletionsystemmessageparam",
|
||||
"ChatCompletionSystemMessageParamRole": ".chatcompletionsystemmessageparam",
|
||||
"ChatCompletionSystemMessageParamTypedDict": ".chatcompletionsystemmessageparam",
|
||||
"ChatCompletionTokenLogprob": ".chatcompletiontokenlogprob",
|
||||
"ChatCompletionTokenLogprobTypedDict": ".chatcompletiontokenlogprob",
|
||||
"TopLogprob": ".chatcompletiontokenlogprob",
|
||||
"TopLogprobTypedDict": ".chatcompletiontokenlogprob",
|
||||
"ChatCompletionTokenLogprobs": ".chatcompletiontokenlogprobs",
|
||||
"ChatCompletionTokenLogprobsTypedDict": ".chatcompletiontokenlogprobs",
|
||||
"ChatCompletionTool": ".chatcompletiontool",
|
||||
"ChatCompletionToolFunction": ".chatcompletiontool",
|
||||
"ChatCompletionToolFunctionTypedDict": ".chatcompletiontool",
|
||||
"ChatCompletionToolType": ".chatcompletiontool",
|
||||
"ChatCompletionToolTypedDict": ".chatcompletiontool",
|
||||
"Parameters": ".chatcompletiontool",
|
||||
"ParametersTypedDict": ".chatcompletiontool",
|
||||
"ChatCompletionToolChoiceOption": ".chatcompletiontoolchoiceoption",
|
||||
"ChatCompletionToolChoiceOptionAuto": ".chatcompletiontoolchoiceoption",
|
||||
"ChatCompletionToolChoiceOptionNone": ".chatcompletiontoolchoiceoption",
|
||||
"ChatCompletionToolChoiceOptionRequired": ".chatcompletiontoolchoiceoption",
|
||||
"ChatCompletionToolChoiceOptionTypedDict": ".chatcompletiontoolchoiceoption",
|
||||
"ChatCompletionToolMessageParam": ".chatcompletiontoolmessageparam",
|
||||
"ChatCompletionToolMessageParamContent": ".chatcompletiontoolmessageparam",
|
||||
"ChatCompletionToolMessageParamContentTypedDict": ".chatcompletiontoolmessageparam",
|
||||
"ChatCompletionToolMessageParamRole": ".chatcompletiontoolmessageparam",
|
||||
"ChatCompletionToolMessageParamTypedDict": ".chatcompletiontoolmessageparam",
|
||||
"ChatCompletionUserMessageParam": ".chatcompletionusermessageparam",
|
||||
"ChatCompletionUserMessageParamContent": ".chatcompletionusermessageparam",
|
||||
"ChatCompletionUserMessageParamContentTypedDict": ".chatcompletionusermessageparam",
|
||||
"ChatCompletionUserMessageParamRole": ".chatcompletionusermessageparam",
|
||||
"ChatCompletionUserMessageParamTypedDict": ".chatcompletionusermessageparam",
|
||||
"ChatStreamCompletionCreateParams": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsAudio": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsAudioTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsCompletion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsCompletionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsDataCollection": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsEffort": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsEngine": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIDChainOfThought": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIDFileParser": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIDModeration": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIDWeb": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIgnoreEnum": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIgnoreUnion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsIgnoreUnionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsImage": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsImageTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsJSONSchema": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsJSONSchemaTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsMaxPrice": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsMaxPriceTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOnlyEnum": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOnlyUnion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOnlyUnionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOrderEnum": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOrderUnion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsOrderUnionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPdf": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPdfEngine": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPdfTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginChainOfThought": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginChainOfThoughtTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginFileParser": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginFileParserTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginModeration": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginModerationTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginUnion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginUnionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginWeb": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPluginWebTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPrompt": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsPromptTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsProvider": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsProviderTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsQuantization": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsReasoning": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsReasoningEffort": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsReasoningTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsRequest": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsRequestTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatGrammar": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatGrammarTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONObject": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONObjectTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONSchema": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatJSONSchemaTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatPython": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatPythonTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatText": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatTextTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatUnion": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsResponseFormatUnionTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsSort": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsStop": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsStopTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsStreamOptions": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsStreamOptionsTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypeGrammar": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypeJSONObject": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypeJSONSchema": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypePython": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypeText": ".chatstreamcompletioncreateparams",
|
||||
"ChatStreamCompletionCreateParamsTypedDict": ".chatstreamcompletioncreateparams",
|
||||
"CompletionTokensDetails": ".completionusage",
|
||||
"CompletionTokensDetailsTypedDict": ".completionusage",
|
||||
"CompletionUsage": ".completionusage",
|
||||
"CompletionUsageTypedDict": ".completionusage",
|
||||
"PromptTokensDetails": ".completionusage",
|
||||
"PromptTokensDetailsTypedDict": ".completionusage",
|
||||
"ContentImageURL": ".fileannotationdetail",
|
||||
"ContentImageURLTypedDict": ".fileannotationdetail",
|
||||
"ContentText": ".fileannotationdetail",
|
||||
"ContentTextTypedDict": ".fileannotationdetail",
|
||||
"ContentTypeImageURL": ".fileannotationdetail",
|
||||
"ContentTypeText": ".fileannotationdetail",
|
||||
"File": ".fileannotationdetail",
|
||||
"FileAnnotationDetail": ".fileannotationdetail",
|
||||
"FileAnnotationDetailContentUnion": ".fileannotationdetail",
|
||||
"FileAnnotationDetailContentUnionTypedDict": ".fileannotationdetail",
|
||||
"FileAnnotationDetailImageURL": ".fileannotationdetail",
|
||||
"FileAnnotationDetailImageURLTypedDict": ".fileannotationdetail",
|
||||
"FileAnnotationDetailTypedDict": ".fileannotationdetail",
|
||||
"FileTypedDict": ".fileannotationdetail",
|
||||
"TypeFile": ".fileannotationdetail",
|
||||
"ReasoningDetail": ".reasoningdetail",
|
||||
"ReasoningDetailTypedDict": ".reasoningdetail",
|
||||
"ReasoningDetailEncrypted": ".reasoningdetailencrypted",
|
||||
"ReasoningDetailEncryptedFormat": ".reasoningdetailencrypted",
|
||||
"ReasoningDetailEncryptedType": ".reasoningdetailencrypted",
|
||||
"ReasoningDetailEncryptedTypedDict": ".reasoningdetailencrypted",
|
||||
"ReasoningDetailSummary": ".reasoningdetailsummary",
|
||||
"ReasoningDetailSummaryFormat": ".reasoningdetailsummary",
|
||||
"ReasoningDetailSummaryType": ".reasoningdetailsummary",
|
||||
"ReasoningDetailSummaryTypedDict": ".reasoningdetailsummary",
|
||||
"ReasoningDetailText": ".reasoningdetailtext",
|
||||
"ReasoningDetailTextFormat": ".reasoningdetailtext",
|
||||
"ReasoningDetailTextType": ".reasoningdetailtext",
|
||||
"ReasoningDetailTextTypedDict": ".reasoningdetailtext",
|
||||
"ResponseFormatJSONSchemaSchema": ".responseformatjsonschemaschema",
|
||||
"ResponseFormatJSONSchemaSchemaTypedDict": ".responseformatjsonschemaschema",
|
||||
"Security": ".security",
|
||||
"SecurityTypedDict": ".security",
|
||||
"StreamChatCompletionResponseBody": ".streamchatcompletionop",
|
||||
"StreamChatCompletionResponseBodyTypedDict": ".streamchatcompletionop",
|
||||
"URLCitation": ".urlcitationannotationdetail",
|
||||
"URLCitationAnnotationDetail": ".urlcitationannotationdetail",
|
||||
"URLCitationAnnotationDetailType": ".urlcitationannotationdetail",
|
||||
"URLCitationAnnotationDetailTypedDict": ".urlcitationannotationdetail",
|
||||
"URLCitationTypedDict": ".urlcitationannotationdetail",
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(attr_name: str) -> object:
|
||||
module_name = _dynamic_imports.get(attr_name)
|
||||
if module_name is None:
|
||||
raise AttributeError(
|
||||
f"No {attr_name} found in _dynamic_imports for module name -> {__name__} "
|
||||
)
|
||||
|
||||
try:
|
||||
module = import_module(module_name, __package__)
|
||||
result = getattr(module, attr_name)
|
||||
return result
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
f"Failed to import {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
except AttributeError as e:
|
||||
raise AttributeError(
|
||||
f"Failed to get {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
|
||||
|
||||
def __dir__():
|
||||
lazy_attrs = builtins.list(_dynamic_imports.keys())
|
||||
return builtins.sorted(lazy_attrs)
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .fileannotationdetail import FileAnnotationDetail, FileAnnotationDetailTypedDict
|
||||
from .urlcitationannotationdetail import (
|
||||
URLCitationAnnotationDetail,
|
||||
URLCitationAnnotationDetailTypedDict,
|
||||
)
|
||||
from openrouter.utils import get_discriminator
|
||||
from pydantic import Discriminator, Tag
|
||||
from typing import Union
|
||||
from typing_extensions import Annotated, TypeAliasType
|
||||
|
||||
|
||||
AnnotationDetailTypedDict = TypeAliasType(
|
||||
"AnnotationDetailTypedDict",
|
||||
Union[FileAnnotationDetailTypedDict, URLCitationAnnotationDetailTypedDict],
|
||||
)
|
||||
r"""Annotation information"""
|
||||
|
||||
|
||||
AnnotationDetail = Annotated[
|
||||
Union[
|
||||
Annotated[FileAnnotationDetail, Tag("file")],
|
||||
Annotated[URLCitationAnnotationDetail, Tag("url_citation")],
|
||||
],
|
||||
Discriminator(lambda m: get_discriminator(m, "type", "type")),
|
||||
]
|
||||
r"""Annotation information"""
|
||||
@@ -0,0 +1,92 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionchoice import ChatCompletionChoice, ChatCompletionChoiceTypedDict
|
||||
from .completionusage import CompletionUsage, CompletionUsageTypedDict
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import List, Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionObject(str, Enum):
|
||||
CHAT_COMPLETION = "chat.completion"
|
||||
|
||||
|
||||
class ChatCompletionTypedDict(TypedDict):
|
||||
r"""Chat completion response"""
|
||||
|
||||
id: str
|
||||
r"""Unique completion identifier"""
|
||||
choices: List[ChatCompletionChoiceTypedDict]
|
||||
r"""List of completion choices"""
|
||||
created: float
|
||||
r"""Unix timestamp of creation"""
|
||||
model: str
|
||||
r"""Model used for completion"""
|
||||
object: ChatCompletionObject
|
||||
system_fingerprint: NotRequired[Nullable[str]]
|
||||
r"""System fingerprint"""
|
||||
usage: NotRequired[CompletionUsageTypedDict]
|
||||
r"""Token usage statistics"""
|
||||
|
||||
|
||||
class ChatCompletion(BaseModel):
|
||||
r"""Chat completion response"""
|
||||
|
||||
id: str
|
||||
r"""Unique completion identifier"""
|
||||
|
||||
choices: List[ChatCompletionChoice]
|
||||
r"""List of completion choices"""
|
||||
|
||||
created: float
|
||||
r"""Unix timestamp of creation"""
|
||||
|
||||
model: str
|
||||
r"""Model used for completion"""
|
||||
|
||||
object: ChatCompletionObject
|
||||
|
||||
system_fingerprint: OptionalNullable[str] = UNSET
|
||||
r"""System fingerprint"""
|
||||
|
||||
usage: Optional[CompletionUsage] = None
|
||||
r"""Token usage statistics"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["system_fingerprint", "usage"]
|
||||
nullable_fields = ["system_fingerprint"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,102 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletioncontentpart import (
|
||||
ChatCompletionContentPart,
|
||||
ChatCompletionContentPartTypedDict,
|
||||
)
|
||||
from .chatcompletionmessagetoolcall import (
|
||||
ChatCompletionMessageToolCall,
|
||||
ChatCompletionMessageToolCallTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import Any, List, Optional, Union
|
||||
from typing_extensions import NotRequired, TypeAliasType, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionAssistantMessageParamRole(str, Enum):
|
||||
ASSISTANT = "assistant"
|
||||
|
||||
|
||||
ChatCompletionAssistantMessageParamContentTypedDict = TypeAliasType(
|
||||
"ChatCompletionAssistantMessageParamContentTypedDict",
|
||||
Union[str, List[ChatCompletionContentPartTypedDict], Any],
|
||||
)
|
||||
r"""Assistant message content"""
|
||||
|
||||
|
||||
ChatCompletionAssistantMessageParamContent = TypeAliasType(
|
||||
"ChatCompletionAssistantMessageParamContent",
|
||||
Union[str, List[ChatCompletionContentPart], Any],
|
||||
)
|
||||
r"""Assistant message content"""
|
||||
|
||||
|
||||
class ChatCompletionAssistantMessageParamTypedDict(TypedDict):
|
||||
r"""Assistant message with tool calls and audio support"""
|
||||
|
||||
role: ChatCompletionAssistantMessageParamRole
|
||||
content: NotRequired[Nullable[ChatCompletionAssistantMessageParamContentTypedDict]]
|
||||
r"""Assistant message content"""
|
||||
name: NotRequired[str]
|
||||
r"""Optional name for the assistant"""
|
||||
tool_calls: NotRequired[List[ChatCompletionMessageToolCallTypedDict]]
|
||||
r"""Tool calls made by the assistant"""
|
||||
refusal: NotRequired[Nullable[str]]
|
||||
r"""Refusal message if content was refused"""
|
||||
|
||||
|
||||
class ChatCompletionAssistantMessageParam(BaseModel):
|
||||
r"""Assistant message with tool calls and audio support"""
|
||||
|
||||
role: ChatCompletionAssistantMessageParamRole
|
||||
|
||||
content: OptionalNullable[ChatCompletionAssistantMessageParamContent] = UNSET
|
||||
r"""Assistant message content"""
|
||||
|
||||
name: Optional[str] = None
|
||||
r"""Optional name for the assistant"""
|
||||
|
||||
tool_calls: Optional[List[ChatCompletionMessageToolCall]] = None
|
||||
r"""Tool calls made by the assistant"""
|
||||
|
||||
refusal: OptionalNullable[str] = UNSET
|
||||
r"""Refusal message if content was refused"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["content", "name", "tool_calls", "refusal"]
|
||||
nullable_fields = ["content", "refusal"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,87 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionmessage import ChatCompletionMessage, ChatCompletionMessageTypedDict
|
||||
from .chatcompletiontokenlogprobs import (
|
||||
ChatCompletionTokenLogprobs,
|
||||
ChatCompletionTokenLogprobsTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionChoiceFinishReason(str, Enum):
|
||||
r"""Reason the completion finished"""
|
||||
|
||||
TOOL_CALLS = "tool_calls"
|
||||
STOP = "stop"
|
||||
LENGTH = "length"
|
||||
CONTENT_FILTER = "content_filter"
|
||||
ERROR = "error"
|
||||
|
||||
|
||||
class ChatCompletionChoiceTypedDict(TypedDict):
|
||||
r"""Chat completion choice"""
|
||||
|
||||
finish_reason: Nullable[ChatCompletionChoiceFinishReason]
|
||||
r"""Reason the completion finished"""
|
||||
index: float
|
||||
r"""Choice index"""
|
||||
message: ChatCompletionMessageTypedDict
|
||||
r"""Assistant message in completion response"""
|
||||
logprobs: NotRequired[Nullable[ChatCompletionTokenLogprobsTypedDict]]
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
|
||||
class ChatCompletionChoice(BaseModel):
|
||||
r"""Chat completion choice"""
|
||||
|
||||
finish_reason: Nullable[ChatCompletionChoiceFinishReason]
|
||||
r"""Reason the completion finished"""
|
||||
|
||||
index: float
|
||||
r"""Choice index"""
|
||||
|
||||
message: ChatCompletionMessage
|
||||
r"""Assistant message in completion response"""
|
||||
|
||||
logprobs: OptionalNullable[ChatCompletionTokenLogprobs] = UNSET
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["logprobs"]
|
||||
nullable_fields = ["finish_reason", "logprobs"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,85 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionchunkchoice import (
|
||||
ChatCompletionChunkChoice,
|
||||
ChatCompletionChunkChoiceTypedDict,
|
||||
)
|
||||
from .completionusage import CompletionUsage, CompletionUsageTypedDict
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import List, Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionChunkObject(str, Enum):
|
||||
CHAT_COMPLETION_CHUNK = "chat.completion.chunk"
|
||||
|
||||
|
||||
class ChatCompletionChunkTypedDict(TypedDict):
|
||||
r"""Streaming chat completion chunk"""
|
||||
|
||||
id: str
|
||||
choices: List[ChatCompletionChunkChoiceTypedDict]
|
||||
created: float
|
||||
model: str
|
||||
object: ChatCompletionChunkObject
|
||||
system_fingerprint: NotRequired[Nullable[str]]
|
||||
usage: NotRequired[CompletionUsageTypedDict]
|
||||
r"""Token usage statistics"""
|
||||
|
||||
|
||||
class ChatCompletionChunk(BaseModel):
|
||||
r"""Streaming chat completion chunk"""
|
||||
|
||||
id: str
|
||||
|
||||
choices: List[ChatCompletionChunkChoice]
|
||||
|
||||
created: float
|
||||
|
||||
model: str
|
||||
|
||||
object: ChatCompletionChunkObject
|
||||
|
||||
system_fingerprint: OptionalNullable[str] = UNSET
|
||||
|
||||
usage: Optional[CompletionUsage] = None
|
||||
r"""Token usage statistics"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["system_fingerprint", "usage"]
|
||||
nullable_fields = ["system_fingerprint"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,84 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionchunkchoicedelta import (
|
||||
ChatCompletionChunkChoiceDelta,
|
||||
ChatCompletionChunkChoiceDeltaTypedDict,
|
||||
)
|
||||
from .chatcompletiontokenlogprobs import (
|
||||
ChatCompletionTokenLogprobs,
|
||||
ChatCompletionTokenLogprobsTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceFinishReason(str, Enum):
|
||||
TOOL_CALLS = "tool_calls"
|
||||
STOP = "stop"
|
||||
LENGTH = "length"
|
||||
CONTENT_FILTER = "content_filter"
|
||||
ERROR = "error"
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceTypedDict(TypedDict):
|
||||
r"""Streaming completion choice chunk"""
|
||||
|
||||
delta: ChatCompletionChunkChoiceDeltaTypedDict
|
||||
r"""Delta changes in streaming response"""
|
||||
finish_reason: Nullable[ChatCompletionChunkChoiceFinishReason]
|
||||
index: float
|
||||
logprobs: NotRequired[Nullable[ChatCompletionTokenLogprobsTypedDict]]
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
|
||||
class ChatCompletionChunkChoice(BaseModel):
|
||||
r"""Streaming completion choice chunk"""
|
||||
|
||||
delta: ChatCompletionChunkChoiceDelta
|
||||
r"""Delta changes in streaming response"""
|
||||
|
||||
finish_reason: Nullable[ChatCompletionChunkChoiceFinishReason]
|
||||
|
||||
index: float
|
||||
|
||||
logprobs: OptionalNullable[ChatCompletionTokenLogprobs] = UNSET
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["logprobs"]
|
||||
nullable_fields = ["finish_reason", "logprobs"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,108 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .annotationdetail import AnnotationDetail, AnnotationDetailTypedDict
|
||||
from .chatcompletionchunkchoicedeltatoolcall import (
|
||||
ChatCompletionChunkChoiceDeltaToolCall,
|
||||
ChatCompletionChunkChoiceDeltaToolCallTypedDict,
|
||||
)
|
||||
from .reasoningdetail import ReasoningDetail, ReasoningDetailTypedDict
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import List, Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaRole(str, Enum):
|
||||
r"""The role of the message author"""
|
||||
|
||||
ASSISTANT = "assistant"
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaTypedDict(TypedDict):
|
||||
r"""Delta changes in streaming response"""
|
||||
|
||||
role: NotRequired[ChatCompletionChunkChoiceDeltaRole]
|
||||
r"""The role of the message author"""
|
||||
content: NotRequired[Nullable[str]]
|
||||
r"""Message content delta"""
|
||||
reasoning: NotRequired[Nullable[str]]
|
||||
r"""Reasoning content delta"""
|
||||
refusal: NotRequired[Nullable[str]]
|
||||
r"""Refusal message delta"""
|
||||
tool_calls: NotRequired[List[ChatCompletionChunkChoiceDeltaToolCallTypedDict]]
|
||||
r"""Tool calls delta"""
|
||||
reasoning_details: NotRequired[List[ReasoningDetailTypedDict]]
|
||||
r"""Reasoning details delta to send reasoning details back to upstream"""
|
||||
annotations: NotRequired[List[AnnotationDetailTypedDict]]
|
||||
r"""Annotations delta to send annotations back to upstream"""
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDelta(BaseModel):
|
||||
r"""Delta changes in streaming response"""
|
||||
|
||||
role: Optional[ChatCompletionChunkChoiceDeltaRole] = None
|
||||
r"""The role of the message author"""
|
||||
|
||||
content: OptionalNullable[str] = UNSET
|
||||
r"""Message content delta"""
|
||||
|
||||
reasoning: OptionalNullable[str] = UNSET
|
||||
r"""Reasoning content delta"""
|
||||
|
||||
refusal: OptionalNullable[str] = UNSET
|
||||
r"""Refusal message delta"""
|
||||
|
||||
tool_calls: Optional[List[ChatCompletionChunkChoiceDeltaToolCall]] = None
|
||||
r"""Tool calls delta"""
|
||||
|
||||
reasoning_details: Optional[List[ReasoningDetail]] = None
|
||||
r"""Reasoning details delta to send reasoning details back to upstream"""
|
||||
|
||||
annotations: Optional[List[AnnotationDetail]] = None
|
||||
r"""Annotations delta to send annotations back to upstream"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = [
|
||||
"role",
|
||||
"content",
|
||||
"reasoning",
|
||||
"refusal",
|
||||
"tool_calls",
|
||||
"reasoning_details",
|
||||
"annotations",
|
||||
]
|
||||
nullable_fields = ["content", "reasoning", "refusal"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaToolCallType(str, Enum):
|
||||
r"""Tool call type"""
|
||||
|
||||
FUNCTION = "function"
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaToolCallFunctionTypedDict(TypedDict):
|
||||
r"""Function call details"""
|
||||
|
||||
name: NotRequired[str]
|
||||
r"""Function name"""
|
||||
arguments: NotRequired[str]
|
||||
r"""Function arguments as JSON string"""
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaToolCallFunction(BaseModel):
|
||||
r"""Function call details"""
|
||||
|
||||
name: Optional[str] = None
|
||||
r"""Function name"""
|
||||
|
||||
arguments: Optional[str] = None
|
||||
r"""Function arguments as JSON string"""
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaToolCallTypedDict(TypedDict):
|
||||
r"""Tool call delta for streaming responses"""
|
||||
|
||||
index: float
|
||||
r"""Tool call index in the array"""
|
||||
id: NotRequired[str]
|
||||
r"""Tool call identifier"""
|
||||
type: NotRequired[ChatCompletionChunkChoiceDeltaToolCallType]
|
||||
r"""Tool call type"""
|
||||
function: NotRequired[ChatCompletionChunkChoiceDeltaToolCallFunctionTypedDict]
|
||||
r"""Function call details"""
|
||||
|
||||
|
||||
class ChatCompletionChunkChoiceDeltaToolCall(BaseModel):
|
||||
r"""Tool call delta for streaming responses"""
|
||||
|
||||
index: float
|
||||
r"""Tool call index in the array"""
|
||||
|
||||
id: Optional[str] = None
|
||||
r"""Tool call identifier"""
|
||||
|
||||
type: Optional[ChatCompletionChunkChoiceDeltaToolCallType] = None
|
||||
r"""Tool call type"""
|
||||
|
||||
function: Optional[ChatCompletionChunkChoiceDeltaToolCallFunction] = None
|
||||
r"""Function call details"""
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletioncontentpartaudio import (
|
||||
ChatCompletionContentPartAudio,
|
||||
ChatCompletionContentPartAudioTypedDict,
|
||||
)
|
||||
from .chatcompletioncontentpartimage import (
|
||||
ChatCompletionContentPartImage,
|
||||
ChatCompletionContentPartImageTypedDict,
|
||||
)
|
||||
from .chatcompletioncontentparttext import (
|
||||
ChatCompletionContentPartText,
|
||||
ChatCompletionContentPartTextTypedDict,
|
||||
)
|
||||
from openrouter.utils import get_discriminator
|
||||
from pydantic import Discriminator, Tag
|
||||
from typing import Union
|
||||
from typing_extensions import Annotated, TypeAliasType
|
||||
|
||||
|
||||
ChatCompletionContentPartTypedDict = TypeAliasType(
|
||||
"ChatCompletionContentPartTypedDict",
|
||||
Union[
|
||||
ChatCompletionContentPartTextTypedDict,
|
||||
ChatCompletionContentPartImageTypedDict,
|
||||
ChatCompletionContentPartAudioTypedDict,
|
||||
],
|
||||
)
|
||||
r"""Content part for chat completion messages"""
|
||||
|
||||
|
||||
ChatCompletionContentPart = Annotated[
|
||||
Union[
|
||||
Annotated[ChatCompletionContentPartText, Tag("text")],
|
||||
Annotated[ChatCompletionContentPartImage, Tag("image_url")],
|
||||
Annotated[ChatCompletionContentPartAudio, Tag("input_audio")],
|
||||
],
|
||||
Discriminator(lambda m: get_discriminator(m, "type", "type")),
|
||||
]
|
||||
r"""Content part for chat completion messages"""
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
import pydantic
|
||||
from typing_extensions import Annotated, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionContentPartAudioType(str, Enum):
|
||||
INPUT_AUDIO = "input_audio"
|
||||
|
||||
|
||||
class ChatCompletionContentPartAudioFormat(str, Enum):
|
||||
r"""Audio format"""
|
||||
|
||||
WAV = "wav"
|
||||
MP3 = "mp3"
|
||||
FLAC = "flac"
|
||||
M4A = "m4a"
|
||||
OGG = "ogg"
|
||||
PCM16 = "pcm16"
|
||||
PCM24 = "pcm24"
|
||||
|
||||
|
||||
class InputAudioTypedDict(TypedDict):
|
||||
data: str
|
||||
r"""Base64 encoded audio data"""
|
||||
format_: ChatCompletionContentPartAudioFormat
|
||||
r"""Audio format"""
|
||||
|
||||
|
||||
class InputAudio(BaseModel):
|
||||
data: str
|
||||
r"""Base64 encoded audio data"""
|
||||
|
||||
format_: Annotated[
|
||||
ChatCompletionContentPartAudioFormat, pydantic.Field(alias="format")
|
||||
]
|
||||
r"""Audio format"""
|
||||
|
||||
|
||||
class ChatCompletionContentPartAudioTypedDict(TypedDict):
|
||||
r"""Audio input content part"""
|
||||
|
||||
type: ChatCompletionContentPartAudioType
|
||||
input_audio: InputAudioTypedDict
|
||||
|
||||
|
||||
class ChatCompletionContentPartAudio(BaseModel):
|
||||
r"""Audio input content part"""
|
||||
|
||||
type: ChatCompletionContentPartAudioType
|
||||
|
||||
input_audio: InputAudio
|
||||
@@ -0,0 +1,49 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionContentPartImageType(str, Enum):
|
||||
IMAGE_URL = "image_url"
|
||||
|
||||
|
||||
class Detail(str, Enum):
|
||||
r"""Image detail level for vision models"""
|
||||
|
||||
AUTO = "auto"
|
||||
LOW = "low"
|
||||
HIGH = "high"
|
||||
|
||||
|
||||
class ChatCompletionContentPartImageImageURLTypedDict(TypedDict):
|
||||
url: str
|
||||
r"""URL of the image (data: URLs supported)"""
|
||||
detail: NotRequired[Detail]
|
||||
r"""Image detail level for vision models"""
|
||||
|
||||
|
||||
class ChatCompletionContentPartImageImageURL(BaseModel):
|
||||
url: str
|
||||
r"""URL of the image (data: URLs supported)"""
|
||||
|
||||
detail: Optional[Detail] = None
|
||||
r"""Image detail level for vision models"""
|
||||
|
||||
|
||||
class ChatCompletionContentPartImageTypedDict(TypedDict):
|
||||
r"""Image content part for vision models"""
|
||||
|
||||
type: ChatCompletionContentPartImageType
|
||||
image_url: ChatCompletionContentPartImageImageURLTypedDict
|
||||
|
||||
|
||||
class ChatCompletionContentPartImage(BaseModel):
|
||||
r"""Image content part for vision models"""
|
||||
|
||||
type: ChatCompletionContentPartImageType
|
||||
|
||||
image_url: ChatCompletionContentPartImageImageURL
|
||||
@@ -0,0 +1,25 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ChatCompletionContentPartTextType(str, Enum):
|
||||
TEXT = "text"
|
||||
|
||||
|
||||
class ChatCompletionContentPartTextTypedDict(TypedDict):
|
||||
r"""Text content part"""
|
||||
|
||||
type: ChatCompletionContentPartTextType
|
||||
text: str
|
||||
|
||||
|
||||
class ChatCompletionContentPartText(BaseModel):
|
||||
r"""Text content part"""
|
||||
|
||||
type: ChatCompletionContentPartTextType
|
||||
|
||||
text: str
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
|
||||
from pydantic import model_serializer
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ErrorTypedDict(TypedDict):
|
||||
r"""Error object structure"""
|
||||
|
||||
code: Nullable[str]
|
||||
message: str
|
||||
param: Nullable[str]
|
||||
type: str
|
||||
|
||||
|
||||
class Error(BaseModel):
|
||||
r"""Error object structure"""
|
||||
|
||||
code: Nullable[str]
|
||||
|
||||
message: str
|
||||
|
||||
param: Nullable[str]
|
||||
|
||||
type: str
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = []
|
||||
nullable_fields = ["code", "param"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,101 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .annotationdetail import AnnotationDetail, AnnotationDetailTypedDict
|
||||
from .chatcompletionmessagetoolcall import (
|
||||
ChatCompletionMessageToolCall,
|
||||
ChatCompletionMessageToolCallTypedDict,
|
||||
)
|
||||
from .reasoningdetail import ReasoningDetail, ReasoningDetailTypedDict
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import List, Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionMessageRole(str, Enum):
|
||||
ASSISTANT = "assistant"
|
||||
|
||||
|
||||
class ChatCompletionMessageTypedDict(TypedDict):
|
||||
r"""Assistant message in completion response"""
|
||||
|
||||
role: ChatCompletionMessageRole
|
||||
content: Nullable[str]
|
||||
r"""Message content"""
|
||||
refusal: Nullable[str]
|
||||
r"""Refusal message if content was refused"""
|
||||
reasoning: NotRequired[Nullable[str]]
|
||||
r"""Reasoning output"""
|
||||
tool_calls: NotRequired[List[ChatCompletionMessageToolCallTypedDict]]
|
||||
r"""Tool calls made by the assistant"""
|
||||
reasoning_details: NotRequired[List[ReasoningDetailTypedDict]]
|
||||
r"""Reasoning details delta to send reasoning details back to upstream"""
|
||||
annotations: NotRequired[List[AnnotationDetailTypedDict]]
|
||||
r"""Annotations delta to send annotations back to upstream"""
|
||||
|
||||
|
||||
class ChatCompletionMessage(BaseModel):
|
||||
r"""Assistant message in completion response"""
|
||||
|
||||
role: ChatCompletionMessageRole
|
||||
|
||||
content: Nullable[str]
|
||||
r"""Message content"""
|
||||
|
||||
refusal: Nullable[str]
|
||||
r"""Refusal message if content was refused"""
|
||||
|
||||
reasoning: OptionalNullable[str] = UNSET
|
||||
r"""Reasoning output"""
|
||||
|
||||
tool_calls: Optional[List[ChatCompletionMessageToolCall]] = None
|
||||
r"""Tool calls made by the assistant"""
|
||||
|
||||
reasoning_details: Optional[List[ReasoningDetail]] = None
|
||||
r"""Reasoning details delta to send reasoning details back to upstream"""
|
||||
|
||||
annotations: Optional[List[AnnotationDetail]] = None
|
||||
r"""Annotations delta to send annotations back to upstream"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = [
|
||||
"reasoning",
|
||||
"tool_calls",
|
||||
"reasoning_details",
|
||||
"annotations",
|
||||
]
|
||||
nullable_fields = ["content", "reasoning", "refusal"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,47 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionassistantmessageparam import (
|
||||
ChatCompletionAssistantMessageParam,
|
||||
ChatCompletionAssistantMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletionsystemmessageparam import (
|
||||
ChatCompletionSystemMessageParam,
|
||||
ChatCompletionSystemMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletiontoolmessageparam import (
|
||||
ChatCompletionToolMessageParam,
|
||||
ChatCompletionToolMessageParamTypedDict,
|
||||
)
|
||||
from .chatcompletionusermessageparam import (
|
||||
ChatCompletionUserMessageParam,
|
||||
ChatCompletionUserMessageParamTypedDict,
|
||||
)
|
||||
from openrouter.utils import get_discriminator
|
||||
from pydantic import Discriminator, Tag
|
||||
from typing import Union
|
||||
from typing_extensions import Annotated, TypeAliasType
|
||||
|
||||
|
||||
ChatCompletionMessageParamTypedDict = TypeAliasType(
|
||||
"ChatCompletionMessageParamTypedDict",
|
||||
Union[
|
||||
ChatCompletionSystemMessageParamTypedDict,
|
||||
ChatCompletionUserMessageParamTypedDict,
|
||||
ChatCompletionToolMessageParamTypedDict,
|
||||
ChatCompletionAssistantMessageParamTypedDict,
|
||||
],
|
||||
)
|
||||
r"""Chat completion message with role-based discrimination"""
|
||||
|
||||
|
||||
ChatCompletionMessageParam = Annotated[
|
||||
Union[
|
||||
Annotated[ChatCompletionSystemMessageParam, Tag("system")],
|
||||
Annotated[ChatCompletionUserMessageParam, Tag("user")],
|
||||
Annotated[ChatCompletionAssistantMessageParam, Tag("assistant")],
|
||||
Annotated[ChatCompletionToolMessageParam, Tag("tool")],
|
||||
],
|
||||
Discriminator(lambda m: get_discriminator(m, "role", "role")),
|
||||
]
|
||||
r"""Chat completion message with role-based discrimination"""
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ChatCompletionMessageToolCallType(str, Enum):
|
||||
FUNCTION = "function"
|
||||
|
||||
|
||||
class ChatCompletionMessageToolCallFunctionTypedDict(TypedDict):
|
||||
name: str
|
||||
r"""Function name to call"""
|
||||
arguments: str
|
||||
r"""Function arguments as JSON string"""
|
||||
|
||||
|
||||
class ChatCompletionMessageToolCallFunction(BaseModel):
|
||||
name: str
|
||||
r"""Function name to call"""
|
||||
|
||||
arguments: str
|
||||
r"""Function arguments as JSON string"""
|
||||
|
||||
|
||||
class ChatCompletionMessageToolCallTypedDict(TypedDict):
|
||||
r"""Tool call made by the assistant"""
|
||||
|
||||
id: str
|
||||
r"""Tool call identifier"""
|
||||
type: ChatCompletionMessageToolCallType
|
||||
function: ChatCompletionMessageToolCallFunctionTypedDict
|
||||
|
||||
|
||||
class ChatCompletionMessageToolCall(BaseModel):
|
||||
r"""Tool call made by the assistant"""
|
||||
|
||||
id: str
|
||||
r"""Tool call identifier"""
|
||||
|
||||
type: ChatCompletionMessageToolCallType
|
||||
|
||||
function: ChatCompletionMessageToolCallFunction
|
||||
@@ -0,0 +1,35 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ChatCompletionNamedToolChoiceType(str, Enum):
|
||||
FUNCTION = "function"
|
||||
|
||||
|
||||
class ChatCompletionNamedToolChoiceFunctionTypedDict(TypedDict):
|
||||
name: str
|
||||
r"""Function name to call"""
|
||||
|
||||
|
||||
class ChatCompletionNamedToolChoiceFunction(BaseModel):
|
||||
name: str
|
||||
r"""Function name to call"""
|
||||
|
||||
|
||||
class ChatCompletionNamedToolChoiceTypedDict(TypedDict):
|
||||
r"""Named tool choice for specific function"""
|
||||
|
||||
type: ChatCompletionNamedToolChoiceType
|
||||
function: ChatCompletionNamedToolChoiceFunctionTypedDict
|
||||
|
||||
|
||||
class ChatCompletionNamedToolChoice(BaseModel):
|
||||
r"""Named tool choice for specific function"""
|
||||
|
||||
type: ChatCompletionNamedToolChoiceType
|
||||
|
||||
function: ChatCompletionNamedToolChoiceFunction
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletioncontentparttext import (
|
||||
ChatCompletionContentPartText,
|
||||
ChatCompletionContentPartTextTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import List, Optional, Union
|
||||
from typing_extensions import NotRequired, TypeAliasType, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionSystemMessageParamRole(str, Enum):
|
||||
SYSTEM = "system"
|
||||
|
||||
|
||||
ChatCompletionSystemMessageParamContentTypedDict = TypeAliasType(
|
||||
"ChatCompletionSystemMessageParamContentTypedDict",
|
||||
Union[str, List[ChatCompletionContentPartTextTypedDict]],
|
||||
)
|
||||
r"""System message content"""
|
||||
|
||||
|
||||
ChatCompletionSystemMessageParamContent = TypeAliasType(
|
||||
"ChatCompletionSystemMessageParamContent",
|
||||
Union[str, List[ChatCompletionContentPartText]],
|
||||
)
|
||||
r"""System message content"""
|
||||
|
||||
|
||||
class ChatCompletionSystemMessageParamTypedDict(TypedDict):
|
||||
r"""System message for setting behavior"""
|
||||
|
||||
role: ChatCompletionSystemMessageParamRole
|
||||
content: ChatCompletionSystemMessageParamContentTypedDict
|
||||
r"""System message content"""
|
||||
name: NotRequired[str]
|
||||
r"""Optional name for the system message"""
|
||||
|
||||
|
||||
class ChatCompletionSystemMessageParam(BaseModel):
|
||||
r"""System message for setting behavior"""
|
||||
|
||||
role: ChatCompletionSystemMessageParamRole
|
||||
|
||||
content: ChatCompletionSystemMessageParamContent
|
||||
r"""System message content"""
|
||||
|
||||
name: Optional[str] = None
|
||||
r"""Optional name for the system message"""
|
||||
@@ -0,0 +1,111 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
|
||||
import pydantic
|
||||
from pydantic import model_serializer
|
||||
from typing import List
|
||||
from typing_extensions import Annotated, TypedDict
|
||||
|
||||
|
||||
class TopLogprobTypedDict(TypedDict):
|
||||
token: str
|
||||
logprob: float
|
||||
bytes_: Nullable[List[float]]
|
||||
|
||||
|
||||
class TopLogprob(BaseModel):
|
||||
token: str
|
||||
|
||||
logprob: float
|
||||
|
||||
bytes_: Annotated[Nullable[List[float]], pydantic.Field(alias="bytes")]
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = []
|
||||
nullable_fields = ["bytes"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
|
||||
|
||||
class ChatCompletionTokenLogprobTypedDict(TypedDict):
|
||||
r"""Token log probability information"""
|
||||
|
||||
token: str
|
||||
r"""The token"""
|
||||
logprob: float
|
||||
r"""Log probability of the token"""
|
||||
bytes_: Nullable[List[float]]
|
||||
r"""UTF-8 bytes of the token"""
|
||||
top_logprobs: List[TopLogprobTypedDict]
|
||||
r"""Top alternative tokens with probabilities"""
|
||||
|
||||
|
||||
class ChatCompletionTokenLogprob(BaseModel):
|
||||
r"""Token log probability information"""
|
||||
|
||||
token: str
|
||||
r"""The token"""
|
||||
|
||||
logprob: float
|
||||
r"""Log probability of the token"""
|
||||
|
||||
bytes_: Annotated[Nullable[List[float]], pydantic.Field(alias="bytes")]
|
||||
r"""UTF-8 bytes of the token"""
|
||||
|
||||
top_logprobs: List[TopLogprob]
|
||||
r"""Top alternative tokens with probabilities"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = []
|
||||
nullable_fields = ["bytes"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,60 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletiontokenlogprob import (
|
||||
ChatCompletionTokenLogprob,
|
||||
ChatCompletionTokenLogprobTypedDict,
|
||||
)
|
||||
from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
|
||||
from pydantic import model_serializer
|
||||
from typing import List
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ChatCompletionTokenLogprobsTypedDict(TypedDict):
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
content: Nullable[List[ChatCompletionTokenLogprobTypedDict]]
|
||||
r"""Log probabilities for content tokens"""
|
||||
refusal: Nullable[List[ChatCompletionTokenLogprobTypedDict]]
|
||||
r"""Log probabilities for refusal tokens"""
|
||||
|
||||
|
||||
class ChatCompletionTokenLogprobs(BaseModel):
|
||||
r"""Log probabilities for the completion"""
|
||||
|
||||
content: Nullable[List[ChatCompletionTokenLogprob]]
|
||||
r"""Log probabilities for content tokens"""
|
||||
|
||||
refusal: Nullable[List[ChatCompletionTokenLogprob]]
|
||||
r"""Log probabilities for refusal tokens"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = []
|
||||
nullable_fields = ["content", "refusal"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,102 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
from pydantic import model_serializer
|
||||
from typing import Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionToolType(str, Enum):
|
||||
FUNCTION = "function"
|
||||
|
||||
|
||||
class ParametersTypedDict(TypedDict):
|
||||
r"""Function parameters as JSON Schema object"""
|
||||
|
||||
|
||||
class Parameters(BaseModel):
|
||||
r"""Function parameters as JSON Schema object"""
|
||||
|
||||
|
||||
class ChatCompletionToolFunctionTypedDict(TypedDict):
|
||||
r"""Function definition for tool calling"""
|
||||
|
||||
name: str
|
||||
r"""Function name (a-z, A-Z, 0-9, underscores, dashes, max 64 chars)"""
|
||||
description: NotRequired[str]
|
||||
r"""Function description for the model"""
|
||||
parameters: NotRequired[ParametersTypedDict]
|
||||
r"""Function parameters as JSON Schema object"""
|
||||
strict: NotRequired[Nullable[bool]]
|
||||
r"""Enable strict schema adherence"""
|
||||
|
||||
|
||||
class ChatCompletionToolFunction(BaseModel):
|
||||
r"""Function definition for tool calling"""
|
||||
|
||||
name: str
|
||||
r"""Function name (a-z, A-Z, 0-9, underscores, dashes, max 64 chars)"""
|
||||
|
||||
description: Optional[str] = None
|
||||
r"""Function description for the model"""
|
||||
|
||||
parameters: Optional[Parameters] = None
|
||||
r"""Function parameters as JSON Schema object"""
|
||||
|
||||
strict: OptionalNullable[bool] = UNSET
|
||||
r"""Enable strict schema adherence"""
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["description", "parameters", "strict"]
|
||||
nullable_fields = ["strict"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
|
||||
|
||||
class ChatCompletionToolTypedDict(TypedDict):
|
||||
r"""Tool definition for function calling"""
|
||||
|
||||
type: ChatCompletionToolType
|
||||
function: ChatCompletionToolFunctionTypedDict
|
||||
r"""Function definition for tool calling"""
|
||||
|
||||
|
||||
class ChatCompletionTool(BaseModel):
|
||||
r"""Tool definition for function calling"""
|
||||
|
||||
type: ChatCompletionToolType
|
||||
|
||||
function: ChatCompletionToolFunction
|
||||
r"""Function definition for tool calling"""
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionnamedtoolchoice import (
|
||||
ChatCompletionNamedToolChoice,
|
||||
ChatCompletionNamedToolChoiceTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from typing import Union
|
||||
from typing_extensions import TypeAliasType
|
||||
|
||||
|
||||
class ChatCompletionToolChoiceOptionRequired(str, Enum):
|
||||
REQUIRED = "required"
|
||||
|
||||
|
||||
class ChatCompletionToolChoiceOptionAuto(str, Enum):
|
||||
AUTO = "auto"
|
||||
|
||||
|
||||
class ChatCompletionToolChoiceOptionNone(str, Enum):
|
||||
NONE = "none"
|
||||
|
||||
|
||||
ChatCompletionToolChoiceOptionTypedDict = TypeAliasType(
|
||||
"ChatCompletionToolChoiceOptionTypedDict",
|
||||
Union[
|
||||
ChatCompletionNamedToolChoiceTypedDict,
|
||||
ChatCompletionToolChoiceOptionNone,
|
||||
ChatCompletionToolChoiceOptionAuto,
|
||||
ChatCompletionToolChoiceOptionRequired,
|
||||
],
|
||||
)
|
||||
r"""Tool choice configuration"""
|
||||
|
||||
|
||||
ChatCompletionToolChoiceOption = TypeAliasType(
|
||||
"ChatCompletionToolChoiceOption",
|
||||
Union[
|
||||
ChatCompletionNamedToolChoice,
|
||||
ChatCompletionToolChoiceOptionNone,
|
||||
ChatCompletionToolChoiceOptionAuto,
|
||||
ChatCompletionToolChoiceOptionRequired,
|
||||
],
|
||||
)
|
||||
r"""Tool choice configuration"""
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletioncontentpart import (
|
||||
ChatCompletionContentPart,
|
||||
ChatCompletionContentPartTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import List, Union
|
||||
from typing_extensions import TypeAliasType, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionToolMessageParamRole(str, Enum):
|
||||
TOOL = "tool"
|
||||
|
||||
|
||||
ChatCompletionToolMessageParamContentTypedDict = TypeAliasType(
|
||||
"ChatCompletionToolMessageParamContentTypedDict",
|
||||
Union[str, List[ChatCompletionContentPartTypedDict]],
|
||||
)
|
||||
r"""Tool response content"""
|
||||
|
||||
|
||||
ChatCompletionToolMessageParamContent = TypeAliasType(
|
||||
"ChatCompletionToolMessageParamContent", Union[str, List[ChatCompletionContentPart]]
|
||||
)
|
||||
r"""Tool response content"""
|
||||
|
||||
|
||||
class ChatCompletionToolMessageParamTypedDict(TypedDict):
|
||||
r"""Tool response message"""
|
||||
|
||||
role: ChatCompletionToolMessageParamRole
|
||||
content: ChatCompletionToolMessageParamContentTypedDict
|
||||
r"""Tool response content"""
|
||||
tool_call_id: str
|
||||
r"""ID of the tool call this message responds to"""
|
||||
|
||||
|
||||
class ChatCompletionToolMessageParam(BaseModel):
|
||||
r"""Tool response message"""
|
||||
|
||||
role: ChatCompletionToolMessageParamRole
|
||||
|
||||
content: ChatCompletionToolMessageParamContent
|
||||
r"""Tool response content"""
|
||||
|
||||
tool_call_id: str
|
||||
r"""ID of the tool call this message responds to"""
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletioncontentpart import (
|
||||
ChatCompletionContentPart,
|
||||
ChatCompletionContentPartTypedDict,
|
||||
)
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import List, Optional, Union
|
||||
from typing_extensions import NotRequired, TypeAliasType, TypedDict
|
||||
|
||||
|
||||
class ChatCompletionUserMessageParamRole(str, Enum):
|
||||
USER = "user"
|
||||
|
||||
|
||||
ChatCompletionUserMessageParamContentTypedDict = TypeAliasType(
|
||||
"ChatCompletionUserMessageParamContentTypedDict",
|
||||
Union[str, List[ChatCompletionContentPartTypedDict]],
|
||||
)
|
||||
r"""User message content"""
|
||||
|
||||
|
||||
ChatCompletionUserMessageParamContent = TypeAliasType(
|
||||
"ChatCompletionUserMessageParamContent", Union[str, List[ChatCompletionContentPart]]
|
||||
)
|
||||
r"""User message content"""
|
||||
|
||||
|
||||
class ChatCompletionUserMessageParamTypedDict(TypedDict):
|
||||
r"""User message"""
|
||||
|
||||
role: ChatCompletionUserMessageParamRole
|
||||
content: ChatCompletionUserMessageParamContentTypedDict
|
||||
r"""User message content"""
|
||||
name: NotRequired[str]
|
||||
r"""Optional name for the user"""
|
||||
|
||||
|
||||
class ChatCompletionUserMessageParam(BaseModel):
|
||||
r"""User message"""
|
||||
|
||||
role: ChatCompletionUserMessageParamRole
|
||||
|
||||
content: ChatCompletionUserMessageParamContent
|
||||
r"""User message content"""
|
||||
|
||||
name: Optional[str] = None
|
||||
r"""Optional name for the user"""
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from openrouter.types import BaseModel
|
||||
from typing import Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class CompletionTokensDetailsTypedDict(TypedDict):
|
||||
r"""Detailed completion token usage"""
|
||||
|
||||
reasoning_tokens: NotRequired[float]
|
||||
r"""Tokens used for reasoning"""
|
||||
audio_tokens: NotRequired[float]
|
||||
r"""Tokens used for audio output"""
|
||||
accepted_prediction_tokens: NotRequired[float]
|
||||
r"""Accepted prediction tokens"""
|
||||
rejected_prediction_tokens: NotRequired[float]
|
||||
r"""Rejected prediction tokens"""
|
||||
|
||||
|
||||
class CompletionTokensDetails(BaseModel):
|
||||
r"""Detailed completion token usage"""
|
||||
|
||||
reasoning_tokens: Optional[float] = None
|
||||
r"""Tokens used for reasoning"""
|
||||
|
||||
audio_tokens: Optional[float] = None
|
||||
r"""Tokens used for audio output"""
|
||||
|
||||
accepted_prediction_tokens: Optional[float] = None
|
||||
r"""Accepted prediction tokens"""
|
||||
|
||||
rejected_prediction_tokens: Optional[float] = None
|
||||
r"""Rejected prediction tokens"""
|
||||
|
||||
|
||||
class PromptTokensDetailsTypedDict(TypedDict):
|
||||
r"""Detailed prompt token usage"""
|
||||
|
||||
cached_tokens: NotRequired[float]
|
||||
r"""Cached prompt tokens"""
|
||||
audio_tokens: NotRequired[float]
|
||||
r"""Audio input tokens"""
|
||||
|
||||
|
||||
class PromptTokensDetails(BaseModel):
|
||||
r"""Detailed prompt token usage"""
|
||||
|
||||
cached_tokens: Optional[float] = None
|
||||
r"""Cached prompt tokens"""
|
||||
|
||||
audio_tokens: Optional[float] = None
|
||||
r"""Audio input tokens"""
|
||||
|
||||
|
||||
class CompletionUsageTypedDict(TypedDict):
|
||||
r"""Token usage statistics"""
|
||||
|
||||
completion_tokens: float
|
||||
r"""Number of tokens in the completion"""
|
||||
prompt_tokens: float
|
||||
r"""Number of tokens in the prompt"""
|
||||
total_tokens: float
|
||||
r"""Total number of tokens"""
|
||||
completion_tokens_details: NotRequired[CompletionTokensDetailsTypedDict]
|
||||
r"""Detailed completion token usage"""
|
||||
prompt_tokens_details: NotRequired[PromptTokensDetailsTypedDict]
|
||||
r"""Detailed prompt token usage"""
|
||||
|
||||
|
||||
class CompletionUsage(BaseModel):
|
||||
r"""Token usage statistics"""
|
||||
|
||||
completion_tokens: float
|
||||
r"""Number of tokens in the completion"""
|
||||
|
||||
prompt_tokens: float
|
||||
r"""Number of tokens in the prompt"""
|
||||
|
||||
total_tokens: float
|
||||
r"""Total number of tokens"""
|
||||
|
||||
completion_tokens_details: Optional[CompletionTokensDetails] = None
|
||||
r"""Detailed completion token usage"""
|
||||
|
||||
prompt_tokens_details: Optional[PromptTokensDetails] = None
|
||||
r"""Detailed prompt token usage"""
|
||||
@@ -0,0 +1,89 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import List, Optional, Union
|
||||
from typing_extensions import NotRequired, TypeAliasType, TypedDict
|
||||
|
||||
|
||||
class TypeFile(str, Enum):
|
||||
FILE = "file"
|
||||
|
||||
|
||||
class ContentTypeImageURL(str, Enum):
|
||||
IMAGE_URL = "image_url"
|
||||
|
||||
|
||||
class FileAnnotationDetailImageURLTypedDict(TypedDict):
|
||||
url: str
|
||||
|
||||
|
||||
class FileAnnotationDetailImageURL(BaseModel):
|
||||
url: str
|
||||
|
||||
|
||||
class ContentImageURLTypedDict(TypedDict):
|
||||
type: ContentTypeImageURL
|
||||
image_url: FileAnnotationDetailImageURLTypedDict
|
||||
|
||||
|
||||
class ContentImageURL(BaseModel):
|
||||
type: ContentTypeImageURL
|
||||
|
||||
image_url: FileAnnotationDetailImageURL
|
||||
|
||||
|
||||
class ContentTypeText(str, Enum):
|
||||
TEXT = "text"
|
||||
|
||||
|
||||
class ContentTextTypedDict(TypedDict):
|
||||
type: ContentTypeText
|
||||
text: str
|
||||
|
||||
|
||||
class ContentText(BaseModel):
|
||||
type: ContentTypeText
|
||||
|
||||
text: str
|
||||
|
||||
|
||||
FileAnnotationDetailContentUnionTypedDict = TypeAliasType(
|
||||
"FileAnnotationDetailContentUnionTypedDict",
|
||||
Union[ContentTextTypedDict, ContentImageURLTypedDict],
|
||||
)
|
||||
|
||||
|
||||
FileAnnotationDetailContentUnion = TypeAliasType(
|
||||
"FileAnnotationDetailContentUnion", Union[ContentText, ContentImageURL]
|
||||
)
|
||||
|
||||
|
||||
class FileTypedDict(TypedDict):
|
||||
hash: str
|
||||
content: List[FileAnnotationDetailContentUnionTypedDict]
|
||||
name: NotRequired[str]
|
||||
|
||||
|
||||
class File(BaseModel):
|
||||
hash: str
|
||||
|
||||
content: List[FileAnnotationDetailContentUnion]
|
||||
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
class FileAnnotationDetailTypedDict(TypedDict):
|
||||
r"""File annotation with content"""
|
||||
|
||||
type: TypeFile
|
||||
file: FileTypedDict
|
||||
|
||||
|
||||
class FileAnnotationDetail(BaseModel):
|
||||
r"""File annotation with content"""
|
||||
|
||||
type: TypeFile
|
||||
|
||||
file: File
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .reasoningdetailencrypted import (
|
||||
ReasoningDetailEncrypted,
|
||||
ReasoningDetailEncryptedTypedDict,
|
||||
)
|
||||
from .reasoningdetailsummary import (
|
||||
ReasoningDetailSummary,
|
||||
ReasoningDetailSummaryTypedDict,
|
||||
)
|
||||
from .reasoningdetailtext import ReasoningDetailText, ReasoningDetailTextTypedDict
|
||||
from openrouter.utils import get_discriminator
|
||||
from pydantic import Discriminator, Tag
|
||||
from typing import Union
|
||||
from typing_extensions import Annotated, TypeAliasType
|
||||
|
||||
|
||||
ReasoningDetailTypedDict = TypeAliasType(
|
||||
"ReasoningDetailTypedDict",
|
||||
Union[
|
||||
ReasoningDetailSummaryTypedDict,
|
||||
ReasoningDetailEncryptedTypedDict,
|
||||
ReasoningDetailTextTypedDict,
|
||||
],
|
||||
)
|
||||
r"""Reasoning detail information"""
|
||||
|
||||
|
||||
ReasoningDetail = Annotated[
|
||||
Union[
|
||||
Annotated[ReasoningDetailSummary, Tag("reasoning.summary")],
|
||||
Annotated[ReasoningDetailEncrypted, Tag("reasoning.encrypted")],
|
||||
Annotated[ReasoningDetailText, Tag("reasoning.text")],
|
||||
],
|
||||
Discriminator(lambda m: get_discriminator(m, "type", "type")),
|
||||
]
|
||||
r"""Reasoning detail information"""
|
||||
@@ -0,0 +1,81 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
import pydantic
|
||||
from pydantic import model_serializer
|
||||
from typing import Optional
|
||||
from typing_extensions import Annotated, NotRequired, TypedDict
|
||||
|
||||
|
||||
class ReasoningDetailEncryptedType(str, Enum):
|
||||
REASONING_ENCRYPTED = "reasoning.encrypted"
|
||||
|
||||
|
||||
class ReasoningDetailEncryptedFormat(str, Enum):
|
||||
UNKNOWN = "unknown"
|
||||
OPENAI_RESPONSES_V1 = "openai-responses-v1"
|
||||
ANTHROPIC_CLAUDE_V1 = "anthropic-claude-v1"
|
||||
|
||||
|
||||
class ReasoningDetailEncryptedTypedDict(TypedDict):
|
||||
r"""Encrypted reasoning detail"""
|
||||
|
||||
type: ReasoningDetailEncryptedType
|
||||
data: str
|
||||
id: NotRequired[Nullable[str]]
|
||||
format_: NotRequired[Nullable[ReasoningDetailEncryptedFormat]]
|
||||
index: NotRequired[float]
|
||||
|
||||
|
||||
class ReasoningDetailEncrypted(BaseModel):
|
||||
r"""Encrypted reasoning detail"""
|
||||
|
||||
type: ReasoningDetailEncryptedType
|
||||
|
||||
data: str
|
||||
|
||||
id: OptionalNullable[str] = UNSET
|
||||
|
||||
format_: Annotated[
|
||||
OptionalNullable[ReasoningDetailEncryptedFormat], pydantic.Field(alias="format")
|
||||
] = ReasoningDetailEncryptedFormat.ANTHROPIC_CLAUDE_V1
|
||||
|
||||
index: Optional[float] = None
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["id", "format", "index"]
|
||||
nullable_fields = ["id", "format"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,81 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
import pydantic
|
||||
from pydantic import model_serializer
|
||||
from typing import Optional
|
||||
from typing_extensions import Annotated, NotRequired, TypedDict
|
||||
|
||||
|
||||
class ReasoningDetailSummaryType(str, Enum):
|
||||
REASONING_SUMMARY = "reasoning.summary"
|
||||
|
||||
|
||||
class ReasoningDetailSummaryFormat(str, Enum):
|
||||
UNKNOWN = "unknown"
|
||||
OPENAI_RESPONSES_V1 = "openai-responses-v1"
|
||||
ANTHROPIC_CLAUDE_V1 = "anthropic-claude-v1"
|
||||
|
||||
|
||||
class ReasoningDetailSummaryTypedDict(TypedDict):
|
||||
r"""Reasoning summary detail"""
|
||||
|
||||
type: ReasoningDetailSummaryType
|
||||
summary: str
|
||||
id: NotRequired[Nullable[str]]
|
||||
format_: NotRequired[Nullable[ReasoningDetailSummaryFormat]]
|
||||
index: NotRequired[float]
|
||||
|
||||
|
||||
class ReasoningDetailSummary(BaseModel):
|
||||
r"""Reasoning summary detail"""
|
||||
|
||||
type: ReasoningDetailSummaryType
|
||||
|
||||
summary: str
|
||||
|
||||
id: OptionalNullable[str] = UNSET
|
||||
|
||||
format_: Annotated[
|
||||
OptionalNullable[ReasoningDetailSummaryFormat], pydantic.Field(alias="format")
|
||||
] = ReasoningDetailSummaryFormat.ANTHROPIC_CLAUDE_V1
|
||||
|
||||
index: Optional[float] = None
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["id", "format", "index"]
|
||||
nullable_fields = ["id", "format"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,84 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
import pydantic
|
||||
from pydantic import model_serializer
|
||||
from typing import Optional
|
||||
from typing_extensions import Annotated, NotRequired, TypedDict
|
||||
|
||||
|
||||
class ReasoningDetailTextType(str, Enum):
|
||||
REASONING_TEXT = "reasoning.text"
|
||||
|
||||
|
||||
class ReasoningDetailTextFormat(str, Enum):
|
||||
UNKNOWN = "unknown"
|
||||
OPENAI_RESPONSES_V1 = "openai-responses-v1"
|
||||
ANTHROPIC_CLAUDE_V1 = "anthropic-claude-v1"
|
||||
|
||||
|
||||
class ReasoningDetailTextTypedDict(TypedDict):
|
||||
r"""Text reasoning detail"""
|
||||
|
||||
type: ReasoningDetailTextType
|
||||
text: NotRequired[Nullable[str]]
|
||||
signature: NotRequired[Nullable[str]]
|
||||
id: NotRequired[Nullable[str]]
|
||||
format_: NotRequired[Nullable[ReasoningDetailTextFormat]]
|
||||
index: NotRequired[float]
|
||||
|
||||
|
||||
class ReasoningDetailText(BaseModel):
|
||||
r"""Text reasoning detail"""
|
||||
|
||||
type: ReasoningDetailTextType
|
||||
|
||||
text: OptionalNullable[str] = UNSET
|
||||
|
||||
signature: OptionalNullable[str] = UNSET
|
||||
|
||||
id: OptionalNullable[str] = UNSET
|
||||
|
||||
format_: Annotated[
|
||||
OptionalNullable[ReasoningDetailTextFormat], pydantic.Field(alias="format")
|
||||
] = ReasoningDetailTextFormat.ANTHROPIC_CLAUDE_V1
|
||||
|
||||
index: Optional[float] = None
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_model(self, handler):
|
||||
optional_fields = ["text", "signature", "id", "format", "index"]
|
||||
nullable_fields = ["text", "signature", "id", "format"]
|
||||
null_default_fields = []
|
||||
|
||||
serialized = handler(self)
|
||||
|
||||
m = {}
|
||||
|
||||
for n, f in type(self).model_fields.items():
|
||||
k = f.alias or n
|
||||
val = serialized.get(k)
|
||||
serialized.pop(k, None)
|
||||
|
||||
optional_nullable = k in optional_fields and k in nullable_fields
|
||||
is_set = (
|
||||
self.__pydantic_fields_set__.intersection({n})
|
||||
or k in null_default_fields
|
||||
) # pylint: disable=no-member
|
||||
|
||||
if val is not None and val != UNSET_SENTINEL:
|
||||
m[k] = val
|
||||
elif val != UNSET_SENTINEL and (
|
||||
not k in optional_fields or (optional_nullable and is_set)
|
||||
):
|
||||
m[k] = val
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from openrouter.types import BaseModel
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ResponseFormatJSONSchemaSchemaTypedDict(TypedDict):
|
||||
r"""The schema for the response format, described as a JSON Schema object"""
|
||||
|
||||
|
||||
class ResponseFormatJSONSchemaSchema(BaseModel):
|
||||
r"""The schema for the response format, described as a JSON Schema object"""
|
||||
@@ -0,0 +1,25 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from openrouter.types import BaseModel
|
||||
from openrouter.utils import FieldMetadata, SecurityMetadata
|
||||
from typing import Optional
|
||||
from typing_extensions import Annotated, NotRequired, TypedDict
|
||||
|
||||
|
||||
class SecurityTypedDict(TypedDict):
|
||||
bearer_auth: NotRequired[str]
|
||||
|
||||
|
||||
class Security(BaseModel):
|
||||
bearer_auth: Annotated[
|
||||
Optional[str],
|
||||
FieldMetadata(
|
||||
security=SecurityMetadata(
|
||||
scheme=True,
|
||||
scheme_type="http",
|
||||
sub_type="bearer",
|
||||
field_name="Authorization",
|
||||
)
|
||||
),
|
||||
] = None
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from .chatcompletionchunk import ChatCompletionChunk, ChatCompletionChunkTypedDict
|
||||
from openrouter.types import BaseModel
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class StreamChatCompletionResponseBodyTypedDict(TypedDict):
|
||||
r"""Successful chat completion response"""
|
||||
|
||||
data: ChatCompletionChunkTypedDict
|
||||
r"""Streaming chat completion chunk"""
|
||||
|
||||
|
||||
class StreamChatCompletionResponseBody(BaseModel):
|
||||
r"""Successful chat completion response"""
|
||||
|
||||
data: ChatCompletionChunk
|
||||
r"""Streaming chat completion chunk"""
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from openrouter.types import BaseModel
|
||||
from typing import Optional
|
||||
from typing_extensions import NotRequired, TypedDict
|
||||
|
||||
|
||||
class URLCitationAnnotationDetailType(str, Enum):
|
||||
URL_CITATION = "url_citation"
|
||||
|
||||
|
||||
class URLCitationTypedDict(TypedDict):
|
||||
end_index: float
|
||||
start_index: float
|
||||
title: str
|
||||
url: str
|
||||
content: NotRequired[str]
|
||||
|
||||
|
||||
class URLCitation(BaseModel):
|
||||
end_index: float
|
||||
|
||||
start_index: float
|
||||
|
||||
title: str
|
||||
|
||||
url: str
|
||||
|
||||
content: Optional[str] = None
|
||||
|
||||
|
||||
class URLCitationAnnotationDetailTypedDict(TypedDict):
|
||||
r"""URL citation annotation"""
|
||||
|
||||
type: URLCitationAnnotationDetailType
|
||||
url_citation: URLCitationTypedDict
|
||||
|
||||
|
||||
class URLCitationAnnotationDetail(BaseModel):
|
||||
r"""URL citation annotation"""
|
||||
|
||||
type: URLCitationAnnotationDetailType
|
||||
|
||||
url_citation: URLCitation
|
||||
@@ -0,0 +1 @@
|
||||
# Marker file for PEP 561. The package enables type hints.
|
||||
@@ -0,0 +1,174 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from .basesdk import BaseSDK
|
||||
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
|
||||
from .sdkconfiguration import SDKConfiguration
|
||||
from .utils.logger import Logger, get_default_logger
|
||||
from .utils.retries import RetryConfig
|
||||
import httpx
|
||||
import importlib
|
||||
from openrouter import models, utils
|
||||
from openrouter._hooks import SDKHooks
|
||||
from openrouter.types import OptionalNullable, UNSET
|
||||
from typing import Any, Callable, Dict, List, Optional, TYPE_CHECKING, Union, cast
|
||||
import weakref
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from openrouter.chat import Chat
|
||||
|
||||
|
||||
class OpenRouter(BaseSDK):
|
||||
r"""OpenRouter Chat Completions API: OpenAI-compatible Chat Completions API with additional OpenRouter features
|
||||
https://openrouter.ai/docs - OpenRouter Documentation
|
||||
"""
|
||||
|
||||
chat: "Chat"
|
||||
r"""Chat completion operations"""
|
||||
_sub_sdk_map = {
|
||||
"chat": ("openrouter.chat", "Chat"),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bearer_auth: Optional[Union[Optional[str], Callable[[], Optional[str]]]] = None,
|
||||
provider_url: Optional[str] = None,
|
||||
server_idx: Optional[int] = None,
|
||||
server_url: Optional[str] = None,
|
||||
url_params: Optional[Dict[str, str]] = None,
|
||||
client: Optional[HttpClient] = None,
|
||||
async_client: Optional[AsyncHttpClient] = None,
|
||||
retry_config: OptionalNullable[RetryConfig] = UNSET,
|
||||
timeout_ms: Optional[int] = None,
|
||||
debug_logger: Optional[Logger] = None,
|
||||
) -> None:
|
||||
r"""Instantiates the SDK configuring it with the provided parameters.
|
||||
|
||||
:param bearer_auth: The bearer_auth required for authentication
|
||||
:param provider_url: Allows setting the provider_url variable for url substitution
|
||||
:param server_idx: The index of the server to use for all methods
|
||||
:param server_url: The server URL to use for all methods
|
||||
:param url_params: Parameters to optionally template the server URL with
|
||||
:param client: The HTTP client to use for all synchronous methods
|
||||
:param async_client: The Async HTTP client to use for all asynchronous methods
|
||||
:param retry_config: The retry configuration to use for all supported methods
|
||||
:param timeout_ms: Optional request timeout applied to each operation in milliseconds
|
||||
"""
|
||||
client_supplied = True
|
||||
if client is None:
|
||||
client = httpx.Client()
|
||||
client_supplied = False
|
||||
|
||||
assert issubclass(
|
||||
type(client), HttpClient
|
||||
), "The provided client must implement the HttpClient protocol."
|
||||
|
||||
async_client_supplied = True
|
||||
if async_client is None:
|
||||
async_client = httpx.AsyncClient()
|
||||
async_client_supplied = False
|
||||
|
||||
if debug_logger is None:
|
||||
debug_logger = get_default_logger()
|
||||
|
||||
assert issubclass(
|
||||
type(async_client), AsyncHttpClient
|
||||
), "The provided async_client must implement the AsyncHttpClient protocol."
|
||||
|
||||
security: Any = None
|
||||
if callable(bearer_auth):
|
||||
# pylint: disable=unnecessary-lambda-assignment
|
||||
security = lambda: models.Security(bearer_auth=bearer_auth())
|
||||
else:
|
||||
security = models.Security(bearer_auth=bearer_auth)
|
||||
|
||||
if server_url is not None:
|
||||
if url_params is not None:
|
||||
server_url = utils.template_url(server_url, url_params)
|
||||
server_defaults: List[Dict[str, str]] = [
|
||||
{
|
||||
"provider_url": provider_url or "openrouter.ai",
|
||||
},
|
||||
]
|
||||
|
||||
BaseSDK.__init__(
|
||||
self,
|
||||
SDKConfiguration(
|
||||
client=client,
|
||||
client_supplied=client_supplied,
|
||||
async_client=async_client,
|
||||
async_client_supplied=async_client_supplied,
|
||||
security=security,
|
||||
server_url=server_url,
|
||||
server_idx=server_idx,
|
||||
server_defaults=server_defaults,
|
||||
retry_config=retry_config,
|
||||
timeout_ms=timeout_ms,
|
||||
debug_logger=debug_logger,
|
||||
),
|
||||
)
|
||||
|
||||
hooks = SDKHooks()
|
||||
|
||||
# pylint: disable=protected-access
|
||||
self.sdk_configuration.__dict__["_hooks"] = hooks
|
||||
|
||||
self.sdk_configuration = hooks.sdk_init(self.sdk_configuration)
|
||||
|
||||
weakref.finalize(
|
||||
self,
|
||||
close_clients,
|
||||
cast(ClientOwner, self.sdk_configuration),
|
||||
self.sdk_configuration.client,
|
||||
self.sdk_configuration.client_supplied,
|
||||
self.sdk_configuration.async_client,
|
||||
self.sdk_configuration.async_client_supplied,
|
||||
)
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name in self._sub_sdk_map:
|
||||
module_path, class_name = self._sub_sdk_map[name]
|
||||
try:
|
||||
module = importlib.import_module(module_path)
|
||||
klass = getattr(module, class_name)
|
||||
instance = klass(self.sdk_configuration)
|
||||
setattr(self, name, instance)
|
||||
return instance
|
||||
except ImportError as e:
|
||||
raise AttributeError(
|
||||
f"Failed to import module {module_path} for attribute {name}: {e}"
|
||||
) from e
|
||||
except AttributeError as e:
|
||||
raise AttributeError(
|
||||
f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
|
||||
) from e
|
||||
|
||||
raise AttributeError(
|
||||
f"'{type(self).__name__}' object has no attribute '{name}'"
|
||||
)
|
||||
|
||||
def __dir__(self):
|
||||
default_attrs = list(super().__dir__())
|
||||
lazy_attrs = list(self._sub_sdk_map.keys())
|
||||
return sorted(list(set(default_attrs + lazy_attrs)))
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if (
|
||||
self.sdk_configuration.client is not None
|
||||
and not self.sdk_configuration.client_supplied
|
||||
):
|
||||
self.sdk_configuration.client.close()
|
||||
self.sdk_configuration.client = None
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
if (
|
||||
self.sdk_configuration.async_client is not None
|
||||
and not self.sdk_configuration.async_client_supplied
|
||||
):
|
||||
await self.sdk_configuration.async_client.aclose()
|
||||
self.sdk_configuration.async_client = None
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from ._version import (
|
||||
__gen_version__,
|
||||
__openapi_doc_version__,
|
||||
__user_agent__,
|
||||
__version__,
|
||||
)
|
||||
from .httpclient import AsyncHttpClient, HttpClient
|
||||
from .utils import Logger, RetryConfig, remove_suffix
|
||||
from dataclasses import dataclass, field
|
||||
from openrouter import models
|
||||
from openrouter.types import OptionalNullable, UNSET
|
||||
from pydantic import Field
|
||||
from typing import Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
|
||||
SERVERS = [
|
||||
"https://{provider_url}/api/v1",
|
||||
# Production server
|
||||
]
|
||||
"""Contains the list of servers available to the SDK"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class SDKConfiguration:
|
||||
client: Union[HttpClient, None]
|
||||
client_supplied: bool
|
||||
async_client: Union[AsyncHttpClient, None]
|
||||
async_client_supplied: bool
|
||||
debug_logger: Logger
|
||||
security: Optional[Union[models.Security, Callable[[], models.Security]]] = None
|
||||
server_url: Optional[str] = ""
|
||||
server_idx: Optional[int] = 0
|
||||
server_defaults: List[Dict[str, str]] = field(default_factory=List)
|
||||
language: str = "python"
|
||||
openapi_doc_version: str = __openapi_doc_version__
|
||||
sdk_version: str = __version__
|
||||
gen_version: str = __gen_version__
|
||||
user_agent: str = __user_agent__
|
||||
retry_config: OptionalNullable[RetryConfig] = Field(default_factory=lambda: UNSET)
|
||||
timeout_ms: Optional[int] = None
|
||||
|
||||
def get_server_details(self) -> Tuple[str, Dict[str, str]]:
|
||||
if self.server_url is not None and self.server_url:
|
||||
return remove_suffix(self.server_url, "/"), {}
|
||||
if self.server_idx is None:
|
||||
self.server_idx = 0
|
||||
|
||||
return SERVERS[self.server_idx], self.server_defaults[self.server_idx]
|
||||
@@ -0,0 +1,21 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from .basemodel import (
|
||||
BaseModel,
|
||||
Nullable,
|
||||
OptionalNullable,
|
||||
UnrecognizedInt,
|
||||
UnrecognizedStr,
|
||||
UNSET,
|
||||
UNSET_SENTINEL,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"BaseModel",
|
||||
"Nullable",
|
||||
"OptionalNullable",
|
||||
"UnrecognizedInt",
|
||||
"UnrecognizedStr",
|
||||
"UNSET",
|
||||
"UNSET_SENTINEL",
|
||||
]
|
||||
@@ -0,0 +1,39 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from pydantic import ConfigDict, model_serializer
|
||||
from pydantic import BaseModel as PydanticBaseModel
|
||||
from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union
|
||||
from typing_extensions import TypeAliasType, TypeAlias
|
||||
|
||||
|
||||
class BaseModel(PydanticBaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True, arbitrary_types_allowed=True, protected_namespaces=()
|
||||
)
|
||||
|
||||
|
||||
class Unset(BaseModel):
|
||||
@model_serializer(mode="plain")
|
||||
def serialize_model(self):
|
||||
return UNSET_SENTINEL
|
||||
|
||||
def __bool__(self) -> Literal[False]:
|
||||
return False
|
||||
|
||||
|
||||
UNSET = Unset()
|
||||
UNSET_SENTINEL = "~?~unset~?~sentinel~?~"
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
if TYPE_CHECKING:
|
||||
Nullable: TypeAlias = Union[T, None]
|
||||
OptionalNullable: TypeAlias = Union[Optional[Nullable[T]], Unset]
|
||||
else:
|
||||
Nullable = TypeAliasType("Nullable", Union[T, None], type_params=(T,))
|
||||
OptionalNullable = TypeAliasType(
|
||||
"OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
|
||||
)
|
||||
|
||||
UnrecognizedInt: TypeAlias = int
|
||||
UnrecognizedStr: TypeAlias = str
|
||||
@@ -0,0 +1,188 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from importlib import import_module
|
||||
import builtins
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .annotations import get_discriminator
|
||||
from .datetimes import parse_datetime
|
||||
from .enums import OpenEnumMeta
|
||||
from .headers import get_headers, get_response_headers
|
||||
from .metadata import (
|
||||
FieldMetadata,
|
||||
find_metadata,
|
||||
FormMetadata,
|
||||
HeaderMetadata,
|
||||
MultipartFormMetadata,
|
||||
PathParamMetadata,
|
||||
QueryParamMetadata,
|
||||
RequestMetadata,
|
||||
SecurityMetadata,
|
||||
)
|
||||
from .queryparams import get_query_params
|
||||
from .retries import BackoffStrategy, Retries, retry, retry_async, RetryConfig
|
||||
from .requestbodies import serialize_request_body, SerializedRequestBody
|
||||
from .security import get_security, get_security_from_env
|
||||
|
||||
from .serializers import (
|
||||
get_pydantic_model,
|
||||
marshal_json,
|
||||
unmarshal,
|
||||
unmarshal_json,
|
||||
serialize_decimal,
|
||||
serialize_float,
|
||||
serialize_int,
|
||||
stream_to_text,
|
||||
stream_to_text_async,
|
||||
stream_to_bytes,
|
||||
stream_to_bytes_async,
|
||||
validate_const,
|
||||
validate_decimal,
|
||||
validate_float,
|
||||
validate_int,
|
||||
validate_open_enum,
|
||||
)
|
||||
from .url import generate_url, template_url, remove_suffix
|
||||
from .values import (
|
||||
get_global_from_env,
|
||||
match_content_type,
|
||||
match_status_codes,
|
||||
match_response,
|
||||
cast_partial,
|
||||
)
|
||||
from .logger import Logger, get_body_content, get_default_logger
|
||||
|
||||
__all__ = [
|
||||
"BackoffStrategy",
|
||||
"FieldMetadata",
|
||||
"find_metadata",
|
||||
"FormMetadata",
|
||||
"generate_url",
|
||||
"get_body_content",
|
||||
"get_default_logger",
|
||||
"get_discriminator",
|
||||
"parse_datetime",
|
||||
"get_global_from_env",
|
||||
"get_headers",
|
||||
"get_pydantic_model",
|
||||
"get_query_params",
|
||||
"get_response_headers",
|
||||
"get_security",
|
||||
"get_security_from_env",
|
||||
"HeaderMetadata",
|
||||
"Logger",
|
||||
"marshal_json",
|
||||
"match_content_type",
|
||||
"match_status_codes",
|
||||
"match_response",
|
||||
"MultipartFormMetadata",
|
||||
"OpenEnumMeta",
|
||||
"PathParamMetadata",
|
||||
"QueryParamMetadata",
|
||||
"remove_suffix",
|
||||
"Retries",
|
||||
"retry",
|
||||
"retry_async",
|
||||
"RetryConfig",
|
||||
"RequestMetadata",
|
||||
"SecurityMetadata",
|
||||
"serialize_decimal",
|
||||
"serialize_float",
|
||||
"serialize_int",
|
||||
"serialize_request_body",
|
||||
"SerializedRequestBody",
|
||||
"stream_to_text",
|
||||
"stream_to_text_async",
|
||||
"stream_to_bytes",
|
||||
"stream_to_bytes_async",
|
||||
"template_url",
|
||||
"unmarshal",
|
||||
"unmarshal_json",
|
||||
"validate_decimal",
|
||||
"validate_const",
|
||||
"validate_float",
|
||||
"validate_int",
|
||||
"validate_open_enum",
|
||||
"cast_partial",
|
||||
]
|
||||
|
||||
_dynamic_imports: dict[str, str] = {
|
||||
"BackoffStrategy": ".retries",
|
||||
"FieldMetadata": ".metadata",
|
||||
"find_metadata": ".metadata",
|
||||
"FormMetadata": ".metadata",
|
||||
"generate_url": ".url",
|
||||
"get_body_content": ".logger",
|
||||
"get_default_logger": ".logger",
|
||||
"get_discriminator": ".annotations",
|
||||
"parse_datetime": ".datetimes",
|
||||
"get_global_from_env": ".values",
|
||||
"get_headers": ".headers",
|
||||
"get_pydantic_model": ".serializers",
|
||||
"get_query_params": ".queryparams",
|
||||
"get_response_headers": ".headers",
|
||||
"get_security": ".security",
|
||||
"get_security_from_env": ".security",
|
||||
"HeaderMetadata": ".metadata",
|
||||
"Logger": ".logger",
|
||||
"marshal_json": ".serializers",
|
||||
"match_content_type": ".values",
|
||||
"match_status_codes": ".values",
|
||||
"match_response": ".values",
|
||||
"MultipartFormMetadata": ".metadata",
|
||||
"OpenEnumMeta": ".enums",
|
||||
"PathParamMetadata": ".metadata",
|
||||
"QueryParamMetadata": ".metadata",
|
||||
"remove_suffix": ".url",
|
||||
"Retries": ".retries",
|
||||
"retry": ".retries",
|
||||
"retry_async": ".retries",
|
||||
"RetryConfig": ".retries",
|
||||
"RequestMetadata": ".metadata",
|
||||
"SecurityMetadata": ".metadata",
|
||||
"serialize_decimal": ".serializers",
|
||||
"serialize_float": ".serializers",
|
||||
"serialize_int": ".serializers",
|
||||
"serialize_request_body": ".requestbodies",
|
||||
"SerializedRequestBody": ".requestbodies",
|
||||
"stream_to_text": ".serializers",
|
||||
"stream_to_text_async": ".serializers",
|
||||
"stream_to_bytes": ".serializers",
|
||||
"stream_to_bytes_async": ".serializers",
|
||||
"template_url": ".url",
|
||||
"unmarshal": ".serializers",
|
||||
"unmarshal_json": ".serializers",
|
||||
"validate_decimal": ".serializers",
|
||||
"validate_const": ".serializers",
|
||||
"validate_float": ".serializers",
|
||||
"validate_int": ".serializers",
|
||||
"validate_open_enum": ".serializers",
|
||||
"cast_partial": ".values",
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(attr_name: str) -> object:
|
||||
module_name = _dynamic_imports.get(attr_name)
|
||||
if module_name is None:
|
||||
raise AttributeError(
|
||||
f"no {attr_name} found in _dynamic_imports, module name -> {__name__} "
|
||||
)
|
||||
|
||||
try:
|
||||
module = import_module(module_name, __package__)
|
||||
result = getattr(module, attr_name)
|
||||
return result
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
f"Failed to import {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
except AttributeError as e:
|
||||
raise AttributeError(
|
||||
f"Failed to get {attr_name} from {module_name}: {e}"
|
||||
) from e
|
||||
|
||||
|
||||
def __dir__():
|
||||
lazy_attrs = builtins.list(_dynamic_imports.keys())
|
||||
return builtins.sorted(lazy_attrs)
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any, Optional
|
||||
|
||||
def get_discriminator(model: Any, fieldname: str, key: str) -> str:
|
||||
"""
|
||||
Recursively search for the discriminator attribute in a model.
|
||||
|
||||
Args:
|
||||
model (Any): The model to search within.
|
||||
fieldname (str): The name of the field to search for.
|
||||
key (str): The key to search for in dictionaries.
|
||||
|
||||
Returns:
|
||||
str: The name of the discriminator attribute.
|
||||
|
||||
Raises:
|
||||
ValueError: If the discriminator attribute is not found.
|
||||
"""
|
||||
upper_fieldname = fieldname.upper()
|
||||
|
||||
def get_field_discriminator(field: Any) -> Optional[str]:
|
||||
"""Search for the discriminator attribute in a given field."""
|
||||
|
||||
if isinstance(field, dict):
|
||||
if key in field:
|
||||
return f'{field[key]}'
|
||||
|
||||
if hasattr(field, fieldname):
|
||||
attr = getattr(field, fieldname)
|
||||
if isinstance(attr, Enum):
|
||||
return f'{attr.value}'
|
||||
return f'{attr}'
|
||||
|
||||
if hasattr(field, upper_fieldname):
|
||||
attr = getattr(field, upper_fieldname)
|
||||
if isinstance(attr, Enum):
|
||||
return f'{attr.value}'
|
||||
return f'{attr}'
|
||||
|
||||
return None
|
||||
|
||||
|
||||
if isinstance(model, list):
|
||||
for field in model:
|
||||
discriminator = get_field_discriminator(field)
|
||||
if discriminator is not None:
|
||||
return discriminator
|
||||
|
||||
discriminator = get_field_discriminator(model)
|
||||
if discriminator is not None:
|
||||
return discriminator
|
||||
|
||||
raise ValueError(f'Could not find discriminator field {fieldname} in {model}')
|
||||
@@ -0,0 +1,23 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from datetime import datetime
|
||||
import sys
|
||||
|
||||
|
||||
def parse_datetime(datetime_string: str) -> datetime:
|
||||
"""
|
||||
Convert a RFC 3339 / ISO 8601 formatted string into a datetime object.
|
||||
Python versions 3.11 and later support parsing RFC 3339 directly with
|
||||
datetime.fromisoformat(), but for earlier versions, this function
|
||||
encapsulates the necessary extra logic.
|
||||
"""
|
||||
# Python 3.11 and later can parse RFC 3339 directly
|
||||
if sys.version_info >= (3, 11):
|
||||
return datetime.fromisoformat(datetime_string)
|
||||
|
||||
# For Python 3.10 and earlier, a common ValueError is trailing 'Z' suffix,
|
||||
# so fix that upfront.
|
||||
if datetime_string.endswith("Z"):
|
||||
datetime_string = datetime_string[:-1] + "+00:00"
|
||||
|
||||
return datetime.fromisoformat(datetime_string)
|
||||
@@ -0,0 +1,74 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import enum
|
||||
import sys
|
||||
|
||||
class OpenEnumMeta(enum.EnumMeta):
|
||||
# The __call__ method `boundary` kwarg was added in 3.11 and must be present
|
||||
# for pyright. Refer also: https://github.com/pylint-dev/pylint/issues/9622
|
||||
# pylint: disable=unexpected-keyword-arg
|
||||
# The __call__ method `values` varg must be named for pyright.
|
||||
# pylint: disable=keyword-arg-before-vararg
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
def __call__(
|
||||
cls, value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None
|
||||
):
|
||||
# The `type` kwarg also happens to be a built-in that pylint flags as
|
||||
# redeclared. Safe to ignore this lint rule with this scope.
|
||||
# pylint: disable=redefined-builtin
|
||||
|
||||
if names is not None:
|
||||
return super().__call__(
|
||||
value,
|
||||
names=names,
|
||||
*values,
|
||||
module=module,
|
||||
qualname=qualname,
|
||||
type=type,
|
||||
start=start,
|
||||
boundary=boundary,
|
||||
)
|
||||
|
||||
try:
|
||||
return super().__call__(
|
||||
value,
|
||||
names=names, # pyright: ignore[reportArgumentType]
|
||||
*values,
|
||||
module=module,
|
||||
qualname=qualname,
|
||||
type=type,
|
||||
start=start,
|
||||
boundary=boundary,
|
||||
)
|
||||
except ValueError:
|
||||
return value
|
||||
else:
|
||||
def __call__(
|
||||
cls, value, names=None, *, module=None, qualname=None, type=None, start=1
|
||||
):
|
||||
# The `type` kwarg also happens to be a built-in that pylint flags as
|
||||
# redeclared. Safe to ignore this lint rule with this scope.
|
||||
# pylint: disable=redefined-builtin
|
||||
|
||||
if names is not None:
|
||||
return super().__call__(
|
||||
value,
|
||||
names=names,
|
||||
module=module,
|
||||
qualname=qualname,
|
||||
type=type,
|
||||
start=start,
|
||||
)
|
||||
|
||||
try:
|
||||
return super().__call__(
|
||||
value,
|
||||
names=names, # pyright: ignore[reportArgumentType]
|
||||
module=module,
|
||||
qualname=qualname,
|
||||
type=type,
|
||||
start=start,
|
||||
)
|
||||
except ValueError:
|
||||
return value
|
||||
@@ -0,0 +1,238 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import re
|
||||
import json
|
||||
from typing import (
|
||||
Callable,
|
||||
Generic,
|
||||
TypeVar,
|
||||
Optional,
|
||||
Generator,
|
||||
AsyncGenerator,
|
||||
Tuple,
|
||||
)
|
||||
import httpx
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class EventStream(Generic[T]):
|
||||
response: httpx.Response
|
||||
generator: Generator[T, None, None]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
response: httpx.Response,
|
||||
decoder: Callable[[str], T],
|
||||
sentinel: Optional[str] = None,
|
||||
):
|
||||
self.response = response
|
||||
self.generator = stream_events(response, decoder, sentinel)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return next(self.generator)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.response.close()
|
||||
|
||||
|
||||
class EventStreamAsync(Generic[T]):
|
||||
response: httpx.Response
|
||||
generator: AsyncGenerator[T, None]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
response: httpx.Response,
|
||||
decoder: Callable[[str], T],
|
||||
sentinel: Optional[str] = None,
|
||||
):
|
||||
self.response = response
|
||||
self.generator = stream_events_async(response, decoder, sentinel)
|
||||
|
||||
def __aiter__(self):
|
||||
return self
|
||||
|
||||
async def __anext__(self):
|
||||
return await self.generator.__anext__()
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
await self.response.aclose()
|
||||
|
||||
|
||||
class ServerEvent:
|
||||
id: Optional[str] = None
|
||||
event: Optional[str] = None
|
||||
data: Optional[str] = None
|
||||
retry: Optional[int] = None
|
||||
|
||||
|
||||
MESSAGE_BOUNDARIES = [
|
||||
b"\r\n\r\n",
|
||||
b"\n\n",
|
||||
b"\r\r",
|
||||
]
|
||||
|
||||
|
||||
async def stream_events_async(
|
||||
response: httpx.Response,
|
||||
decoder: Callable[[str], T],
|
||||
sentinel: Optional[str] = None,
|
||||
) -> AsyncGenerator[T, None]:
|
||||
buffer = bytearray()
|
||||
position = 0
|
||||
discard = False
|
||||
async for chunk in response.aiter_bytes():
|
||||
# We've encountered the sentinel value and should no longer process
|
||||
# incoming data. Instead we throw new data away until the server closes
|
||||
# the connection.
|
||||
if discard:
|
||||
continue
|
||||
|
||||
buffer += chunk
|
||||
for i in range(position, len(buffer)):
|
||||
char = buffer[i : i + 1]
|
||||
seq: Optional[bytes] = None
|
||||
if char in [b"\r", b"\n"]:
|
||||
for boundary in MESSAGE_BOUNDARIES:
|
||||
seq = _peek_sequence(i, buffer, boundary)
|
||||
if seq is not None:
|
||||
break
|
||||
if seq is None:
|
||||
continue
|
||||
|
||||
block = buffer[position:i]
|
||||
position = i + len(seq)
|
||||
event, discard = _parse_event(block, decoder, sentinel)
|
||||
if event is not None:
|
||||
yield event
|
||||
|
||||
if position > 0:
|
||||
buffer = buffer[position:]
|
||||
position = 0
|
||||
|
||||
event, discard = _parse_event(buffer, decoder, sentinel)
|
||||
if event is not None:
|
||||
yield event
|
||||
|
||||
|
||||
def stream_events(
|
||||
response: httpx.Response,
|
||||
decoder: Callable[[str], T],
|
||||
sentinel: Optional[str] = None,
|
||||
) -> Generator[T, None, None]:
|
||||
buffer = bytearray()
|
||||
position = 0
|
||||
discard = False
|
||||
for chunk in response.iter_bytes():
|
||||
# We've encountered the sentinel value and should no longer process
|
||||
# incoming data. Instead we throw new data away until the server closes
|
||||
# the connection.
|
||||
if discard:
|
||||
continue
|
||||
|
||||
buffer += chunk
|
||||
for i in range(position, len(buffer)):
|
||||
char = buffer[i : i + 1]
|
||||
seq: Optional[bytes] = None
|
||||
if char in [b"\r", b"\n"]:
|
||||
for boundary in MESSAGE_BOUNDARIES:
|
||||
seq = _peek_sequence(i, buffer, boundary)
|
||||
if seq is not None:
|
||||
break
|
||||
if seq is None:
|
||||
continue
|
||||
|
||||
block = buffer[position:i]
|
||||
position = i + len(seq)
|
||||
event, discard = _parse_event(block, decoder, sentinel)
|
||||
if event is not None:
|
||||
yield event
|
||||
|
||||
if position > 0:
|
||||
buffer = buffer[position:]
|
||||
position = 0
|
||||
|
||||
event, discard = _parse_event(buffer, decoder, sentinel)
|
||||
if event is not None:
|
||||
yield event
|
||||
|
||||
|
||||
def _parse_event(
|
||||
raw: bytearray, decoder: Callable[[str], T], sentinel: Optional[str] = None
|
||||
) -> Tuple[Optional[T], bool]:
|
||||
block = raw.decode()
|
||||
lines = re.split(r"\r?\n|\r", block)
|
||||
publish = False
|
||||
event = ServerEvent()
|
||||
data = ""
|
||||
for line in lines:
|
||||
if not line:
|
||||
continue
|
||||
|
||||
delim = line.find(":")
|
||||
if delim <= 0:
|
||||
continue
|
||||
|
||||
field = line[0:delim]
|
||||
value = line[delim + 1 :] if delim < len(line) - 1 else ""
|
||||
if len(value) and value[0] == " ":
|
||||
value = value[1:]
|
||||
|
||||
if field == "event":
|
||||
event.event = value
|
||||
publish = True
|
||||
elif field == "data":
|
||||
data += value + "\n"
|
||||
publish = True
|
||||
elif field == "id":
|
||||
event.id = value
|
||||
publish = True
|
||||
elif field == "retry":
|
||||
event.retry = int(value) if value.isdigit() else None
|
||||
publish = True
|
||||
|
||||
if sentinel and data == f"{sentinel}\n":
|
||||
return None, True
|
||||
|
||||
if data:
|
||||
data = data[:-1]
|
||||
event.data = data
|
||||
|
||||
data_is_primitive = (
|
||||
data.isnumeric() or data == "true" or data == "false" or data == "null"
|
||||
)
|
||||
data_is_json = (
|
||||
data.startswith("{") or data.startswith("[") or data.startswith('"')
|
||||
)
|
||||
|
||||
if data_is_primitive or data_is_json:
|
||||
try:
|
||||
event.data = json.loads(data)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
out = None
|
||||
if publish:
|
||||
out = decoder(json.dumps(event.__dict__))
|
||||
|
||||
return out, False
|
||||
|
||||
|
||||
def _peek_sequence(position: int, buffer: bytearray, sequence: bytes):
|
||||
if len(sequence) > (len(buffer) - position):
|
||||
return None
|
||||
|
||||
for i, seq in enumerate(sequence):
|
||||
if buffer[position + i] != seq:
|
||||
return None
|
||||
|
||||
return sequence
|
||||
@@ -0,0 +1,223 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
get_type_hints,
|
||||
List,
|
||||
Tuple,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from .serializers import marshal_json
|
||||
|
||||
from .metadata import (
|
||||
FormMetadata,
|
||||
MultipartFormMetadata,
|
||||
find_field_metadata,
|
||||
)
|
||||
from .values import _is_set, _val_to_string
|
||||
|
||||
|
||||
def _populate_form(
|
||||
field_name: str,
|
||||
explode: bool,
|
||||
obj: Any,
|
||||
delimiter: str,
|
||||
form: Dict[str, List[str]],
|
||||
):
|
||||
if not _is_set(obj):
|
||||
return form
|
||||
|
||||
if isinstance(obj, BaseModel):
|
||||
items = []
|
||||
|
||||
obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields
|
||||
for name in obj_fields:
|
||||
obj_field = obj_fields[name]
|
||||
obj_field_name = obj_field.alias if obj_field.alias is not None else name
|
||||
if obj_field_name == "":
|
||||
continue
|
||||
|
||||
val = getattr(obj, name)
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
if explode:
|
||||
form[obj_field_name] = [_val_to_string(val)]
|
||||
else:
|
||||
items.append(f"{obj_field_name}{delimiter}{_val_to_string(val)}")
|
||||
|
||||
if len(items) > 0:
|
||||
form[field_name] = [delimiter.join(items)]
|
||||
elif isinstance(obj, Dict):
|
||||
items = []
|
||||
for key, value in obj.items():
|
||||
if not _is_set(value):
|
||||
continue
|
||||
|
||||
if explode:
|
||||
form[key] = [_val_to_string(value)]
|
||||
else:
|
||||
items.append(f"{key}{delimiter}{_val_to_string(value)}")
|
||||
|
||||
if len(items) > 0:
|
||||
form[field_name] = [delimiter.join(items)]
|
||||
elif isinstance(obj, List):
|
||||
items = []
|
||||
|
||||
for value in obj:
|
||||
if not _is_set(value):
|
||||
continue
|
||||
|
||||
if explode:
|
||||
if not field_name in form:
|
||||
form[field_name] = []
|
||||
form[field_name].append(_val_to_string(value))
|
||||
else:
|
||||
items.append(_val_to_string(value))
|
||||
|
||||
if len(items) > 0:
|
||||
form[field_name] = [delimiter.join([str(item) for item in items])]
|
||||
else:
|
||||
form[field_name] = [_val_to_string(obj)]
|
||||
|
||||
return form
|
||||
|
||||
|
||||
def _extract_file_properties(file_obj: Any) -> Tuple[str, Any, Any]:
|
||||
"""Extract file name, content, and content type from a file object."""
|
||||
file_fields: Dict[str, FieldInfo] = file_obj.__class__.model_fields
|
||||
|
||||
file_name = ""
|
||||
content = None
|
||||
content_type = None
|
||||
|
||||
for file_field_name in file_fields:
|
||||
file_field = file_fields[file_field_name]
|
||||
|
||||
file_metadata = find_field_metadata(file_field, MultipartFormMetadata)
|
||||
if file_metadata is None:
|
||||
continue
|
||||
|
||||
if file_metadata.content:
|
||||
content = getattr(file_obj, file_field_name, None)
|
||||
elif file_field_name == "content_type":
|
||||
content_type = getattr(file_obj, file_field_name, None)
|
||||
else:
|
||||
file_name = getattr(file_obj, file_field_name)
|
||||
|
||||
if file_name == "" or content is None:
|
||||
raise ValueError("invalid multipart/form-data file")
|
||||
|
||||
return file_name, content, content_type
|
||||
|
||||
|
||||
def serialize_multipart_form(
|
||||
media_type: str, request: Any
|
||||
) -> Tuple[str, Dict[str, Any], List[Tuple[str, Any]]]:
|
||||
form: Dict[str, Any] = {}
|
||||
files: List[Tuple[str, Any]] = []
|
||||
|
||||
if not isinstance(request, BaseModel):
|
||||
raise TypeError("invalid request body type")
|
||||
|
||||
request_fields: Dict[str, FieldInfo] = request.__class__.model_fields
|
||||
request_field_types = get_type_hints(request.__class__)
|
||||
|
||||
for name in request_fields:
|
||||
field = request_fields[name]
|
||||
|
||||
val = getattr(request, name)
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
field_metadata = find_field_metadata(field, MultipartFormMetadata)
|
||||
if not field_metadata:
|
||||
continue
|
||||
|
||||
f_name = field.alias if field.alias else name
|
||||
|
||||
if field_metadata.file:
|
||||
if isinstance(val, List):
|
||||
# Handle array of files
|
||||
for file_obj in val:
|
||||
if not _is_set(file_obj):
|
||||
continue
|
||||
|
||||
file_name, content, content_type = _extract_file_properties(file_obj)
|
||||
|
||||
if content_type is not None:
|
||||
files.append((f_name + "[]", (file_name, content, content_type)))
|
||||
else:
|
||||
files.append((f_name + "[]", (file_name, content)))
|
||||
else:
|
||||
# Handle single file
|
||||
file_name, content, content_type = _extract_file_properties(val)
|
||||
|
||||
if content_type is not None:
|
||||
files.append((f_name, (file_name, content, content_type)))
|
||||
else:
|
||||
files.append((f_name, (file_name, content)))
|
||||
elif field_metadata.json:
|
||||
files.append((f_name, (
|
||||
None,
|
||||
marshal_json(val, request_field_types[name]),
|
||||
"application/json",
|
||||
)))
|
||||
else:
|
||||
if isinstance(val, List):
|
||||
values = []
|
||||
|
||||
for value in val:
|
||||
if not _is_set(value):
|
||||
continue
|
||||
values.append(_val_to_string(value))
|
||||
|
||||
form[f_name + "[]"] = values
|
||||
else:
|
||||
form[f_name] = _val_to_string(val)
|
||||
return media_type, form, files
|
||||
|
||||
|
||||
def serialize_form_data(data: Any) -> Dict[str, Any]:
|
||||
form: Dict[str, List[str]] = {}
|
||||
|
||||
if isinstance(data, BaseModel):
|
||||
data_fields: Dict[str, FieldInfo] = data.__class__.model_fields
|
||||
data_field_types = get_type_hints(data.__class__)
|
||||
for name in data_fields:
|
||||
field = data_fields[name]
|
||||
|
||||
val = getattr(data, name)
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
metadata = find_field_metadata(field, FormMetadata)
|
||||
if metadata is None:
|
||||
continue
|
||||
|
||||
f_name = field.alias if field.alias is not None else name
|
||||
|
||||
if metadata.json:
|
||||
form[f_name] = [marshal_json(val, data_field_types[name])]
|
||||
else:
|
||||
if metadata.style == "form":
|
||||
_populate_form(
|
||||
f_name,
|
||||
metadata.explode,
|
||||
val,
|
||||
",",
|
||||
form,
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Invalid form style for field {name}")
|
||||
elif isinstance(data, Dict):
|
||||
for key, value in data.items():
|
||||
if _is_set(value):
|
||||
form[key] = [_val_to_string(value)]
|
||||
else:
|
||||
raise TypeError(f"Invalid request body type {type(data)} for form data")
|
||||
|
||||
return form
|
||||
@@ -0,0 +1,136 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
)
|
||||
from httpx import Headers
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from .metadata import (
|
||||
HeaderMetadata,
|
||||
find_field_metadata,
|
||||
)
|
||||
|
||||
from .values import _is_set, _populate_from_globals, _val_to_string
|
||||
|
||||
|
||||
def get_headers(headers_params: Any, gbls: Optional[Any] = None) -> Dict[str, str]:
|
||||
headers: Dict[str, str] = {}
|
||||
|
||||
globals_already_populated = []
|
||||
if _is_set(headers_params):
|
||||
globals_already_populated = _populate_headers(headers_params, gbls, headers, [])
|
||||
if _is_set(gbls):
|
||||
_populate_headers(gbls, None, headers, globals_already_populated)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def _populate_headers(
|
||||
headers_params: Any,
|
||||
gbls: Any,
|
||||
header_values: Dict[str, str],
|
||||
skip_fields: List[str],
|
||||
) -> List[str]:
|
||||
globals_already_populated: List[str] = []
|
||||
|
||||
if not isinstance(headers_params, BaseModel):
|
||||
return globals_already_populated
|
||||
|
||||
param_fields: Dict[str, FieldInfo] = headers_params.__class__.model_fields
|
||||
for name in param_fields:
|
||||
if name in skip_fields:
|
||||
continue
|
||||
|
||||
field = param_fields[name]
|
||||
f_name = field.alias if field.alias is not None else name
|
||||
|
||||
metadata = find_field_metadata(field, HeaderMetadata)
|
||||
if metadata is None:
|
||||
continue
|
||||
|
||||
value, global_found = _populate_from_globals(
|
||||
name, getattr(headers_params, name), HeaderMetadata, gbls
|
||||
)
|
||||
if global_found:
|
||||
globals_already_populated.append(name)
|
||||
value = _serialize_header(metadata.explode, value)
|
||||
|
||||
if value != "":
|
||||
header_values[f_name] = value
|
||||
|
||||
return globals_already_populated
|
||||
|
||||
|
||||
def _serialize_header(explode: bool, obj: Any) -> str:
|
||||
if not _is_set(obj):
|
||||
return ""
|
||||
|
||||
if isinstance(obj, BaseModel):
|
||||
items = []
|
||||
obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields
|
||||
for name in obj_fields:
|
||||
obj_field = obj_fields[name]
|
||||
obj_param_metadata = find_field_metadata(obj_field, HeaderMetadata)
|
||||
|
||||
if not obj_param_metadata:
|
||||
continue
|
||||
|
||||
f_name = obj_field.alias if obj_field.alias is not None else name
|
||||
|
||||
val = getattr(obj, name)
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
if explode:
|
||||
items.append(f"{f_name}={_val_to_string(val)}")
|
||||
else:
|
||||
items.append(f_name)
|
||||
items.append(_val_to_string(val))
|
||||
|
||||
if len(items) > 0:
|
||||
return ",".join(items)
|
||||
elif isinstance(obj, Dict):
|
||||
items = []
|
||||
|
||||
for key, value in obj.items():
|
||||
if not _is_set(value):
|
||||
continue
|
||||
|
||||
if explode:
|
||||
items.append(f"{key}={_val_to_string(value)}")
|
||||
else:
|
||||
items.append(key)
|
||||
items.append(_val_to_string(value))
|
||||
|
||||
if len(items) > 0:
|
||||
return ",".join([str(item) for item in items])
|
||||
elif isinstance(obj, List):
|
||||
items = []
|
||||
|
||||
for value in obj:
|
||||
if not _is_set(value):
|
||||
continue
|
||||
|
||||
items.append(_val_to_string(value))
|
||||
|
||||
if len(items) > 0:
|
||||
return ",".join(items)
|
||||
elif _is_set(obj):
|
||||
return f"{_val_to_string(obj)}"
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def get_response_headers(headers: Headers) -> Dict[str, List[str]]:
|
||||
res: Dict[str, List[str]] = {}
|
||||
for k, v in headers.items():
|
||||
if not k in res:
|
||||
res[k] = []
|
||||
|
||||
res[k].append(v)
|
||||
return res
|
||||
@@ -0,0 +1,27 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import httpx
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Protocol
|
||||
|
||||
|
||||
class Logger(Protocol):
|
||||
def debug(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class NoOpLogger:
|
||||
def debug(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def get_body_content(req: httpx.Request) -> str:
|
||||
return "<streaming body>" if not hasattr(req, "_content") else str(req.content)
|
||||
|
||||
|
||||
def get_default_logger() -> Logger:
|
||||
if os.getenv("OPENROUTER_DEBUG"):
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
return logging.getLogger("openrouter")
|
||||
return NoOpLogger()
|
||||
@@ -0,0 +1,118 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import Optional, Type, TypeVar, Union
|
||||
from dataclasses import dataclass
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
@dataclass
|
||||
class SecurityMetadata:
|
||||
option: bool = False
|
||||
scheme: bool = False
|
||||
scheme_type: Optional[str] = None
|
||||
sub_type: Optional[str] = None
|
||||
field_name: Optional[str] = None
|
||||
|
||||
def get_field_name(self, default: str) -> str:
|
||||
return self.field_name or default
|
||||
|
||||
|
||||
@dataclass
|
||||
class ParamMetadata:
|
||||
serialization: Optional[str] = None
|
||||
style: str = "simple"
|
||||
explode: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class PathParamMetadata(ParamMetadata):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class QueryParamMetadata(ParamMetadata):
|
||||
style: str = "form"
|
||||
explode: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class HeaderMetadata(ParamMetadata):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class RequestMetadata:
|
||||
media_type: str = "application/octet-stream"
|
||||
|
||||
|
||||
@dataclass
|
||||
class MultipartFormMetadata:
|
||||
file: bool = False
|
||||
content: bool = False
|
||||
json: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class FormMetadata:
|
||||
json: bool = False
|
||||
style: str = "form"
|
||||
explode: bool = True
|
||||
|
||||
|
||||
class FieldMetadata:
|
||||
security: Optional[SecurityMetadata] = None
|
||||
path: Optional[PathParamMetadata] = None
|
||||
query: Optional[QueryParamMetadata] = None
|
||||
header: Optional[HeaderMetadata] = None
|
||||
request: Optional[RequestMetadata] = None
|
||||
form: Optional[FormMetadata] = None
|
||||
multipart: Optional[MultipartFormMetadata] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
security: Optional[SecurityMetadata] = None,
|
||||
path: Optional[Union[PathParamMetadata, bool]] = None,
|
||||
query: Optional[Union[QueryParamMetadata, bool]] = None,
|
||||
header: Optional[Union[HeaderMetadata, bool]] = None,
|
||||
request: Optional[Union[RequestMetadata, bool]] = None,
|
||||
form: Optional[Union[FormMetadata, bool]] = None,
|
||||
multipart: Optional[Union[MultipartFormMetadata, bool]] = None,
|
||||
):
|
||||
self.security = security
|
||||
self.path = PathParamMetadata() if isinstance(path, bool) else path
|
||||
self.query = QueryParamMetadata() if isinstance(query, bool) else query
|
||||
self.header = HeaderMetadata() if isinstance(header, bool) else header
|
||||
self.request = RequestMetadata() if isinstance(request, bool) else request
|
||||
self.form = FormMetadata() if isinstance(form, bool) else form
|
||||
self.multipart = (
|
||||
MultipartFormMetadata() if isinstance(multipart, bool) else multipart
|
||||
)
|
||||
|
||||
|
||||
def find_field_metadata(field_info: FieldInfo, metadata_type: Type[T]) -> Optional[T]:
|
||||
metadata = find_metadata(field_info, FieldMetadata)
|
||||
if not metadata:
|
||||
return None
|
||||
|
||||
fields = metadata.__dict__
|
||||
|
||||
for field in fields:
|
||||
if isinstance(fields[field], metadata_type):
|
||||
return fields[field]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_metadata(field_info: FieldInfo, metadata_type: Type[T]) -> Optional[T]:
|
||||
metadata = field_info.metadata
|
||||
if not metadata:
|
||||
return None
|
||||
|
||||
for md in metadata:
|
||||
if isinstance(md, metadata_type):
|
||||
return md
|
||||
|
||||
return None
|
||||
@@ -0,0 +1,205 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
get_type_hints,
|
||||
List,
|
||||
Optional,
|
||||
)
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from .metadata import (
|
||||
QueryParamMetadata,
|
||||
find_field_metadata,
|
||||
)
|
||||
from .values import (
|
||||
_get_serialized_params,
|
||||
_is_set,
|
||||
_populate_from_globals,
|
||||
_val_to_string,
|
||||
)
|
||||
from .forms import _populate_form
|
||||
|
||||
|
||||
def get_query_params(
|
||||
query_params: Any,
|
||||
gbls: Optional[Any] = None,
|
||||
) -> Dict[str, List[str]]:
|
||||
params: Dict[str, List[str]] = {}
|
||||
|
||||
globals_already_populated = _populate_query_params(query_params, gbls, params, [])
|
||||
if _is_set(gbls):
|
||||
_populate_query_params(gbls, None, params, globals_already_populated)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def _populate_query_params(
|
||||
query_params: Any,
|
||||
gbls: Any,
|
||||
query_param_values: Dict[str, List[str]],
|
||||
skip_fields: List[str],
|
||||
) -> List[str]:
|
||||
globals_already_populated: List[str] = []
|
||||
|
||||
if not isinstance(query_params, BaseModel):
|
||||
return globals_already_populated
|
||||
|
||||
param_fields: Dict[str, FieldInfo] = query_params.__class__.model_fields
|
||||
param_field_types = get_type_hints(query_params.__class__)
|
||||
for name in param_fields:
|
||||
if name in skip_fields:
|
||||
continue
|
||||
|
||||
field = param_fields[name]
|
||||
|
||||
metadata = find_field_metadata(field, QueryParamMetadata)
|
||||
if not metadata:
|
||||
continue
|
||||
|
||||
value = getattr(query_params, name) if _is_set(query_params) else None
|
||||
|
||||
value, global_found = _populate_from_globals(
|
||||
name, value, QueryParamMetadata, gbls
|
||||
)
|
||||
if global_found:
|
||||
globals_already_populated.append(name)
|
||||
|
||||
f_name = field.alias if field.alias is not None else name
|
||||
serialization = metadata.serialization
|
||||
if serialization is not None:
|
||||
serialized_parms = _get_serialized_params(
|
||||
metadata, f_name, value, param_field_types[name]
|
||||
)
|
||||
for key, value in serialized_parms.items():
|
||||
if key in query_param_values:
|
||||
query_param_values[key].extend(value)
|
||||
else:
|
||||
query_param_values[key] = [value]
|
||||
else:
|
||||
style = metadata.style
|
||||
if style == "deepObject":
|
||||
_populate_deep_object_query_params(f_name, value, query_param_values)
|
||||
elif style == "form":
|
||||
_populate_delimited_query_params(
|
||||
metadata, f_name, value, ",", query_param_values
|
||||
)
|
||||
elif style == "pipeDelimited":
|
||||
_populate_delimited_query_params(
|
||||
metadata, f_name, value, "|", query_param_values
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"query param style {style} not yet supported"
|
||||
)
|
||||
|
||||
return globals_already_populated
|
||||
|
||||
|
||||
def _populate_deep_object_query_params(
|
||||
field_name: str,
|
||||
obj: Any,
|
||||
params: Dict[str, List[str]],
|
||||
):
|
||||
if not _is_set(obj):
|
||||
return
|
||||
|
||||
if isinstance(obj, BaseModel):
|
||||
_populate_deep_object_query_params_basemodel(field_name, obj, params)
|
||||
elif isinstance(obj, Dict):
|
||||
_populate_deep_object_query_params_dict(field_name, obj, params)
|
||||
|
||||
|
||||
def _populate_deep_object_query_params_basemodel(
|
||||
prior_params_key: str,
|
||||
obj: Any,
|
||||
params: Dict[str, List[str]],
|
||||
):
|
||||
if not _is_set(obj) or not isinstance(obj, BaseModel):
|
||||
return
|
||||
|
||||
obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields
|
||||
for name in obj_fields:
|
||||
obj_field = obj_fields[name]
|
||||
|
||||
f_name = obj_field.alias if obj_field.alias is not None else name
|
||||
|
||||
params_key = f"{prior_params_key}[{f_name}]"
|
||||
|
||||
obj_param_metadata = find_field_metadata(obj_field, QueryParamMetadata)
|
||||
if not _is_set(obj_param_metadata):
|
||||
continue
|
||||
|
||||
obj_val = getattr(obj, name)
|
||||
if not _is_set(obj_val):
|
||||
continue
|
||||
|
||||
if isinstance(obj_val, BaseModel):
|
||||
_populate_deep_object_query_params_basemodel(params_key, obj_val, params)
|
||||
elif isinstance(obj_val, Dict):
|
||||
_populate_deep_object_query_params_dict(params_key, obj_val, params)
|
||||
elif isinstance(obj_val, List):
|
||||
_populate_deep_object_query_params_list(params_key, obj_val, params)
|
||||
else:
|
||||
params[params_key] = [_val_to_string(obj_val)]
|
||||
|
||||
|
||||
def _populate_deep_object_query_params_dict(
|
||||
prior_params_key: str,
|
||||
value: Dict,
|
||||
params: Dict[str, List[str]],
|
||||
):
|
||||
if not _is_set(value):
|
||||
return
|
||||
|
||||
for key, val in value.items():
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
params_key = f"{prior_params_key}[{key}]"
|
||||
|
||||
if isinstance(val, BaseModel):
|
||||
_populate_deep_object_query_params_basemodel(params_key, val, params)
|
||||
elif isinstance(val, Dict):
|
||||
_populate_deep_object_query_params_dict(params_key, val, params)
|
||||
elif isinstance(val, List):
|
||||
_populate_deep_object_query_params_list(params_key, val, params)
|
||||
else:
|
||||
params[params_key] = [_val_to_string(val)]
|
||||
|
||||
|
||||
def _populate_deep_object_query_params_list(
|
||||
params_key: str,
|
||||
value: List,
|
||||
params: Dict[str, List[str]],
|
||||
):
|
||||
if not _is_set(value):
|
||||
return
|
||||
|
||||
for val in value:
|
||||
if not _is_set(val):
|
||||
continue
|
||||
|
||||
if params.get(params_key) is None:
|
||||
params[params_key] = []
|
||||
|
||||
params[params_key].append(_val_to_string(val))
|
||||
|
||||
|
||||
def _populate_delimited_query_params(
|
||||
metadata: QueryParamMetadata,
|
||||
field_name: str,
|
||||
obj: Any,
|
||||
delimiter: str,
|
||||
query_param_values: Dict[str, List[str]],
|
||||
):
|
||||
_populate_form(
|
||||
field_name,
|
||||
metadata.explode,
|
||||
obj,
|
||||
delimiter,
|
||||
query_param_values,
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import io
|
||||
from dataclasses import dataclass
|
||||
import re
|
||||
from typing import (
|
||||
Any,
|
||||
Optional,
|
||||
)
|
||||
|
||||
from .forms import serialize_form_data, serialize_multipart_form
|
||||
|
||||
from .serializers import marshal_json
|
||||
|
||||
SERIALIZATION_METHOD_TO_CONTENT_TYPE = {
|
||||
"json": "application/json",
|
||||
"form": "application/x-www-form-urlencoded",
|
||||
"multipart": "multipart/form-data",
|
||||
"raw": "application/octet-stream",
|
||||
"string": "text/plain",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class SerializedRequestBody:
|
||||
media_type: Optional[str] = None
|
||||
content: Optional[Any] = None
|
||||
data: Optional[Any] = None
|
||||
files: Optional[Any] = None
|
||||
|
||||
|
||||
def serialize_request_body(
|
||||
request_body: Any,
|
||||
nullable: bool,
|
||||
optional: bool,
|
||||
serialization_method: str,
|
||||
request_body_type,
|
||||
) -> Optional[SerializedRequestBody]:
|
||||
if request_body is None:
|
||||
if not nullable and optional:
|
||||
return None
|
||||
|
||||
media_type = SERIALIZATION_METHOD_TO_CONTENT_TYPE[serialization_method]
|
||||
|
||||
serialized_request_body = SerializedRequestBody(media_type)
|
||||
|
||||
if re.match(r"(application|text)\/.*?\+*json.*", media_type) is not None:
|
||||
serialized_request_body.content = marshal_json(request_body, request_body_type)
|
||||
elif re.match(r"multipart\/.*", media_type) is not None:
|
||||
(
|
||||
serialized_request_body.media_type,
|
||||
serialized_request_body.data,
|
||||
serialized_request_body.files,
|
||||
) = serialize_multipart_form(media_type, request_body)
|
||||
elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None:
|
||||
serialized_request_body.data = serialize_form_data(request_body)
|
||||
elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)):
|
||||
serialized_request_body.content = request_body
|
||||
elif isinstance(request_body, str):
|
||||
serialized_request_body.content = request_body
|
||||
else:
|
||||
raise TypeError(
|
||||
f"invalid request body type {type(request_body)} for mediaType {media_type}"
|
||||
)
|
||||
|
||||
return serialized_request_body
|
||||
@@ -0,0 +1,217 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import asyncio
|
||||
import random
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
import httpx
|
||||
|
||||
|
||||
class BackoffStrategy:
|
||||
initial_interval: int
|
||||
max_interval: int
|
||||
exponent: float
|
||||
max_elapsed_time: int
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
initial_interval: int,
|
||||
max_interval: int,
|
||||
exponent: float,
|
||||
max_elapsed_time: int,
|
||||
):
|
||||
self.initial_interval = initial_interval
|
||||
self.max_interval = max_interval
|
||||
self.exponent = exponent
|
||||
self.max_elapsed_time = max_elapsed_time
|
||||
|
||||
|
||||
class RetryConfig:
|
||||
strategy: str
|
||||
backoff: BackoffStrategy
|
||||
retry_connection_errors: bool
|
||||
|
||||
def __init__(
|
||||
self, strategy: str, backoff: BackoffStrategy, retry_connection_errors: bool
|
||||
):
|
||||
self.strategy = strategy
|
||||
self.backoff = backoff
|
||||
self.retry_connection_errors = retry_connection_errors
|
||||
|
||||
|
||||
class Retries:
|
||||
config: RetryConfig
|
||||
status_codes: List[str]
|
||||
|
||||
def __init__(self, config: RetryConfig, status_codes: List[str]):
|
||||
self.config = config
|
||||
self.status_codes = status_codes
|
||||
|
||||
|
||||
class TemporaryError(Exception):
|
||||
response: httpx.Response
|
||||
|
||||
def __init__(self, response: httpx.Response):
|
||||
self.response = response
|
||||
|
||||
|
||||
class PermanentError(Exception):
|
||||
inner: Exception
|
||||
|
||||
def __init__(self, inner: Exception):
|
||||
self.inner = inner
|
||||
|
||||
|
||||
def retry(func, retries: Retries):
|
||||
if retries.config.strategy == "backoff":
|
||||
|
||||
def do_request() -> httpx.Response:
|
||||
res: httpx.Response
|
||||
try:
|
||||
res = func()
|
||||
|
||||
for code in retries.status_codes:
|
||||
if "X" in code.upper():
|
||||
code_range = int(code[0])
|
||||
|
||||
status_major = res.status_code / 100
|
||||
|
||||
if code_range <= status_major < code_range + 1:
|
||||
raise TemporaryError(res)
|
||||
else:
|
||||
parsed_code = int(code)
|
||||
|
||||
if res.status_code == parsed_code:
|
||||
raise TemporaryError(res)
|
||||
except httpx.ConnectError as exception:
|
||||
if retries.config.retry_connection_errors:
|
||||
raise
|
||||
|
||||
raise PermanentError(exception) from exception
|
||||
except httpx.TimeoutException as exception:
|
||||
if retries.config.retry_connection_errors:
|
||||
raise
|
||||
|
||||
raise PermanentError(exception) from exception
|
||||
except TemporaryError:
|
||||
raise
|
||||
except Exception as exception:
|
||||
raise PermanentError(exception) from exception
|
||||
|
||||
return res
|
||||
|
||||
return retry_with_backoff(
|
||||
do_request,
|
||||
retries.config.backoff.initial_interval,
|
||||
retries.config.backoff.max_interval,
|
||||
retries.config.backoff.exponent,
|
||||
retries.config.backoff.max_elapsed_time,
|
||||
)
|
||||
|
||||
return func()
|
||||
|
||||
|
||||
async def retry_async(func, retries: Retries):
|
||||
if retries.config.strategy == "backoff":
|
||||
|
||||
async def do_request() -> httpx.Response:
|
||||
res: httpx.Response
|
||||
try:
|
||||
res = await func()
|
||||
|
||||
for code in retries.status_codes:
|
||||
if "X" in code.upper():
|
||||
code_range = int(code[0])
|
||||
|
||||
status_major = res.status_code / 100
|
||||
|
||||
if code_range <= status_major < code_range + 1:
|
||||
raise TemporaryError(res)
|
||||
else:
|
||||
parsed_code = int(code)
|
||||
|
||||
if res.status_code == parsed_code:
|
||||
raise TemporaryError(res)
|
||||
except httpx.ConnectError as exception:
|
||||
if retries.config.retry_connection_errors:
|
||||
raise
|
||||
|
||||
raise PermanentError(exception) from exception
|
||||
except httpx.TimeoutException as exception:
|
||||
if retries.config.retry_connection_errors:
|
||||
raise
|
||||
|
||||
raise PermanentError(exception) from exception
|
||||
except TemporaryError:
|
||||
raise
|
||||
except Exception as exception:
|
||||
raise PermanentError(exception) from exception
|
||||
|
||||
return res
|
||||
|
||||
return await retry_with_backoff_async(
|
||||
do_request,
|
||||
retries.config.backoff.initial_interval,
|
||||
retries.config.backoff.max_interval,
|
||||
retries.config.backoff.exponent,
|
||||
retries.config.backoff.max_elapsed_time,
|
||||
)
|
||||
|
||||
return await func()
|
||||
|
||||
|
||||
def retry_with_backoff(
|
||||
func,
|
||||
initial_interval=500,
|
||||
max_interval=60000,
|
||||
exponent=1.5,
|
||||
max_elapsed_time=3600000,
|
||||
):
|
||||
start = round(time.time() * 1000)
|
||||
retries = 0
|
||||
|
||||
while True:
|
||||
try:
|
||||
return func()
|
||||
except PermanentError as exception:
|
||||
raise exception.inner
|
||||
except Exception as exception: # pylint: disable=broad-exception-caught
|
||||
now = round(time.time() * 1000)
|
||||
if now - start > max_elapsed_time:
|
||||
if isinstance(exception, TemporaryError):
|
||||
return exception.response
|
||||
|
||||
raise
|
||||
sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
|
||||
sleep = min(sleep, max_interval / 1000)
|
||||
time.sleep(sleep)
|
||||
retries += 1
|
||||
|
||||
|
||||
async def retry_with_backoff_async(
|
||||
func,
|
||||
initial_interval=500,
|
||||
max_interval=60000,
|
||||
exponent=1.5,
|
||||
max_elapsed_time=3600000,
|
||||
):
|
||||
start = round(time.time() * 1000)
|
||||
retries = 0
|
||||
|
||||
while True:
|
||||
try:
|
||||
return await func()
|
||||
except PermanentError as exception:
|
||||
raise exception.inner
|
||||
except Exception as exception: # pylint: disable=broad-exception-caught
|
||||
now = round(time.time() * 1000)
|
||||
if now - start > max_elapsed_time:
|
||||
if isinstance(exception, TemporaryError):
|
||||
return exception.response
|
||||
|
||||
raise
|
||||
sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
|
||||
sleep = min(sleep, max_interval / 1000)
|
||||
await asyncio.sleep(sleep)
|
||||
retries += 1
|
||||
@@ -0,0 +1,192 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
import base64
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from .metadata import (
|
||||
SecurityMetadata,
|
||||
find_field_metadata,
|
||||
)
|
||||
import os
|
||||
|
||||
|
||||
def get_security(security: Any) -> Tuple[Dict[str, str], Dict[str, List[str]]]:
|
||||
headers: Dict[str, str] = {}
|
||||
query_params: Dict[str, List[str]] = {}
|
||||
|
||||
if security is None:
|
||||
return headers, query_params
|
||||
|
||||
if not isinstance(security, BaseModel):
|
||||
raise TypeError("security must be a pydantic model")
|
||||
|
||||
sec_fields: Dict[str, FieldInfo] = security.__class__.model_fields
|
||||
for name in sec_fields:
|
||||
sec_field = sec_fields[name]
|
||||
|
||||
value = getattr(security, name)
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
metadata = find_field_metadata(sec_field, SecurityMetadata)
|
||||
if metadata is None:
|
||||
continue
|
||||
if metadata.option:
|
||||
_parse_security_option(headers, query_params, value)
|
||||
return headers, query_params
|
||||
if metadata.scheme:
|
||||
# Special case for basic auth or custom auth which could be a flattened model
|
||||
if metadata.sub_type in ["basic", "custom"] and not isinstance(
|
||||
value, BaseModel
|
||||
):
|
||||
_parse_security_scheme(headers, query_params, metadata, name, security)
|
||||
else:
|
||||
_parse_security_scheme(headers, query_params, metadata, name, value)
|
||||
|
||||
return headers, query_params
|
||||
|
||||
|
||||
def get_security_from_env(security: Any, security_class: Any) -> Optional[BaseModel]:
|
||||
if security is not None:
|
||||
return security
|
||||
|
||||
if not issubclass(security_class, BaseModel):
|
||||
raise TypeError("security_class must be a pydantic model class")
|
||||
|
||||
security_dict: Any = {}
|
||||
|
||||
if os.getenv("OPENROUTER_BEARER_AUTH"):
|
||||
security_dict["bearer_auth"] = os.getenv("OPENROUTER_BEARER_AUTH")
|
||||
|
||||
return security_class(**security_dict) if security_dict else None
|
||||
|
||||
|
||||
def _parse_security_option(
|
||||
headers: Dict[str, str], query_params: Dict[str, List[str]], option: Any
|
||||
):
|
||||
if not isinstance(option, BaseModel):
|
||||
raise TypeError("security option must be a pydantic model")
|
||||
|
||||
opt_fields: Dict[str, FieldInfo] = option.__class__.model_fields
|
||||
for name in opt_fields:
|
||||
opt_field = opt_fields[name]
|
||||
|
||||
metadata = find_field_metadata(opt_field, SecurityMetadata)
|
||||
if metadata is None or not metadata.scheme:
|
||||
continue
|
||||
_parse_security_scheme(
|
||||
headers, query_params, metadata, name, getattr(option, name)
|
||||
)
|
||||
|
||||
|
||||
def _parse_security_scheme(
|
||||
headers: Dict[str, str],
|
||||
query_params: Dict[str, List[str]],
|
||||
scheme_metadata: SecurityMetadata,
|
||||
field_name: str,
|
||||
scheme: Any,
|
||||
):
|
||||
scheme_type = scheme_metadata.scheme_type
|
||||
sub_type = scheme_metadata.sub_type
|
||||
|
||||
if isinstance(scheme, BaseModel):
|
||||
if scheme_type == "http":
|
||||
if sub_type == "basic":
|
||||
_parse_basic_auth_scheme(headers, scheme)
|
||||
return
|
||||
if sub_type == "custom":
|
||||
return
|
||||
|
||||
scheme_fields: Dict[str, FieldInfo] = scheme.__class__.model_fields
|
||||
for name in scheme_fields:
|
||||
scheme_field = scheme_fields[name]
|
||||
|
||||
metadata = find_field_metadata(scheme_field, SecurityMetadata)
|
||||
if metadata is None or metadata.field_name is None:
|
||||
continue
|
||||
|
||||
value = getattr(scheme, name)
|
||||
|
||||
_parse_security_scheme_value(
|
||||
headers, query_params, scheme_metadata, metadata, name, value
|
||||
)
|
||||
else:
|
||||
_parse_security_scheme_value(
|
||||
headers, query_params, scheme_metadata, scheme_metadata, field_name, scheme
|
||||
)
|
||||
|
||||
|
||||
def _parse_security_scheme_value(
|
||||
headers: Dict[str, str],
|
||||
query_params: Dict[str, List[str]],
|
||||
scheme_metadata: SecurityMetadata,
|
||||
security_metadata: SecurityMetadata,
|
||||
field_name: str,
|
||||
value: Any,
|
||||
):
|
||||
scheme_type = scheme_metadata.scheme_type
|
||||
sub_type = scheme_metadata.sub_type
|
||||
|
||||
header_name = security_metadata.get_field_name(field_name)
|
||||
|
||||
if scheme_type == "apiKey":
|
||||
if sub_type == "header":
|
||||
headers[header_name] = value
|
||||
elif sub_type == "query":
|
||||
query_params[header_name] = [value]
|
||||
else:
|
||||
raise ValueError("sub type {sub_type} not supported")
|
||||
elif scheme_type == "openIdConnect":
|
||||
headers[header_name] = _apply_bearer(value)
|
||||
elif scheme_type == "oauth2":
|
||||
if sub_type != "client_credentials":
|
||||
headers[header_name] = _apply_bearer(value)
|
||||
elif scheme_type == "http":
|
||||
if sub_type == "bearer":
|
||||
headers[header_name] = _apply_bearer(value)
|
||||
elif sub_type == "custom":
|
||||
return
|
||||
else:
|
||||
raise ValueError("sub type {sub_type} not supported")
|
||||
else:
|
||||
raise ValueError("scheme type {scheme_type} not supported")
|
||||
|
||||
|
||||
def _apply_bearer(token: str) -> str:
|
||||
return token.lower().startswith("bearer ") and token or f"Bearer {token}"
|
||||
|
||||
|
||||
def _parse_basic_auth_scheme(headers: Dict[str, str], scheme: Any):
|
||||
username = ""
|
||||
password = ""
|
||||
|
||||
if not isinstance(scheme, BaseModel):
|
||||
raise TypeError("basic auth scheme must be a pydantic model")
|
||||
|
||||
scheme_fields: Dict[str, FieldInfo] = scheme.__class__.model_fields
|
||||
for name in scheme_fields:
|
||||
scheme_field = scheme_fields[name]
|
||||
|
||||
metadata = find_field_metadata(scheme_field, SecurityMetadata)
|
||||
if metadata is None or metadata.field_name is None:
|
||||
continue
|
||||
|
||||
field_name = metadata.field_name
|
||||
value = getattr(scheme, name)
|
||||
|
||||
if field_name == "username":
|
||||
username = value
|
||||
if field_name == "password":
|
||||
password = value
|
||||
|
||||
data = f"{username}:{password}".encode()
|
||||
headers["Authorization"] = f"Basic {base64.b64encode(data).decode()}"
|
||||
@@ -0,0 +1,249 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from decimal import Decimal
|
||||
import functools
|
||||
import json
|
||||
import typing
|
||||
from typing import Any, Dict, List, Tuple, Union, get_args
|
||||
import typing_extensions
|
||||
from typing_extensions import get_origin
|
||||
|
||||
import httpx
|
||||
from pydantic import ConfigDict, create_model
|
||||
from pydantic_core import from_json
|
||||
|
||||
from ..types.basemodel import BaseModel, Nullable, OptionalNullable, Unset
|
||||
|
||||
|
||||
def serialize_decimal(as_str: bool):
|
||||
def serialize(d):
|
||||
# Optional[T] is a Union[T, None]
|
||||
if is_union(type(d)) and type(None) in get_args(type(d)) and d is None:
|
||||
return None
|
||||
if isinstance(d, Unset):
|
||||
return d
|
||||
|
||||
if not isinstance(d, Decimal):
|
||||
raise ValueError("Expected Decimal object")
|
||||
|
||||
return str(d) if as_str else float(d)
|
||||
|
||||
return serialize
|
||||
|
||||
|
||||
def validate_decimal(d):
|
||||
if d is None:
|
||||
return None
|
||||
|
||||
if isinstance(d, (Decimal, Unset)):
|
||||
return d
|
||||
|
||||
if not isinstance(d, (str, int, float)):
|
||||
raise ValueError("Expected string, int or float")
|
||||
|
||||
return Decimal(str(d))
|
||||
|
||||
|
||||
def serialize_float(as_str: bool):
|
||||
def serialize(f):
|
||||
# Optional[T] is a Union[T, None]
|
||||
if is_union(type(f)) and type(None) in get_args(type(f)) and f is None:
|
||||
return None
|
||||
if isinstance(f, Unset):
|
||||
return f
|
||||
|
||||
if not isinstance(f, float):
|
||||
raise ValueError("Expected float")
|
||||
|
||||
return str(f) if as_str else f
|
||||
|
||||
return serialize
|
||||
|
||||
|
||||
def validate_float(f):
|
||||
if f is None:
|
||||
return None
|
||||
|
||||
if isinstance(f, (float, Unset)):
|
||||
return f
|
||||
|
||||
if not isinstance(f, str):
|
||||
raise ValueError("Expected string")
|
||||
|
||||
return float(f)
|
||||
|
||||
|
||||
def serialize_int(as_str: bool):
|
||||
def serialize(i):
|
||||
# Optional[T] is a Union[T, None]
|
||||
if is_union(type(i)) and type(None) in get_args(type(i)) and i is None:
|
||||
return None
|
||||
if isinstance(i, Unset):
|
||||
return i
|
||||
|
||||
if not isinstance(i, int):
|
||||
raise ValueError("Expected int")
|
||||
|
||||
return str(i) if as_str else i
|
||||
|
||||
return serialize
|
||||
|
||||
|
||||
def validate_int(b):
|
||||
if b is None:
|
||||
return None
|
||||
|
||||
if isinstance(b, (int, Unset)):
|
||||
return b
|
||||
|
||||
if not isinstance(b, str):
|
||||
raise ValueError("Expected string")
|
||||
|
||||
return int(b)
|
||||
|
||||
|
||||
def validate_open_enum(is_int: bool):
|
||||
def validate(e):
|
||||
if e is None:
|
||||
return None
|
||||
|
||||
if isinstance(e, Unset):
|
||||
return e
|
||||
|
||||
if is_int:
|
||||
if not isinstance(e, int):
|
||||
raise ValueError("Expected int")
|
||||
else:
|
||||
if not isinstance(e, str):
|
||||
raise ValueError("Expected string")
|
||||
|
||||
return e
|
||||
|
||||
return validate
|
||||
|
||||
|
||||
def validate_const(v):
|
||||
def validate(c):
|
||||
# Optional[T] is a Union[T, None]
|
||||
if is_union(type(c)) and type(None) in get_args(type(c)) and c is None:
|
||||
return None
|
||||
|
||||
if v != c:
|
||||
raise ValueError(f"Expected {v}")
|
||||
|
||||
return c
|
||||
|
||||
return validate
|
||||
|
||||
|
||||
def unmarshal_json(raw, typ: Any) -> Any:
|
||||
return unmarshal(from_json(raw), typ)
|
||||
|
||||
|
||||
def unmarshal(val, typ: Any) -> Any:
|
||||
unmarshaller = create_model(
|
||||
"Unmarshaller",
|
||||
body=(typ, ...),
|
||||
__config__=ConfigDict(populate_by_name=True, arbitrary_types_allowed=True),
|
||||
)
|
||||
|
||||
m = unmarshaller(body=val)
|
||||
|
||||
# pyright: ignore[reportAttributeAccessIssue]
|
||||
return m.body # type: ignore
|
||||
|
||||
|
||||
def marshal_json(val, typ):
|
||||
if is_nullable(typ) and val is None:
|
||||
return "null"
|
||||
|
||||
marshaller = create_model(
|
||||
"Marshaller",
|
||||
body=(typ, ...),
|
||||
__config__=ConfigDict(populate_by_name=True, arbitrary_types_allowed=True),
|
||||
)
|
||||
|
||||
m = marshaller(body=val)
|
||||
|
||||
d = m.model_dump(by_alias=True, mode="json", exclude_none=True)
|
||||
|
||||
if len(d) == 0:
|
||||
return ""
|
||||
|
||||
return json.dumps(d[next(iter(d))], separators=(",", ":"))
|
||||
|
||||
|
||||
def is_nullable(field):
|
||||
origin = get_origin(field)
|
||||
if origin is Nullable or origin is OptionalNullable:
|
||||
return True
|
||||
|
||||
if not origin is Union or type(None) not in get_args(field):
|
||||
return False
|
||||
|
||||
for arg in get_args(field):
|
||||
if get_origin(arg) is Nullable or get_origin(arg) is OptionalNullable:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_union(obj: object) -> bool:
|
||||
"""
|
||||
Returns True if the given object is a typing.Union or typing_extensions.Union.
|
||||
"""
|
||||
return any(
|
||||
obj is typing_obj for typing_obj in _get_typing_objects_by_name_of("Union")
|
||||
)
|
||||
|
||||
|
||||
def stream_to_text(stream: httpx.Response) -> str:
|
||||
return "".join(stream.iter_text())
|
||||
|
||||
|
||||
async def stream_to_text_async(stream: httpx.Response) -> str:
|
||||
return "".join([chunk async for chunk in stream.aiter_text()])
|
||||
|
||||
|
||||
def stream_to_bytes(stream: httpx.Response) -> bytes:
|
||||
return stream.content
|
||||
|
||||
|
||||
async def stream_to_bytes_async(stream: httpx.Response) -> bytes:
|
||||
return await stream.aread()
|
||||
|
||||
|
||||
def get_pydantic_model(data: Any, typ: Any) -> Any:
|
||||
if not _contains_pydantic_model(data):
|
||||
return unmarshal(data, typ)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def _contains_pydantic_model(data: Any) -> bool:
|
||||
if isinstance(data, BaseModel):
|
||||
return True
|
||||
if isinstance(data, List):
|
||||
return any(_contains_pydantic_model(item) for item in data)
|
||||
if isinstance(data, Dict):
|
||||
return any(_contains_pydantic_model(value) for value in data.values())
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@functools.cache
|
||||
def _get_typing_objects_by_name_of(name: str) -> Tuple[Any, ...]:
|
||||
"""
|
||||
Get typing objects by name from typing and typing_extensions.
|
||||
Reference: https://typing-extensions.readthedocs.io/en/latest/#runtime-use-of-types
|
||||
"""
|
||||
result = tuple(
|
||||
getattr(module, name)
|
||||
for module in (typing, typing_extensions)
|
||||
if hasattr(module, name)
|
||||
)
|
||||
if not result:
|
||||
raise ValueError(
|
||||
f"Neither typing nor typing_extensions has an object called {name!r}"
|
||||
)
|
||||
return result
|
||||
@@ -0,0 +1,24 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
import httpx
|
||||
|
||||
from .serializers import unmarshal_json
|
||||
from openrouter import errors
|
||||
|
||||
|
||||
def unmarshal_json_response(
|
||||
typ: Any, http_res: httpx.Response, body: Optional[str] = None
|
||||
) -> Any:
|
||||
if body is None:
|
||||
body = http_res.text
|
||||
try:
|
||||
return unmarshal_json(body, typ)
|
||||
except Exception as e:
|
||||
raise errors.ResponseValidationError(
|
||||
"Response validation failed",
|
||||
http_res,
|
||||
e,
|
||||
body,
|
||||
) from e
|
||||
@@ -0,0 +1,155 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
get_type_hints,
|
||||
List,
|
||||
Optional,
|
||||
Union,
|
||||
get_args,
|
||||
get_origin,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from .metadata import (
|
||||
PathParamMetadata,
|
||||
find_field_metadata,
|
||||
)
|
||||
from .values import (
|
||||
_get_serialized_params,
|
||||
_is_set,
|
||||
_populate_from_globals,
|
||||
_val_to_string,
|
||||
)
|
||||
|
||||
|
||||
def generate_url(
|
||||
server_url: str,
|
||||
path: str,
|
||||
path_params: Any,
|
||||
gbls: Optional[Any] = None,
|
||||
) -> str:
|
||||
path_param_values: Dict[str, str] = {}
|
||||
|
||||
globals_already_populated = _populate_path_params(
|
||||
path_params, gbls, path_param_values, []
|
||||
)
|
||||
if _is_set(gbls):
|
||||
_populate_path_params(gbls, None, path_param_values, globals_already_populated)
|
||||
|
||||
for key, value in path_param_values.items():
|
||||
path = path.replace("{" + key + "}", value, 1)
|
||||
|
||||
return remove_suffix(server_url, "/") + path
|
||||
|
||||
|
||||
def _populate_path_params(
|
||||
path_params: Any,
|
||||
gbls: Any,
|
||||
path_param_values: Dict[str, str],
|
||||
skip_fields: List[str],
|
||||
) -> List[str]:
|
||||
globals_already_populated: List[str] = []
|
||||
|
||||
if not isinstance(path_params, BaseModel):
|
||||
return globals_already_populated
|
||||
|
||||
path_param_fields: Dict[str, FieldInfo] = path_params.__class__.model_fields
|
||||
path_param_field_types = get_type_hints(path_params.__class__)
|
||||
for name in path_param_fields:
|
||||
if name in skip_fields:
|
||||
continue
|
||||
|
||||
field = path_param_fields[name]
|
||||
|
||||
param_metadata = find_field_metadata(field, PathParamMetadata)
|
||||
if param_metadata is None:
|
||||
continue
|
||||
|
||||
param = getattr(path_params, name) if _is_set(path_params) else None
|
||||
param, global_found = _populate_from_globals(
|
||||
name, param, PathParamMetadata, gbls
|
||||
)
|
||||
if global_found:
|
||||
globals_already_populated.append(name)
|
||||
|
||||
if not _is_set(param):
|
||||
continue
|
||||
|
||||
f_name = field.alias if field.alias is not None else name
|
||||
serialization = param_metadata.serialization
|
||||
if serialization is not None:
|
||||
serialized_params = _get_serialized_params(
|
||||
param_metadata, f_name, param, path_param_field_types[name]
|
||||
)
|
||||
for key, value in serialized_params.items():
|
||||
path_param_values[key] = value
|
||||
else:
|
||||
pp_vals: List[str] = []
|
||||
if param_metadata.style == "simple":
|
||||
if isinstance(param, List):
|
||||
for pp_val in param:
|
||||
if not _is_set(pp_val):
|
||||
continue
|
||||
pp_vals.append(_val_to_string(pp_val))
|
||||
path_param_values[f_name] = ",".join(pp_vals)
|
||||
elif isinstance(param, Dict):
|
||||
for pp_key in param:
|
||||
if not _is_set(param[pp_key]):
|
||||
continue
|
||||
if param_metadata.explode:
|
||||
pp_vals.append(f"{pp_key}={_val_to_string(param[pp_key])}")
|
||||
else:
|
||||
pp_vals.append(f"{pp_key},{_val_to_string(param[pp_key])}")
|
||||
path_param_values[f_name] = ",".join(pp_vals)
|
||||
elif not isinstance(param, (str, int, float, complex, bool, Decimal)):
|
||||
param_fields: Dict[str, FieldInfo] = param.__class__.model_fields
|
||||
for name in param_fields:
|
||||
param_field = param_fields[name]
|
||||
|
||||
param_value_metadata = find_field_metadata(
|
||||
param_field, PathParamMetadata
|
||||
)
|
||||
if param_value_metadata is None:
|
||||
continue
|
||||
|
||||
param_name = (
|
||||
param_field.alias if param_field.alias is not None else name
|
||||
)
|
||||
|
||||
param_field_val = getattr(param, name)
|
||||
if not _is_set(param_field_val):
|
||||
continue
|
||||
if param_metadata.explode:
|
||||
pp_vals.append(
|
||||
f"{param_name}={_val_to_string(param_field_val)}"
|
||||
)
|
||||
else:
|
||||
pp_vals.append(
|
||||
f"{param_name},{_val_to_string(param_field_val)}"
|
||||
)
|
||||
path_param_values[f_name] = ",".join(pp_vals)
|
||||
elif _is_set(param):
|
||||
path_param_values[f_name] = _val_to_string(param)
|
||||
|
||||
return globals_already_populated
|
||||
|
||||
|
||||
def is_optional(field):
|
||||
return get_origin(field) is Union and type(None) in get_args(field)
|
||||
|
||||
|
||||
def template_url(url_with_params: str, params: Dict[str, str]) -> str:
|
||||
for key, value in params.items():
|
||||
url_with_params = url_with_params.replace("{" + key + "}", value)
|
||||
|
||||
return url_with_params
|
||||
|
||||
|
||||
def remove_suffix(input_string, suffix):
|
||||
if suffix and input_string.endswith(suffix):
|
||||
return input_string[: -len(suffix)]
|
||||
return input_string
|
||||
@@ -0,0 +1,137 @@
|
||||
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from email.message import Message
|
||||
from functools import partial
|
||||
import os
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast
|
||||
|
||||
from httpx import Response
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
from ..types.basemodel import Unset
|
||||
|
||||
from .serializers import marshal_json
|
||||
|
||||
from .metadata import ParamMetadata, find_field_metadata
|
||||
|
||||
|
||||
def match_content_type(content_type: str, pattern: str) -> bool:
|
||||
if pattern in (content_type, "*", "*/*"):
|
||||
return True
|
||||
|
||||
msg = Message()
|
||||
msg["content-type"] = content_type
|
||||
media_type = msg.get_content_type()
|
||||
|
||||
if media_type == pattern:
|
||||
return True
|
||||
|
||||
parts = media_type.split("/")
|
||||
if len(parts) == 2:
|
||||
if pattern in (f"{parts[0]}/*", f"*/{parts[1]}"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def match_status_codes(status_codes: List[str], status_code: int) -> bool:
|
||||
if "default" in status_codes:
|
||||
return True
|
||||
|
||||
for code in status_codes:
|
||||
if code == str(status_code):
|
||||
return True
|
||||
|
||||
if code.endswith("XX") and code.startswith(str(status_code)[:1]):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
def cast_partial(typ):
|
||||
return partial(cast, typ)
|
||||
|
||||
def get_global_from_env(
|
||||
value: Optional[T], env_key: str, type_cast: Callable[[str], T]
|
||||
) -> Optional[T]:
|
||||
if value is not None:
|
||||
return value
|
||||
env_value = os.getenv(env_key)
|
||||
if env_value is not None:
|
||||
try:
|
||||
return type_cast(env_value)
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def match_response(
|
||||
response: Response, code: Union[str, List[str]], content_type: str
|
||||
) -> bool:
|
||||
codes = code if isinstance(code, list) else [code]
|
||||
return match_status_codes(codes, response.status_code) and match_content_type(
|
||||
response.headers.get("content-type", "application/octet-stream"), content_type
|
||||
)
|
||||
|
||||
|
||||
def _populate_from_globals(
|
||||
param_name: str, value: Any, param_metadata_type: type, gbls: Any
|
||||
) -> Tuple[Any, bool]:
|
||||
if gbls is None:
|
||||
return value, False
|
||||
|
||||
if not isinstance(gbls, BaseModel):
|
||||
raise TypeError("globals must be a pydantic model")
|
||||
|
||||
global_fields: Dict[str, FieldInfo] = gbls.__class__.model_fields
|
||||
found = False
|
||||
for name in global_fields:
|
||||
field = global_fields[name]
|
||||
if name is not param_name:
|
||||
continue
|
||||
|
||||
found = True
|
||||
|
||||
if value is not None:
|
||||
return value, True
|
||||
|
||||
global_value = getattr(gbls, name)
|
||||
|
||||
param_metadata = find_field_metadata(field, param_metadata_type)
|
||||
if param_metadata is None:
|
||||
return value, True
|
||||
|
||||
return global_value, True
|
||||
|
||||
return value, found
|
||||
|
||||
|
||||
def _val_to_string(val) -> str:
|
||||
if isinstance(val, bool):
|
||||
return str(val).lower()
|
||||
if isinstance(val, datetime):
|
||||
return str(val.isoformat().replace("+00:00", "Z"))
|
||||
if isinstance(val, Enum):
|
||||
return str(val.value)
|
||||
|
||||
return str(val)
|
||||
|
||||
|
||||
def _get_serialized_params(
|
||||
metadata: ParamMetadata, field_name: str, obj: Any, typ: type
|
||||
) -> Dict[str, str]:
|
||||
params: Dict[str, str] = {}
|
||||
|
||||
serialization = metadata.serialization
|
||||
if serialization == "json":
|
||||
params[field_name] = marshal_json(obj, typ)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def _is_set(value: Any) -> bool:
|
||||
return value is not None and not isinstance(value, Unset)
|
||||
Reference in New Issue
Block a user