From efadea87ab3842f65b9a042ad00019285199c8ba Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:53:03 +0000 Subject: [PATCH 1/4] feat(api): api update (#12) --- .github/workflows/publish-pypi.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- LICENSE | 2 +- README.md | 46 ++++--- SECURITY.md | 4 +- bin/check-release-environment | 2 +- pyproject.toml | 4 +- src/arcadepy/__init__.py | 22 +--- src/arcadepy/_client.py | 136 ++++++--------------- src/arcadepy/_exceptions.py | 4 +- src/arcadepy/_resource.py | 10 +- src/arcadepy/_response.py | 4 +- src/arcadepy/_streaming.py | 6 +- src/arcadepy/_utils/_logs.py | 2 +- tests/api_resources/test_auth.py | 34 +++--- tests/api_resources/test_chat.py | 18 +-- tests/api_resources/test_health.py | 14 +-- tests/api_resources/test_tools.py | 42 +++---- tests/conftest.py | 10 +- tests/test_client.py | 176 ++++++++++++--------------- tests/test_response.py | 26 ++-- tests/test_streaming.py | 30 ++--- 22 files changed, 250 insertions(+), 346 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 918b838c..e68c2875 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -28,4 +28,4 @@ jobs: run: | bash ./bin/publish-pypi env: - PYPI_TOKEN: ${{ secrets.ARCADE_AI_PYPI_TOKEN || secrets.PYPI_TOKEN }} + PYPI_TOKEN: ${{ secrets.ARCADE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index a16324eb..d4ed5cf1 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -18,4 +18,4 @@ jobs: run: | bash ./bin/check-release-environment env: - PYPI_TOKEN: ${{ secrets.ARCADE_AI_PYPI_TOKEN || secrets.PYPI_TOKEN }} + PYPI_TOKEN: ${{ secrets.ARCADE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/LICENSE b/LICENSE index 334a3439..a47b4317 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2024 Arcade AI + Copyright 2024 Arcade Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 92047a12..7dfe008a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Arcade AI Python API library +# Arcade Python API library [![PyPI version](https://img.shields.io/pypi/v/arcadepy.svg)](https://pypi.org/project/arcadepy/) -The Arcade AI Python library provides convenient access to the Arcade AI REST API from any Python 3.7+ +The Arcade Python library provides convenient access to the Arcade REST API from any Python 3.7+ application. The library includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). @@ -28,13 +28,11 @@ The full API of this library can be found in [api.md](api.md). ```python import os -from arcadepy import ArcadeAI +from arcadepy import Arcade -client = ArcadeAI( +client = Arcade( # This is the default and can be omitted api_key=os.environ.get("ARCADE_API_KEY"), - # defaults to "production". - environment="staging", ) tool_response = client.tools.execute( @@ -53,18 +51,16 @@ so that your API Key is not stored in source control. ## Async usage -Simply import `AsyncArcadeAI` instead of `ArcadeAI` and use `await` with each API call: +Simply import `AsyncArcade` instead of `Arcade` and use `await` with each API call: ```python import os import asyncio -from arcadepy import AsyncArcadeAI +from arcadepy import AsyncArcade -client = AsyncArcadeAI( +client = AsyncArcade( # This is the default and can be omitted api_key=os.environ.get("ARCADE_API_KEY"), - # defaults to "production". - environment="staging", ) @@ -103,9 +99,9 @@ All errors inherit from `arcadepy.APIError`. ```python import arcadepy -from arcadepy import ArcadeAI +from arcadepy import Arcade -client = ArcadeAI() +client = Arcade() try: client.chat.completions( @@ -149,10 +145,10 @@ Connection errors (for example, due to a network connectivity problem), 408 Requ You can use the `max_retries` option to configure or disable retry settings: ```python -from arcadepy import ArcadeAI +from arcadepy import Arcade # Configure the default for all requests: -client = ArcadeAI( +client = Arcade( # default is 2 max_retries=0, ) @@ -174,16 +170,16 @@ By default requests time out after 1 minute. You can configure this with a `time which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object: ```python -from arcadepy import ArcadeAI +from arcadepy import Arcade # Configure the default for all requests: -client = ArcadeAI( +client = Arcade( # 20 seconds (default is 1 minute) timeout=20.0, ) # More granular control: -client = ArcadeAI( +client = Arcade( timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), ) @@ -208,10 +204,10 @@ Note that requests that time out are [retried twice by default](#retries). We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module. -You can enable logging by setting the environment variable `ARCADE_AI_LOG` to `debug`. +You can enable logging by setting the environment variable `ARCADE_LOG` to `debug`. ```shell -$ export ARCADE_AI_LOG=debug +$ export ARCADE_LOG=debug ``` ### How to tell whether `None` means `null` or missing @@ -231,9 +227,9 @@ if response.my_field is None: The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., ```py -from arcadepy import ArcadeAI +from arcadepy import Arcade -client = ArcadeAI() +client = Arcade() response = client.chat.with_raw_response.completions( messages=[{ "role": "user", @@ -317,10 +313,10 @@ You can directly override the [httpx client](https://www.python-httpx.org/api/#c - Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality ```python -from arcadepy import ArcadeAI, DefaultHttpxClient +from arcadepy import Arcade, DefaultHttpxClient -client = ArcadeAI( - # Or use the `ARCADE_AI_BASE_URL` env var +client = Arcade( + # Or use the `ARCADE_BASE_URL` env var base_url="http://my.test.server.example.com:8083", http_client=DefaultHttpxClient( proxies="http://my.test.proxy.example.com", diff --git a/SECURITY.md b/SECURITY.md index 3ab81032..a5382b7d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,9 +16,9 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Arcade AI please follow the respective company's security reporting guidelines. +or products provided by Arcade please follow the respective company's security reporting guidelines. -### Arcade AI Terms and Policies +### Arcade Terms and Policies Please contact contact@arcade-ai.com for any questions or concerns regarding security of our services. diff --git a/bin/check-release-environment b/bin/check-release-environment index b98a6fa0..adcf74b4 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -3,7 +3,7 @@ errors=() if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The ARCADE_AI_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") + errors+=("The ARCADE_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") fi lenErrors=${#errors[@]} diff --git a/pyproject.toml b/pyproject.toml index 30cb15e0..352d8399 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [project] name = "arcadepy" version = "0.1.0-alpha.2" -description = "The official Python library for the Arcade AI API" +description = "The official Python library for the Arcade API" dynamic = ["readme"] license = "Apache-2.0" authors = [ -{ name = "Arcade AI", email = "contact@arcade-ai.com" }, +{ name = "Arcade", email = "contact@arcade-ai.com" }, ] dependencies = [ "httpx>=0.23.0, <1", diff --git a/src/arcadepy/__init__.py b/src/arcadepy/__init__.py index 855de195..8f72a207 100644 --- a/src/arcadepy/__init__.py +++ b/src/arcadepy/__init__.py @@ -3,25 +3,14 @@ from . import types from ._types import NOT_GIVEN, NoneType, NotGiven, Transport, ProxiesTypes from ._utils import file_from_path -from ._client import ( - ENVIRONMENTS, - Client, - Stream, - Timeout, - ArcadeAI, - Transport, - AsyncClient, - AsyncStream, - AsyncArcadeAI, - RequestOptions, -) +from ._client import Arcade, Client, Stream, Timeout, Transport, AsyncArcade, AsyncClient, AsyncStream, RequestOptions from ._models import BaseModel from ._version import __title__, __version__ from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse from ._constants import DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_CONNECTION_LIMITS from ._exceptions import ( APIError, - ArcadeAIError, + ArcadeError, ConflictError, NotFoundError, APIStatusError, @@ -47,7 +36,7 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", - "ArcadeAIError", + "ArcadeError", "APIError", "APIStatusError", "APITimeoutError", @@ -67,9 +56,8 @@ "AsyncClient", "Stream", "AsyncStream", - "ArcadeAI", - "AsyncArcadeAI", - "ENVIRONMENTS", + "Arcade", + "AsyncArcade", "file_from_path", "BaseModel", "DEFAULT_TIMEOUT", diff --git a/src/arcadepy/_client.py b/src/arcadepy/_client.py index 41b0073b..2cf4cb44 100644 --- a/src/arcadepy/_client.py +++ b/src/arcadepy/_client.py @@ -3,8 +3,8 @@ from __future__ import annotations import os -from typing import Any, Dict, Union, Mapping, cast -from typing_extensions import Self, Literal, override +from typing import Any, Union, Mapping +from typing_extensions import Self, override import httpx @@ -25,7 +25,7 @@ ) from ._version import __version__ from ._streaming import Stream as Stream, AsyncStream as AsyncStream -from ._exceptions import ArcadeAIError, APIStatusError +from ._exceptions import ArcadeError, APIStatusError from ._base_client import ( DEFAULT_MAX_RETRIES, SyncAPIClient, @@ -33,43 +33,34 @@ ) __all__ = [ - "ENVIRONMENTS", "Timeout", "Transport", "ProxiesTypes", "RequestOptions", "resources", - "ArcadeAI", - "AsyncArcadeAI", + "Arcade", + "AsyncArcade", "Client", "AsyncClient", ] -ENVIRONMENTS: Dict[str, str] = { - "production": "https://api.arcade-ai.com", - "staging": "https://dev-api.arcade-ai.com", -} - -class ArcadeAI(SyncAPIClient): +class Arcade(SyncAPIClient): auth: resources.AuthResource chat: resources.ChatResource health: resources.HealthResource tools: resources.ToolsResource - with_raw_response: ArcadeAIWithRawResponse - with_streaming_response: ArcadeAIWithStreamedResponse + with_raw_response: ArcadeWithRawResponse + with_streaming_response: ArcadeWithStreamedResponse # client options api_key: str - _environment: Literal["production", "staging"] | NotGiven - def __init__( self, *, api_key: str | None = None, - environment: Literal["production", "staging"] | NotGiven = NOT_GIVEN, - base_url: str | httpx.URL | None | NotGiven = NOT_GIVEN, + base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -88,43 +79,22 @@ def __init__( # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: - """Construct a new synchronous Arcade AI client instance. + """Construct a new synchronous Arcade client instance. This automatically infers the `api_key` argument from the `ARCADE_API_KEY` environment variable if it is not provided. """ if api_key is None: api_key = os.environ.get("ARCADE_API_KEY") if api_key is None: - raise ArcadeAIError( + raise ArcadeError( "The api_key client option must be set either by passing api_key to the client or by setting the ARCADE_API_KEY environment variable" ) self.api_key = api_key - self._environment = environment - - base_url_env = os.environ.get("ARCADE_AI_BASE_URL") - if is_given(base_url) and base_url is not None: - # cast required because mypy doesn't understand the type narrowing - base_url = cast("str | httpx.URL", base_url) # pyright: ignore[reportUnnecessaryCast] - elif is_given(environment): - if base_url_env and base_url is not None: - raise ValueError( - "Ambiguous URL; The `ARCADE_AI_BASE_URL` env var and the `environment` argument are given. If you want to use the environment, you must pass base_url=None", - ) - - try: - base_url = ENVIRONMENTS[environment] - except KeyError as exc: - raise ValueError(f"Unknown environment: {environment}") from exc - elif base_url_env is not None: - base_url = base_url_env - else: - self._environment = environment = "production" - - try: - base_url = ENVIRONMENTS[environment] - except KeyError as exc: - raise ValueError(f"Unknown environment: {environment}") from exc + if base_url is None: + base_url = os.environ.get("ARCADE_BASE_URL") + if base_url is None: + base_url = f"https://api.arcade-ai.com" super().__init__( version=__version__, @@ -143,8 +113,8 @@ def __init__( self.chat = resources.ChatResource(self) self.health = resources.HealthResource(self) self.tools = resources.ToolsResource(self) - self.with_raw_response = ArcadeAIWithRawResponse(self) - self.with_streaming_response = ArcadeAIWithStreamedResponse(self) + self.with_raw_response = ArcadeWithRawResponse(self) + self.with_streaming_response = ArcadeWithStreamedResponse(self) @property @override @@ -170,7 +140,6 @@ def copy( self, *, api_key: str | None = None, - environment: Literal["production", "staging"] | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, @@ -206,7 +175,6 @@ def copy( return self.__class__( api_key=api_key or self.api_key, base_url=base_url or self.base_url, - environment=environment or self._environment, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, @@ -253,25 +221,22 @@ def _make_status_error( return APIStatusError(err_msg, response=response, body=body) -class AsyncArcadeAI(AsyncAPIClient): +class AsyncArcade(AsyncAPIClient): auth: resources.AsyncAuthResource chat: resources.AsyncChatResource health: resources.AsyncHealthResource tools: resources.AsyncToolsResource - with_raw_response: AsyncArcadeAIWithRawResponse - with_streaming_response: AsyncArcadeAIWithStreamedResponse + with_raw_response: AsyncArcadeWithRawResponse + with_streaming_response: AsyncArcadeWithStreamedResponse # client options api_key: str - _environment: Literal["production", "staging"] | NotGiven - def __init__( self, *, api_key: str | None = None, - environment: Literal["production", "staging"] | NotGiven = NOT_GIVEN, - base_url: str | httpx.URL | None | NotGiven = NOT_GIVEN, + base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -290,43 +255,22 @@ def __init__( # part of our public interface in the future. _strict_response_validation: bool = False, ) -> None: - """Construct a new async Arcade AI client instance. + """Construct a new async Arcade client instance. This automatically infers the `api_key` argument from the `ARCADE_API_KEY` environment variable if it is not provided. """ if api_key is None: api_key = os.environ.get("ARCADE_API_KEY") if api_key is None: - raise ArcadeAIError( + raise ArcadeError( "The api_key client option must be set either by passing api_key to the client or by setting the ARCADE_API_KEY environment variable" ) self.api_key = api_key - self._environment = environment - - base_url_env = os.environ.get("ARCADE_AI_BASE_URL") - if is_given(base_url) and base_url is not None: - # cast required because mypy doesn't understand the type narrowing - base_url = cast("str | httpx.URL", base_url) # pyright: ignore[reportUnnecessaryCast] - elif is_given(environment): - if base_url_env and base_url is not None: - raise ValueError( - "Ambiguous URL; The `ARCADE_AI_BASE_URL` env var and the `environment` argument are given. If you want to use the environment, you must pass base_url=None", - ) - - try: - base_url = ENVIRONMENTS[environment] - except KeyError as exc: - raise ValueError(f"Unknown environment: {environment}") from exc - elif base_url_env is not None: - base_url = base_url_env - else: - self._environment = environment = "production" - - try: - base_url = ENVIRONMENTS[environment] - except KeyError as exc: - raise ValueError(f"Unknown environment: {environment}") from exc + if base_url is None: + base_url = os.environ.get("ARCADE_BASE_URL") + if base_url is None: + base_url = f"https://api.arcade-ai.com" super().__init__( version=__version__, @@ -345,8 +289,8 @@ def __init__( self.chat = resources.AsyncChatResource(self) self.health = resources.AsyncHealthResource(self) self.tools = resources.AsyncToolsResource(self) - self.with_raw_response = AsyncArcadeAIWithRawResponse(self) - self.with_streaming_response = AsyncArcadeAIWithStreamedResponse(self) + self.with_raw_response = AsyncArcadeWithRawResponse(self) + self.with_streaming_response = AsyncArcadeWithStreamedResponse(self) @property @override @@ -372,7 +316,6 @@ def copy( self, *, api_key: str | None = None, - environment: Literal["production", "staging"] | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, @@ -408,7 +351,6 @@ def copy( return self.__class__( api_key=api_key or self.api_key, base_url=base_url or self.base_url, - environment=environment or self._environment, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, @@ -455,38 +397,38 @@ def _make_status_error( return APIStatusError(err_msg, response=response, body=body) -class ArcadeAIWithRawResponse: - def __init__(self, client: ArcadeAI) -> None: +class ArcadeWithRawResponse: + def __init__(self, client: Arcade) -> None: self.auth = resources.AuthResourceWithRawResponse(client.auth) self.chat = resources.ChatResourceWithRawResponse(client.chat) self.health = resources.HealthResourceWithRawResponse(client.health) self.tools = resources.ToolsResourceWithRawResponse(client.tools) -class AsyncArcadeAIWithRawResponse: - def __init__(self, client: AsyncArcadeAI) -> None: +class AsyncArcadeWithRawResponse: + def __init__(self, client: AsyncArcade) -> None: self.auth = resources.AsyncAuthResourceWithRawResponse(client.auth) self.chat = resources.AsyncChatResourceWithRawResponse(client.chat) self.health = resources.AsyncHealthResourceWithRawResponse(client.health) self.tools = resources.AsyncToolsResourceWithRawResponse(client.tools) -class ArcadeAIWithStreamedResponse: - def __init__(self, client: ArcadeAI) -> None: +class ArcadeWithStreamedResponse: + def __init__(self, client: Arcade) -> None: self.auth = resources.AuthResourceWithStreamingResponse(client.auth) self.chat = resources.ChatResourceWithStreamingResponse(client.chat) self.health = resources.HealthResourceWithStreamingResponse(client.health) self.tools = resources.ToolsResourceWithStreamingResponse(client.tools) -class AsyncArcadeAIWithStreamedResponse: - def __init__(self, client: AsyncArcadeAI) -> None: +class AsyncArcadeWithStreamedResponse: + def __init__(self, client: AsyncArcade) -> None: self.auth = resources.AsyncAuthResourceWithStreamingResponse(client.auth) self.chat = resources.AsyncChatResourceWithStreamingResponse(client.chat) self.health = resources.AsyncHealthResourceWithStreamingResponse(client.health) self.tools = resources.AsyncToolsResourceWithStreamingResponse(client.tools) -Client = ArcadeAI +Client = Arcade -AsyncClient = AsyncArcadeAI +AsyncClient = AsyncArcade diff --git a/src/arcadepy/_exceptions.py b/src/arcadepy/_exceptions.py index 6744a4c3..fd0cb6d8 100644 --- a/src/arcadepy/_exceptions.py +++ b/src/arcadepy/_exceptions.py @@ -18,11 +18,11 @@ ] -class ArcadeAIError(Exception): +class ArcadeError(Exception): pass -class APIError(ArcadeAIError): +class APIError(ArcadeError): message: str request: httpx.Request diff --git a/src/arcadepy/_resource.py b/src/arcadepy/_resource.py index 9ad5da43..f5eb4486 100644 --- a/src/arcadepy/_resource.py +++ b/src/arcadepy/_resource.py @@ -8,13 +8,13 @@ import anyio if TYPE_CHECKING: - from ._client import ArcadeAI, AsyncArcadeAI + from ._client import Arcade, AsyncArcade class SyncAPIResource: - _client: ArcadeAI + _client: Arcade - def __init__(self, client: ArcadeAI) -> None: + def __init__(self, client: Arcade) -> None: self._client = client self._get = client.get self._post = client.post @@ -28,9 +28,9 @@ def _sleep(self, seconds: float) -> None: class AsyncAPIResource: - _client: AsyncArcadeAI + _client: AsyncArcade - def __init__(self, client: AsyncArcadeAI) -> None: + def __init__(self, client: AsyncArcade) -> None: self._client = client self._get = client.get self._post = client.post diff --git a/src/arcadepy/_response.py b/src/arcadepy/_response.py index c71a72f6..70461f92 100644 --- a/src/arcadepy/_response.py +++ b/src/arcadepy/_response.py @@ -29,7 +29,7 @@ from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type -from ._exceptions import ArcadeAIError, APIResponseValidationError +from ._exceptions import ArcadeError, APIResponseValidationError if TYPE_CHECKING: from ._models import FinalRequestOptions @@ -554,7 +554,7 @@ def __init__(self) -> None: ) -class StreamAlreadyConsumed(ArcadeAIError): +class StreamAlreadyConsumed(ArcadeError): """ Attempted to read or stream content, but the content has already been streamed. diff --git a/src/arcadepy/_streaming.py b/src/arcadepy/_streaming.py index bca8270f..c3f35449 100644 --- a/src/arcadepy/_streaming.py +++ b/src/arcadepy/_streaming.py @@ -12,7 +12,7 @@ from ._utils import extract_type_var_from_base if TYPE_CHECKING: - from ._client import ArcadeAI, AsyncArcadeAI + from ._client import Arcade, AsyncArcade _T = TypeVar("_T") @@ -30,7 +30,7 @@ def __init__( *, cast_to: type[_T], response: httpx.Response, - client: ArcadeAI, + client: Arcade, ) -> None: self.response = response self._cast_to = cast_to @@ -93,7 +93,7 @@ def __init__( *, cast_to: type[_T], response: httpx.Response, - client: AsyncArcadeAI, + client: AsyncArcade, ) -> None: self.response = response self._cast_to = cast_to diff --git a/src/arcadepy/_utils/_logs.py b/src/arcadepy/_utils/_logs.py index ea2b4608..4d36ed2d 100644 --- a/src/arcadepy/_utils/_logs.py +++ b/src/arcadepy/_utils/_logs.py @@ -14,7 +14,7 @@ def _basic_config() -> None: def setup_logging() -> None: - env = os.environ.get("ARCADE_AI_LOG") + env = os.environ.get("ARCADE_LOG") if env == "debug": _basic_config() logger.setLevel(logging.DEBUG) diff --git a/tests/api_resources/test_auth.py b/tests/api_resources/test_auth.py index d4171b49..d0816c46 100644 --- a/tests/api_resources/test_auth.py +++ b/tests/api_resources/test_auth.py @@ -7,7 +7,7 @@ import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type from arcadepy.types import AuthorizationResponse @@ -18,7 +18,7 @@ class TestAuth: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_authorize(self, client: ArcadeAI) -> None: + def test_method_authorize(self, client: Arcade) -> None: auth = client.auth.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -26,7 +26,7 @@ def test_method_authorize(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_method_authorize_with_all_params(self, client: ArcadeAI) -> None: + def test_method_authorize_with_all_params(self, client: Arcade) -> None: auth = client.auth.authorize( auth_requirement={ "provider": "provider", @@ -40,7 +40,7 @@ def test_method_authorize_with_all_params(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_raw_response_authorize(self, client: ArcadeAI) -> None: + def test_raw_response_authorize(self, client: Arcade) -> None: response = client.auth.with_raw_response.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -52,7 +52,7 @@ def test_raw_response_authorize(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_streaming_response_authorize(self, client: ArcadeAI) -> None: + def test_streaming_response_authorize(self, client: Arcade) -> None: with client.auth.with_streaming_response.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -66,14 +66,14 @@ def test_streaming_response_authorize(self, client: ArcadeAI) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_status(self, client: ArcadeAI) -> None: + def test_method_status(self, client: Arcade) -> None: auth = client.auth.status( authorization_id="authorizationID", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_method_status_with_all_params(self, client: ArcadeAI) -> None: + def test_method_status_with_all_params(self, client: Arcade) -> None: auth = client.auth.status( authorization_id="authorizationID", scopes="scopes", @@ -81,7 +81,7 @@ def test_method_status_with_all_params(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_raw_response_status(self, client: ArcadeAI) -> None: + def test_raw_response_status(self, client: Arcade) -> None: response = client.auth.with_raw_response.status( authorization_id="authorizationID", ) @@ -92,7 +92,7 @@ def test_raw_response_status(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - def test_streaming_response_status(self, client: ArcadeAI) -> None: + def test_streaming_response_status(self, client: Arcade) -> None: with client.auth.with_streaming_response.status( authorization_id="authorizationID", ) as response: @@ -109,7 +109,7 @@ class TestAsyncAuth: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_method_authorize(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -117,7 +117,7 @@ async def test_method_authorize(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_method_authorize_with_all_params(self, async_client: AsyncArcadeAI) -> None: + async def test_method_authorize_with_all_params(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.authorize( auth_requirement={ "provider": "provider", @@ -131,7 +131,7 @@ async def test_method_authorize_with_all_params(self, async_client: AsyncArcadeA assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_raw_response_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_authorize(self, async_client: AsyncArcade) -> None: response = await async_client.auth.with_raw_response.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -143,7 +143,7 @@ async def test_raw_response_authorize(self, async_client: AsyncArcadeAI) -> None assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_streaming_response_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_authorize(self, async_client: AsyncArcade) -> None: async with async_client.auth.with_streaming_response.authorize( auth_requirement={"provider": "provider"}, user_id="user_id", @@ -157,14 +157,14 @@ async def test_streaming_response_authorize(self, async_client: AsyncArcadeAI) - assert cast(Any, response.is_closed) is True @parametrize - async def test_method_status(self, async_client: AsyncArcadeAI) -> None: + async def test_method_status(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.status( authorization_id="authorizationID", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_method_status_with_all_params(self, async_client: AsyncArcadeAI) -> None: + async def test_method_status_with_all_params(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.status( authorization_id="authorizationID", scopes="scopes", @@ -172,7 +172,7 @@ async def test_method_status_with_all_params(self, async_client: AsyncArcadeAI) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_raw_response_status(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_status(self, async_client: AsyncArcade) -> None: response = await async_client.auth.with_raw_response.status( authorization_id="authorizationID", ) @@ -183,7 +183,7 @@ async def test_raw_response_status(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize - async def test_streaming_response_status(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_status(self, async_client: AsyncArcade) -> None: async with async_client.auth.with_streaming_response.status( authorization_id="authorizationID", ) as response: diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py index 455b858a..0b6b9658 100644 --- a/tests/api_resources/test_chat.py +++ b/tests/api_resources/test_chat.py @@ -7,7 +7,7 @@ import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type from arcadepy.types import ChatResponse @@ -18,12 +18,12 @@ class TestChat: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_completions(self, client: ArcadeAI) -> None: + def test_method_completions(self, client: Arcade) -> None: chat = client.chat.completions() assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - def test_method_completions_with_all_params(self, client: ArcadeAI) -> None: + def test_method_completions_with_all_params(self, client: Arcade) -> None: chat = client.chat.completions( frequency_penalty=0, logit_bias={"foo": 0}, @@ -146,7 +146,7 @@ def test_method_completions_with_all_params(self, client: ArcadeAI) -> None: assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - def test_raw_response_completions(self, client: ArcadeAI) -> None: + def test_raw_response_completions(self, client: Arcade) -> None: response = client.chat.with_raw_response.completions() assert response.is_closed is True @@ -155,7 +155,7 @@ def test_raw_response_completions(self, client: ArcadeAI) -> None: assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - def test_streaming_response_completions(self, client: ArcadeAI) -> None: + def test_streaming_response_completions(self, client: Arcade) -> None: with client.chat.with_streaming_response.completions() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -170,12 +170,12 @@ class TestAsyncChat: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_completions(self, async_client: AsyncArcadeAI) -> None: + async def test_method_completions(self, async_client: AsyncArcade) -> None: chat = await async_client.chat.completions() assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - async def test_method_completions_with_all_params(self, async_client: AsyncArcadeAI) -> None: + async def test_method_completions_with_all_params(self, async_client: AsyncArcade) -> None: chat = await async_client.chat.completions( frequency_penalty=0, logit_bias={"foo": 0}, @@ -298,7 +298,7 @@ async def test_method_completions_with_all_params(self, async_client: AsyncArcad assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - async def test_raw_response_completions(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_completions(self, async_client: AsyncArcade) -> None: response = await async_client.chat.with_raw_response.completions() assert response.is_closed is True @@ -307,7 +307,7 @@ async def test_raw_response_completions(self, async_client: AsyncArcadeAI) -> No assert_matches_type(ChatResponse, chat, path=["response"]) @parametrize - async def test_streaming_response_completions(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_completions(self, async_client: AsyncArcade) -> None: async with async_client.chat.with_streaming_response.completions() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_health.py b/tests/api_resources/test_health.py index ca3ffc14..910a6ac0 100644 --- a/tests/api_resources/test_health.py +++ b/tests/api_resources/test_health.py @@ -7,7 +7,7 @@ import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type from arcadepy.types import HealthSchema @@ -18,12 +18,12 @@ class TestHealth: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_check(self, client: ArcadeAI) -> None: + def test_method_check(self, client: Arcade) -> None: health = client.health.check() assert_matches_type(HealthSchema, health, path=["response"]) @parametrize - def test_raw_response_check(self, client: ArcadeAI) -> None: + def test_raw_response_check(self, client: Arcade) -> None: response = client.health.with_raw_response.check() assert response.is_closed is True @@ -32,7 +32,7 @@ def test_raw_response_check(self, client: ArcadeAI) -> None: assert_matches_type(HealthSchema, health, path=["response"]) @parametrize - def test_streaming_response_check(self, client: ArcadeAI) -> None: + def test_streaming_response_check(self, client: Arcade) -> None: with client.health.with_streaming_response.check() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -47,12 +47,12 @@ class TestAsyncHealth: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_check(self, async_client: AsyncArcadeAI) -> None: + async def test_method_check(self, async_client: AsyncArcade) -> None: health = await async_client.health.check() assert_matches_type(HealthSchema, health, path=["response"]) @parametrize - async def test_raw_response_check(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_check(self, async_client: AsyncArcade) -> None: response = await async_client.health.with_raw_response.check() assert response.is_closed is True @@ -61,7 +61,7 @@ async def test_raw_response_check(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(HealthSchema, health, path=["response"]) @parametrize - async def test_streaming_response_check(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_check(self, async_client: AsyncArcade) -> None: async with async_client.health.with_streaming_response.check() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_tools.py b/tests/api_resources/test_tools.py index 6a0d501a..8fbcf4a6 100644 --- a/tests/api_resources/test_tools.py +++ b/tests/api_resources/test_tools.py @@ -7,7 +7,7 @@ import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type from arcadepy.types import ( ToolResponse, @@ -22,7 +22,7 @@ class TestTools: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_authorize(self, client: ArcadeAI) -> None: + def test_method_authorize(self, client: Arcade) -> None: tool = client.tools.authorize( tool_name="tool_name", user_id="user_id", @@ -30,7 +30,7 @@ def test_method_authorize(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - def test_method_authorize_with_all_params(self, client: ArcadeAI) -> None: + def test_method_authorize_with_all_params(self, client: Arcade) -> None: tool = client.tools.authorize( tool_name="tool_name", user_id="user_id", @@ -39,7 +39,7 @@ def test_method_authorize_with_all_params(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - def test_raw_response_authorize(self, client: ArcadeAI) -> None: + def test_raw_response_authorize(self, client: Arcade) -> None: response = client.tools.with_raw_response.authorize( tool_name="tool_name", user_id="user_id", @@ -51,7 +51,7 @@ def test_raw_response_authorize(self, client: ArcadeAI) -> None: assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - def test_streaming_response_authorize(self, client: ArcadeAI) -> None: + def test_streaming_response_authorize(self, client: Arcade) -> None: with client.tools.with_streaming_response.authorize( tool_name="tool_name", user_id="user_id", @@ -65,7 +65,7 @@ def test_streaming_response_authorize(self, client: ArcadeAI) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_execute(self, client: ArcadeAI) -> None: + def test_method_execute(self, client: Arcade) -> None: tool = client.tools.execute( inputs="inputs", tool_name="tool_name", @@ -75,7 +75,7 @@ def test_method_execute(self, client: ArcadeAI) -> None: assert_matches_type(ToolResponse, tool, path=["response"]) @parametrize - def test_raw_response_execute(self, client: ArcadeAI) -> None: + def test_raw_response_execute(self, client: Arcade) -> None: response = client.tools.with_raw_response.execute( inputs="inputs", tool_name="tool_name", @@ -89,7 +89,7 @@ def test_raw_response_execute(self, client: ArcadeAI) -> None: assert_matches_type(ToolResponse, tool, path=["response"]) @parametrize - def test_streaming_response_execute(self, client: ArcadeAI) -> None: + def test_streaming_response_execute(self, client: Arcade) -> None: with client.tools.with_streaming_response.execute( inputs="inputs", tool_name="tool_name", @@ -105,7 +105,7 @@ def test_streaming_response_execute(self, client: ArcadeAI) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_method_retrieve_definition(self, client: ArcadeAI) -> None: + def test_method_retrieve_definition(self, client: Arcade) -> None: tool = client.tools.retrieve_definition( director_id="director_id", tool_id="tool_id", @@ -113,7 +113,7 @@ def test_method_retrieve_definition(self, client: ArcadeAI) -> None: assert_matches_type(ToolDefinition, tool, path=["response"]) @parametrize - def test_raw_response_retrieve_definition(self, client: ArcadeAI) -> None: + def test_raw_response_retrieve_definition(self, client: Arcade) -> None: response = client.tools.with_raw_response.retrieve_definition( director_id="director_id", tool_id="tool_id", @@ -125,7 +125,7 @@ def test_raw_response_retrieve_definition(self, client: ArcadeAI) -> None: assert_matches_type(ToolDefinition, tool, path=["response"]) @parametrize - def test_streaming_response_retrieve_definition(self, client: ArcadeAI) -> None: + def test_streaming_response_retrieve_definition(self, client: Arcade) -> None: with client.tools.with_streaming_response.retrieve_definition( director_id="director_id", tool_id="tool_id", @@ -143,7 +143,7 @@ class TestAsyncTools: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_method_authorize(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.authorize( tool_name="tool_name", user_id="user_id", @@ -151,7 +151,7 @@ async def test_method_authorize(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - async def test_method_authorize_with_all_params(self, async_client: AsyncArcadeAI) -> None: + async def test_method_authorize_with_all_params(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.authorize( tool_name="tool_name", user_id="user_id", @@ -160,7 +160,7 @@ async def test_method_authorize_with_all_params(self, async_client: AsyncArcadeA assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - async def test_raw_response_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_authorize(self, async_client: AsyncArcade) -> None: response = await async_client.tools.with_raw_response.authorize( tool_name="tool_name", user_id="user_id", @@ -172,7 +172,7 @@ async def test_raw_response_authorize(self, async_client: AsyncArcadeAI) -> None assert_matches_type(AuthorizationResponse, tool, path=["response"]) @parametrize - async def test_streaming_response_authorize(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_authorize(self, async_client: AsyncArcade) -> None: async with async_client.tools.with_streaming_response.authorize( tool_name="tool_name", user_id="user_id", @@ -186,7 +186,7 @@ async def test_streaming_response_authorize(self, async_client: AsyncArcadeAI) - assert cast(Any, response.is_closed) is True @parametrize - async def test_method_execute(self, async_client: AsyncArcadeAI) -> None: + async def test_method_execute(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.execute( inputs="inputs", tool_name="tool_name", @@ -196,7 +196,7 @@ async def test_method_execute(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(ToolResponse, tool, path=["response"]) @parametrize - async def test_raw_response_execute(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_execute(self, async_client: AsyncArcade) -> None: response = await async_client.tools.with_raw_response.execute( inputs="inputs", tool_name="tool_name", @@ -210,7 +210,7 @@ async def test_raw_response_execute(self, async_client: AsyncArcadeAI) -> None: assert_matches_type(ToolResponse, tool, path=["response"]) @parametrize - async def test_streaming_response_execute(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_execute(self, async_client: AsyncArcade) -> None: async with async_client.tools.with_streaming_response.execute( inputs="inputs", tool_name="tool_name", @@ -226,7 +226,7 @@ async def test_streaming_response_execute(self, async_client: AsyncArcadeAI) -> assert cast(Any, response.is_closed) is True @parametrize - async def test_method_retrieve_definition(self, async_client: AsyncArcadeAI) -> None: + async def test_method_retrieve_definition(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.retrieve_definition( director_id="director_id", tool_id="tool_id", @@ -234,7 +234,7 @@ async def test_method_retrieve_definition(self, async_client: AsyncArcadeAI) -> assert_matches_type(ToolDefinition, tool, path=["response"]) @parametrize - async def test_raw_response_retrieve_definition(self, async_client: AsyncArcadeAI) -> None: + async def test_raw_response_retrieve_definition(self, async_client: AsyncArcade) -> None: response = await async_client.tools.with_raw_response.retrieve_definition( director_id="director_id", tool_id="tool_id", @@ -246,7 +246,7 @@ async def test_raw_response_retrieve_definition(self, async_client: AsyncArcadeA assert_matches_type(ToolDefinition, tool, path=["response"]) @parametrize - async def test_streaming_response_retrieve_definition(self, async_client: AsyncArcadeAI) -> None: + async def test_streaming_response_retrieve_definition(self, async_client: AsyncArcade) -> None: async with async_client.tools.with_streaming_response.retrieve_definition( director_id="director_id", tool_id="tool_id", diff --git a/tests/conftest.py b/tests/conftest.py index ba66b4aa..2206dddb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,7 @@ import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade if TYPE_CHECKING: from _pytest.fixtures import FixtureRequest @@ -30,20 +30,20 @@ def event_loop() -> Iterator[asyncio.AbstractEventLoop]: @pytest.fixture(scope="session") -def client(request: FixtureRequest) -> Iterator[ArcadeAI]: +def client(request: FixtureRequest) -> Iterator[Arcade]: strict = getattr(request, "param", True) if not isinstance(strict, bool): raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - with ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + with Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client @pytest.fixture(scope="session") -async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncArcadeAI]: +async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncArcade]: strict = getattr(request, "param", True) if not isinstance(strict, bool): raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - async with AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + async with AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client diff --git a/tests/test_client.py b/tests/test_client.py index 534824d3..04929ebb 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -16,11 +16,11 @@ from respx import MockRouter from pydantic import ValidationError -from arcadepy import ArcadeAI, AsyncArcadeAI, APIResponseValidationError +from arcadepy import Arcade, AsyncArcade, APIResponseValidationError from arcadepy._types import Omit from arcadepy._models import BaseModel, FinalRequestOptions from arcadepy._constants import RAW_RESPONSE_HEADER -from arcadepy._exceptions import ArcadeAIError, APIStatusError, APITimeoutError, APIResponseValidationError +from arcadepy._exceptions import ArcadeError, APIStatusError, APITimeoutError, APIResponseValidationError from arcadepy._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, @@ -44,7 +44,7 @@ def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 -def _get_open_connections(client: ArcadeAI | AsyncArcadeAI) -> int: +def _get_open_connections(client: Arcade | AsyncArcade) -> int: transport = client._client._transport assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) @@ -52,8 +52,8 @@ def _get_open_connections(client: ArcadeAI | AsyncArcadeAI) -> int: return len(pool._requests) -class TestArcadeAI: - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) +class TestArcade: + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter) -> None: @@ -100,7 +100,7 @@ def test_copy_default_options(self) -> None: assert isinstance(self.client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" @@ -134,7 +134,7 @@ def test_copy_default_headers(self) -> None: client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) def test_copy_default_query(self) -> None: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -259,9 +259,7 @@ def test_request_timeout(self) -> None: assert timeout == httpx.Timeout(100.0) def test_client_timeout_option(self) -> None: - client = ArcadeAI( - base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) - ) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0)) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore @@ -270,7 +268,7 @@ def test_client_timeout_option(self) -> None: def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -280,7 +278,7 @@ def test_http_client_timeout_option(self) -> None: # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -290,7 +288,7 @@ def test_http_client_timeout_option(self) -> None: # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -301,7 +299,7 @@ def test_http_client_timeout_option(self) -> None: async def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): async with httpx.AsyncClient() as http_client: - ArcadeAI( + Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -309,14 +307,14 @@ async def test_invalid_http_client(self) -> None: ) def test_default_headers_option(self) -> None: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = ArcadeAI( + client2 = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -330,17 +328,17 @@ def test_default_headers_option(self) -> None: assert request.headers.get("x-stainless-lang") == "my-overriding-header" def test_validate_headers(self) -> None: - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("Authorization") == api_key - with pytest.raises(ArcadeAIError): + with pytest.raises(ArcadeError): with update_env(**{"ARCADE_API_KEY": Omit()}): - client2 = ArcadeAI(base_url=base_url, api_key=None, _strict_response_validation=True) + client2 = Arcade(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: - client = ArcadeAI( + client = Arcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -454,7 +452,7 @@ def test_request_extra_query(self) -> None: params = dict(request.url.params) assert params == {"foo": "2"} - def test_multipart_repeating_array(self, client: ArcadeAI) -> None: + def test_multipart_repeating_array(self, client: Arcade) -> None: request = client._build_request( FinalRequestOptions.construct( method="get", @@ -572,7 +570,7 @@ def test_idempotency_header_options(self, respx_mock: MockRouter) -> None: assert response.request.headers.get("Idempotency-Key") == "custom-key" def test_base_url_setter(self) -> None: - client = ArcadeAI(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) + client = Arcade(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) assert client.base_url == "https://example.com/from_init/" client.base_url = "https://example.com/from_setter" # type: ignore[assignment] @@ -580,25 +578,15 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" def test_base_url_env(self) -> None: - with update_env(ARCADE_AI_BASE_URL="http://localhost:5000/from/env"): - client = ArcadeAI(api_key=api_key, _strict_response_validation=True) + with update_env(ARCADE_BASE_URL="http://localhost:5000/from/env"): + client = Arcade(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" - # explicit environment arg requires explicitness - with update_env(ARCADE_AI_BASE_URL="http://localhost:5000/from/env"): - with pytest.raises(ValueError, match=r"you must pass base_url=None"): - ArcadeAI(api_key=api_key, _strict_response_validation=True, environment="production") - - client = ArcadeAI( - base_url=None, api_key=api_key, _strict_response_validation=True, environment="production" - ) - assert str(client.base_url).startswith("https://api.arcade-ai.com") - @pytest.mark.parametrize( "client", [ - ArcadeAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - ArcadeAI( + Arcade(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + Arcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -607,7 +595,7 @@ def test_base_url_env(self) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_trailing_slash(self, client: ArcadeAI) -> None: + def test_base_url_trailing_slash(self, client: Arcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -620,8 +608,8 @@ def test_base_url_trailing_slash(self, client: ArcadeAI) -> None: @pytest.mark.parametrize( "client", [ - ArcadeAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - ArcadeAI( + Arcade(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + Arcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -630,7 +618,7 @@ def test_base_url_trailing_slash(self, client: ArcadeAI) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_no_trailing_slash(self, client: ArcadeAI) -> None: + def test_base_url_no_trailing_slash(self, client: Arcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -643,8 +631,8 @@ def test_base_url_no_trailing_slash(self, client: ArcadeAI) -> None: @pytest.mark.parametrize( "client", [ - ArcadeAI(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - ArcadeAI( + Arcade(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), + Arcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -653,7 +641,7 @@ def test_base_url_no_trailing_slash(self, client: ArcadeAI) -> None: ], ids=["standard", "custom http client"], ) - def test_absolute_request_url(self, client: ArcadeAI) -> None: + def test_absolute_request_url(self, client: Arcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -664,7 +652,7 @@ def test_absolute_request_url(self, client: ArcadeAI) -> None: assert request.url == "https://myapi.com/foo" def test_copied_client_does_not_close_http(self) -> None: - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -675,7 +663,7 @@ def test_copied_client_does_not_close_http(self) -> None: assert not client.is_closed() def test_client_context_manager(self) -> None: - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) with client as c2: assert c2 is client assert not c2.is_closed() @@ -696,7 +684,7 @@ class Model(BaseModel): def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) + Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) @pytest.mark.respx(base_url=base_url) def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -705,12 +693,12 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - strict_client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + strict_client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=False) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -738,7 +726,7 @@ class Model(BaseModel): ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = ArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Arcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) @@ -798,7 +786,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) @mock.patch("arcadepy._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) - def test_retries_taken(self, client: ArcadeAI, failures_before_success: int, respx_mock: MockRouter) -> None: + def test_retries_taken(self, client: Arcade, failures_before_success: int, respx_mock: MockRouter) -> None: client = client.with_options(max_retries=4) nb_retries = 0 @@ -821,7 +809,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @mock.patch("arcadepy._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_omit_retry_count_header( - self, client: ArcadeAI, failures_before_success: int, respx_mock: MockRouter + self, client: Arcade, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) @@ -844,7 +832,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @mock.patch("arcadepy._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( - self, client: ArcadeAI, failures_before_success: int, respx_mock: MockRouter + self, client: Arcade, failures_before_success: int, respx_mock: MockRouter ) -> None: client = client.with_options(max_retries=4) @@ -864,8 +852,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" -class TestAsyncArcadeAI: - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) +class TestAsyncArcade: + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio @@ -914,7 +902,7 @@ def test_copy_default_options(self) -> None: assert isinstance(self.client.timeout, httpx.Timeout) def test_copy_default_headers(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" @@ -948,7 +936,7 @@ def test_copy_default_headers(self) -> None: client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) def test_copy_default_query(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -1073,7 +1061,7 @@ async def test_request_timeout(self) -> None: assert timeout == httpx.Timeout(100.0) async def test_client_timeout_option(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) ) @@ -1084,7 +1072,7 @@ async def test_client_timeout_option(self) -> None: async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -1094,7 +1082,7 @@ async def test_http_client_timeout_option(self) -> None: # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -1104,7 +1092,7 @@ async def test_http_client_timeout_option(self) -> None: # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) @@ -1115,7 +1103,7 @@ async def test_http_client_timeout_option(self) -> None: def test_invalid_http_client(self) -> None: with pytest.raises(TypeError, match="Invalid `http_client` arg"): with httpx.Client() as http_client: - AsyncArcadeAI( + AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -1123,14 +1111,14 @@ def test_invalid_http_client(self) -> None: ) def test_default_headers_option(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" assert request.headers.get("x-stainless-lang") == "python" - client2 = AsyncArcadeAI( + client2 = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, @@ -1144,17 +1132,17 @@ def test_default_headers_option(self) -> None: assert request.headers.get("x-stainless-lang") == "my-overriding-header" def test_validate_headers(self) -> None: - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("Authorization") == api_key - with pytest.raises(ArcadeAIError): + with pytest.raises(ArcadeError): with update_env(**{"ARCADE_API_KEY": Omit()}): - client2 = AsyncArcadeAI(base_url=base_url, api_key=None, _strict_response_validation=True) + client2 = AsyncArcade(base_url=base_url, api_key=None, _strict_response_validation=True) _ = client2 def test_default_query_option(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1268,7 +1256,7 @@ def test_request_extra_query(self) -> None: params = dict(request.url.params) assert params == {"foo": "2"} - def test_multipart_repeating_array(self, async_client: AsyncArcadeAI) -> None: + def test_multipart_repeating_array(self, async_client: AsyncArcade) -> None: request = async_client._build_request( FinalRequestOptions.construct( method="get", @@ -1386,7 +1374,7 @@ async def test_idempotency_header_options(self, respx_mock: MockRouter) -> None: assert response.request.headers.get("Idempotency-Key") == "custom-key" def test_base_url_setter(self) -> None: - client = AsyncArcadeAI( + client = AsyncArcade( base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True ) assert client.base_url == "https://example.com/from_init/" @@ -1396,27 +1384,17 @@ def test_base_url_setter(self) -> None: assert client.base_url == "https://example.com/from_setter/" def test_base_url_env(self) -> None: - with update_env(ARCADE_AI_BASE_URL="http://localhost:5000/from/env"): - client = AsyncArcadeAI(api_key=api_key, _strict_response_validation=True) + with update_env(ARCADE_BASE_URL="http://localhost:5000/from/env"): + client = AsyncArcade(api_key=api_key, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" - # explicit environment arg requires explicitness - with update_env(ARCADE_AI_BASE_URL="http://localhost:5000/from/env"): - with pytest.raises(ValueError, match=r"you must pass base_url=None"): - AsyncArcadeAI(api_key=api_key, _strict_response_validation=True, environment="production") - - client = AsyncArcadeAI( - base_url=None, api_key=api_key, _strict_response_validation=True, environment="production" - ) - assert str(client.base_url).startswith("https://api.arcade-ai.com") - @pytest.mark.parametrize( "client", [ - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -1425,7 +1403,7 @@ def test_base_url_env(self) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_trailing_slash(self, client: AsyncArcadeAI) -> None: + def test_base_url_trailing_slash(self, client: AsyncArcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1438,10 +1416,10 @@ def test_base_url_trailing_slash(self, client: AsyncArcadeAI) -> None: @pytest.mark.parametrize( "client", [ - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -1450,7 +1428,7 @@ def test_base_url_trailing_slash(self, client: AsyncArcadeAI) -> None: ], ids=["standard", "custom http client"], ) - def test_base_url_no_trailing_slash(self, client: AsyncArcadeAI) -> None: + def test_base_url_no_trailing_slash(self, client: AsyncArcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1463,10 +1441,10 @@ def test_base_url_no_trailing_slash(self, client: AsyncArcadeAI) -> None: @pytest.mark.parametrize( "client", [ - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), - AsyncArcadeAI( + AsyncArcade( base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True, @@ -1475,7 +1453,7 @@ def test_base_url_no_trailing_slash(self, client: AsyncArcadeAI) -> None: ], ids=["standard", "custom http client"], ) - def test_absolute_request_url(self, client: AsyncArcadeAI) -> None: + def test_absolute_request_url(self, client: AsyncArcade) -> None: request = client._build_request( FinalRequestOptions( method="post", @@ -1486,7 +1464,7 @@ def test_absolute_request_url(self, client: AsyncArcadeAI) -> None: assert request.url == "https://myapi.com/foo" async def test_copied_client_does_not_close_http(self) -> None: - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -1498,7 +1476,7 @@ async def test_copied_client_does_not_close_http(self) -> None: assert not client.is_closed() async def test_client_context_manager(self) -> None: - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) async with client as c2: assert c2 is client assert not c2.is_closed() @@ -1520,7 +1498,7 @@ class Model(BaseModel): async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - AsyncArcadeAI( + AsyncArcade( base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) ) @@ -1532,12 +1510,12 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - strict_client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + strict_client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=False) + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = await client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -1566,7 +1544,7 @@ class Model(BaseModel): @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) @pytest.mark.asyncio async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = AsyncArcadeAI(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncArcade(base_url=base_url, api_key=api_key, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) @@ -1628,7 +1606,7 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_retries_taken( - self, async_client: AsyncArcadeAI, failures_before_success: int, respx_mock: MockRouter + self, async_client: AsyncArcade, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1653,7 +1631,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_omit_retry_count_header( - self, async_client: AsyncArcadeAI, failures_before_success: int, respx_mock: MockRouter + self, async_client: AsyncArcade, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) @@ -1677,7 +1655,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_overwrite_retry_count_header( - self, async_client: AsyncArcadeAI, failures_before_success: int, respx_mock: MockRouter + self, async_client: AsyncArcade, failures_before_success: int, respx_mock: MockRouter ) -> None: client = async_client.with_options(max_retries=4) diff --git a/tests/test_response.py b/tests/test_response.py index 2551438b..11e31ec9 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -6,7 +6,7 @@ import pytest import pydantic -from arcadepy import ArcadeAI, BaseModel, AsyncArcadeAI +from arcadepy import Arcade, BaseModel, AsyncArcade from arcadepy._response import ( APIResponse, BaseAPIResponse, @@ -56,7 +56,7 @@ def test_extract_response_type_binary_response() -> None: class PydanticModel(pydantic.BaseModel): ... -def test_response_parse_mismatched_basemodel(client: ArcadeAI) -> None: +def test_response_parse_mismatched_basemodel(client: Arcade) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo"), client=client, @@ -74,7 +74,7 @@ def test_response_parse_mismatched_basemodel(client: ArcadeAI) -> None: @pytest.mark.asyncio -async def test_async_response_parse_mismatched_basemodel(async_client: AsyncArcadeAI) -> None: +async def test_async_response_parse_mismatched_basemodel(async_client: AsyncArcade) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo"), client=async_client, @@ -91,7 +91,7 @@ async def test_async_response_parse_mismatched_basemodel(async_client: AsyncArca await response.parse(to=PydanticModel) -def test_response_parse_custom_stream(client: ArcadeAI) -> None: +def test_response_parse_custom_stream(client: Arcade) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo"), client=client, @@ -106,7 +106,7 @@ def test_response_parse_custom_stream(client: ArcadeAI) -> None: @pytest.mark.asyncio -async def test_async_response_parse_custom_stream(async_client: AsyncArcadeAI) -> None: +async def test_async_response_parse_custom_stream(async_client: AsyncArcade) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo"), client=async_client, @@ -125,7 +125,7 @@ class CustomModel(BaseModel): bar: int -def test_response_parse_custom_model(client: ArcadeAI) -> None: +def test_response_parse_custom_model(client: Arcade) -> None: response = APIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, @@ -141,7 +141,7 @@ def test_response_parse_custom_model(client: ArcadeAI) -> None: @pytest.mark.asyncio -async def test_async_response_parse_custom_model(async_client: AsyncArcadeAI) -> None: +async def test_async_response_parse_custom_model(async_client: AsyncArcade) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=async_client, @@ -156,7 +156,7 @@ async def test_async_response_parse_custom_model(async_client: AsyncArcadeAI) -> assert obj.bar == 2 -def test_response_parse_annotated_type(client: ArcadeAI) -> None: +def test_response_parse_annotated_type(client: Arcade) -> None: response = APIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=client, @@ -173,7 +173,7 @@ def test_response_parse_annotated_type(client: ArcadeAI) -> None: assert obj.bar == 2 -async def test_async_response_parse_annotated_type(async_client: AsyncArcadeAI) -> None: +async def test_async_response_parse_annotated_type(async_client: AsyncArcade) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), client=async_client, @@ -201,7 +201,7 @@ async def test_async_response_parse_annotated_type(async_client: AsyncArcadeAI) ("FalSe", False), ], ) -def test_response_parse_bool(client: ArcadeAI, content: str, expected: bool) -> None: +def test_response_parse_bool(client: Arcade, content: str, expected: bool) -> None: response = APIResponse( raw=httpx.Response(200, content=content), client=client, @@ -226,7 +226,7 @@ def test_response_parse_bool(client: ArcadeAI, content: str, expected: bool) -> ("FalSe", False), ], ) -async def test_async_response_parse_bool(client: AsyncArcadeAI, content: str, expected: bool) -> None: +async def test_async_response_parse_bool(client: AsyncArcade, content: str, expected: bool) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=content), client=client, @@ -245,7 +245,7 @@ class OtherModel(BaseModel): @pytest.mark.parametrize("client", [False], indirect=True) # loose validation -def test_response_parse_expect_model_union_non_json_content(client: ArcadeAI) -> None: +def test_response_parse_expect_model_union_non_json_content(client: Arcade) -> None: response = APIResponse( raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), client=client, @@ -262,7 +262,7 @@ def test_response_parse_expect_model_union_non_json_content(client: ArcadeAI) -> @pytest.mark.asyncio @pytest.mark.parametrize("async_client", [False], indirect=True) # loose validation -async def test_async_response_parse_expect_model_union_non_json_content(async_client: AsyncArcadeAI) -> None: +async def test_async_response_parse_expect_model_union_non_json_content(async_client: AsyncArcade) -> None: response = AsyncAPIResponse( raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), client=async_client, diff --git a/tests/test_streaming.py b/tests/test_streaming.py index 17da4ab0..65985b2c 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -5,13 +5,13 @@ import httpx import pytest -from arcadepy import ArcadeAI, AsyncArcadeAI +from arcadepy import Arcade, AsyncArcade from arcadepy._streaming import Stream, AsyncStream, ServerSentEvent @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_basic(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_basic(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: completion\n" yield b'data: {"foo":true}\n' @@ -28,7 +28,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_missing_event(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_data_missing_event(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b'data: {"foo":true}\n' yield b"\n" @@ -44,7 +44,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_event_missing_data(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_event_missing_data(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -60,7 +60,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_multiple_events(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"\n" @@ -82,7 +82,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events_with_data(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_multiple_events_with_data(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo":true}\n' @@ -106,7 +106,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines_with_empty_line(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_multiple_data_lines_with_empty_line(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" @@ -128,7 +128,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_json_escaped_double_new_line(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_data_json_escaped_double_new_line(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b'data: {"foo": "my long\\n\\ncontent"}' @@ -145,7 +145,7 @@ def body() -> Iterator[bytes]: @pytest.mark.asyncio @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines(sync: bool, client: ArcadeAI, async_client: AsyncArcadeAI) -> None: +async def test_multiple_data_lines(sync: bool, client: Arcade, async_client: AsyncArcade) -> None: def body() -> Iterator[bytes]: yield b"event: ping\n" yield b"data: {\n" @@ -165,8 +165,8 @@ def body() -> Iterator[bytes]: @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_special_new_line_character( sync: bool, - client: ArcadeAI, - async_client: AsyncArcadeAI, + client: Arcade, + async_client: AsyncArcade, ) -> None: def body() -> Iterator[bytes]: yield b'data: {"content":" culpa"}\n' @@ -196,8 +196,8 @@ def body() -> Iterator[bytes]: @pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) async def test_multi_byte_character_multiple_chunks( sync: bool, - client: ArcadeAI, - async_client: AsyncArcadeAI, + client: Arcade, + async_client: AsyncArcade, ) -> None: def body() -> Iterator[bytes]: yield b'data: {"content":"' @@ -237,8 +237,8 @@ def make_event_iterator( content: Iterator[bytes], *, sync: bool, - client: ArcadeAI, - async_client: AsyncArcadeAI, + client: Arcade, + async_client: AsyncArcade, ) -> Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]: if sync: return Stream(cast_to=object, client=client, response=httpx.Response(200, content=content))._iter_events() From 744e3f3ec16f28155847fe0f195ef5b8e620859f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 02:45:44 +0000 Subject: [PATCH 2/4] feat(api): api update (#14) --- .stats.yml | 4 +- README.md | 26 +- api.md | 48 +- src/arcadepy/_client.py | 16 +- src/arcadepy/resources/__init__.py | 12 +- src/arcadepy/resources/auth.py | 24 +- src/arcadepy/resources/chat/__init__.py | 33 ++ src/arcadepy/resources/chat/chat.py | 102 ++++ src/arcadepy/resources/chat/completions.py | 310 ++++++++++++ src/arcadepy/resources/tools/__init__.py | 33 ++ src/arcadepy/resources/tools/definition.py | 194 ++++++++ src/arcadepy/resources/tools/tools.py | 442 ++++++++++++++++++ src/arcadepy/types/__init__.py | 19 +- src/arcadepy/types/auth_authorize_params.py | 8 +- src/arcadepy/types/auth_status_params.py | 5 +- src/arcadepy/types/chat/__init__.py | 5 + .../chat/completion_completions_params.py | 82 ++++ src/arcadepy/types/chat_response.py | 23 +- src/arcadepy/types/choice.py | 23 + src/arcadepy/types/inputs.py | 12 + src/arcadepy/types/output.py | 16 + src/arcadepy/types/parameter.py | 20 + src/arcadepy/types/requirements.py | 23 + src/arcadepy/types/response.py | 23 +- src/arcadepy/types/response_output.py | 28 ++ src/arcadepy/types/shared/__init__.py | 2 + .../types/shared/authorization_response.py | 10 +- src/arcadepy/types/shared/tool_definition.py | 25 + src/arcadepy/types/tool_authorize_params.py | 2 +- src/arcadepy/types/tool_execute_params.py | 11 +- src/arcadepy/types/tool_list_params.py | 12 + src/arcadepy/types/tool_list_response.py | 10 + src/arcadepy/types/toolkit_definition.py | 15 + src/arcadepy/types/tools/__init__.py | 5 + .../types/tools/definition_get_params.py | 17 + src/arcadepy/types/usage.py | 15 + src/arcadepy/types/value_schema.py | 15 + tests/api_resources/chat/__init__.py | 1 + tests/api_resources/chat/test_completions.py | 318 +++++++++++++ tests/api_resources/test_auth.py | 48 +- tests/api_resources/test_tools.py | 159 +++---- tests/api_resources/tools/__init__.py | 1 + tests/api_resources/tools/test_definition.py | 90 ++++ tests/test_client.py | 20 +- 44 files changed, 2084 insertions(+), 223 deletions(-) create mode 100644 src/arcadepy/resources/chat/__init__.py create mode 100644 src/arcadepy/resources/chat/chat.py create mode 100644 src/arcadepy/resources/chat/completions.py create mode 100644 src/arcadepy/resources/tools/__init__.py create mode 100644 src/arcadepy/resources/tools/definition.py create mode 100644 src/arcadepy/resources/tools/tools.py create mode 100644 src/arcadepy/types/chat/__init__.py create mode 100644 src/arcadepy/types/chat/completion_completions_params.py create mode 100644 src/arcadepy/types/choice.py create mode 100644 src/arcadepy/types/inputs.py create mode 100644 src/arcadepy/types/output.py create mode 100644 src/arcadepy/types/parameter.py create mode 100644 src/arcadepy/types/requirements.py create mode 100644 src/arcadepy/types/response_output.py create mode 100644 src/arcadepy/types/shared/tool_definition.py create mode 100644 src/arcadepy/types/tool_list_params.py create mode 100644 src/arcadepy/types/tool_list_response.py create mode 100644 src/arcadepy/types/toolkit_definition.py create mode 100644 src/arcadepy/types/tools/__init__.py create mode 100644 src/arcadepy/types/tools/definition_get_params.py create mode 100644 src/arcadepy/types/usage.py create mode 100644 src/arcadepy/types/value_schema.py create mode 100644 tests/api_resources/chat/__init__.py create mode 100644 tests/api_resources/chat/test_completions.py create mode 100644 tests/api_resources/tools/__init__.py create mode 100644 tests/api_resources/tools/test_definition.py diff --git a/.stats.yml b/.stats.yml index c9c0ed68..e786c4a6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/arcade-ai%2Farcade-engine-2f4d672c34ee530fb7290e2fb799d907aba7d9e47030659422f4e7760625be90.yml +configured_endpoints: 8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/arcade-ai%2Farcade-engine-e021712a6bf43d1333001852981dae4a2461da7e8285a732f8adfbeb7b6d77c4.yml diff --git a/README.md b/README.md index 7dfe008a..e886bf44 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ client = Arcade( api_key=os.environ.get("ARCADE_API_KEY"), ) -tool_response = client.tools.execute( - inputs="[object Object]", +response = client.tools.execute( tool_name="Google.ListEmails", + inputs='{"n_emails": 10}', tool_version="0.1.0", user_id="user@example.com", ) -print(tool_response.invocation_id) +print(response.invocation_id) ``` While you can provide an `api_key` keyword argument, @@ -65,13 +65,13 @@ client = AsyncArcade( async def main() -> None: - tool_response = await client.tools.execute( - inputs="[object Object]", + response = await client.tools.execute( tool_name="Google.ListEmails", + inputs='{"n_emails": 10}', tool_version="0.1.0", user_id="user@example.com", ) - print(tool_response.invocation_id) + print(response.invocation_id) asyncio.run(main()) @@ -104,7 +104,7 @@ from arcadepy import Arcade client = Arcade() try: - client.chat.completions( + client.chat.completions.completions( messages=[ { "role": "user", @@ -154,7 +154,7 @@ client = Arcade( ) # Or, configure per-request: -client.with_options(max_retries=5).chat.completions( +client.with_options(max_retries=5).chat.completions.completions( messages=[ { "role": "user", @@ -184,7 +184,7 @@ client = Arcade( ) # Override per-request: -client.with_options(timeout=5.0).chat.completions( +client.with_options(timeout=5.0).chat.completions.completions( messages=[ { "role": "user", @@ -230,7 +230,7 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from arcadepy import Arcade client = Arcade() -response = client.chat.with_raw_response.completions( +response = client.chat.completions.with_raw_response.completions( messages=[{ "role": "user", "content": "Hello, how can I use Arcade AI?", @@ -238,8 +238,8 @@ response = client.chat.with_raw_response.completions( ) print(response.headers.get('X-My-Header')) -chat = response.parse() # get the object that `chat.completions()` would have returned -print(chat.id) +completion = response.parse() # get the object that `chat.completions.completions()` would have returned +print(completion.id) ``` These methods return an [`APIResponse`](https://github.com/ArcadeAI/arcade-py/tree/main/src/arcadepy/_response.py) object. @@ -253,7 +253,7 @@ The above interface eagerly reads the full response body when you make the reque To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. ```python -with client.chat.with_streaming_response.completions( +with client.chat.completions.with_streaming_response.completions( messages=[ { "role": "user", diff --git a/api.md b/api.md index 35d431bc..795764d6 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,7 @@ # Shared Types ```python -from arcadepy.types import Error +from arcadepy.types import AuthorizationResponse, Error, ToolDefinition ``` # Auth @@ -9,48 +9,68 @@ from arcadepy.types import Error Types: ```python -from arcadepy.types import AuthorizationResponse +from arcadepy.types import AuthRequest ``` Methods: -- client.auth.authorize(\*\*params) -> AuthorizationResponse -- client.auth.status(\*\*params) -> AuthorizationResponse +- client.auth.authorize(\*\*params) -> AuthorizationResponse +- client.auth.status(\*\*params) -> AuthorizationResponse -# Chat +# Health Types: ```python -from arcadepy.types import ChatMessage, ChatRequest, ChatResponse +from arcadepy.types import HealthSchema ``` Methods: -- client.chat.completions(\*\*params) -> ChatResponse +- client.health.check() -> HealthSchema -# Health +# Chat Types: ```python -from arcadepy.types import HealthSchema +from arcadepy.types import ChatMessage, ChatRequest, ChatResponse, Choice, Usage ``` +## Completions + Methods: -- client.health.check() -> HealthSchema +- client.chat.completions.completions(\*\*params) -> ChatResponse # Tools Types: ```python -from arcadepy.types import AuthorizeToolRequest, ExecuteToolRequest, ToolDefinition, ToolResponse +from arcadepy.types import ( + AuthorizeToolRequest, + ExecuteToolRequest, + Inputs, + Output, + Parameter, + Requirements, + Response, + ResponseOutput, + ToolkitDefinition, + ValueSchema, + ToolListResponse, +) ``` Methods: -- client.tools.authorize(\*\*params) -> AuthorizationResponse -- client.tools.execute(\*\*params) -> ToolResponse -- client.tools.retrieve_definition(\*\*params) -> ToolDefinition +- client.tools.list(\*\*params) -> ToolListResponse +- client.tools.authorize(\*\*params) -> AuthorizationResponse +- client.tools.execute(\*\*params) -> Response + +## Definition + +Methods: + +- client.tools.definition.get(\*\*params) -> ToolDefinition diff --git a/src/arcadepy/_client.py b/src/arcadepy/_client.py index 2cf4cb44..519a3ab5 100644 --- a/src/arcadepy/_client.py +++ b/src/arcadepy/_client.py @@ -47,8 +47,8 @@ class Arcade(SyncAPIClient): auth: resources.AuthResource - chat: resources.ChatResource health: resources.HealthResource + chat: resources.ChatResource tools: resources.ToolsResource with_raw_response: ArcadeWithRawResponse with_streaming_response: ArcadeWithStreamedResponse @@ -110,8 +110,8 @@ def __init__( self._idempotency_header = "Idempotency-Key" self.auth = resources.AuthResource(self) - self.chat = resources.ChatResource(self) self.health = resources.HealthResource(self) + self.chat = resources.ChatResource(self) self.tools = resources.ToolsResource(self) self.with_raw_response = ArcadeWithRawResponse(self) self.with_streaming_response = ArcadeWithStreamedResponse(self) @@ -223,8 +223,8 @@ def _make_status_error( class AsyncArcade(AsyncAPIClient): auth: resources.AsyncAuthResource - chat: resources.AsyncChatResource health: resources.AsyncHealthResource + chat: resources.AsyncChatResource tools: resources.AsyncToolsResource with_raw_response: AsyncArcadeWithRawResponse with_streaming_response: AsyncArcadeWithStreamedResponse @@ -286,8 +286,8 @@ def __init__( self._idempotency_header = "Idempotency-Key" self.auth = resources.AsyncAuthResource(self) - self.chat = resources.AsyncChatResource(self) self.health = resources.AsyncHealthResource(self) + self.chat = resources.AsyncChatResource(self) self.tools = resources.AsyncToolsResource(self) self.with_raw_response = AsyncArcadeWithRawResponse(self) self.with_streaming_response = AsyncArcadeWithStreamedResponse(self) @@ -400,32 +400,32 @@ def _make_status_error( class ArcadeWithRawResponse: def __init__(self, client: Arcade) -> None: self.auth = resources.AuthResourceWithRawResponse(client.auth) - self.chat = resources.ChatResourceWithRawResponse(client.chat) self.health = resources.HealthResourceWithRawResponse(client.health) + self.chat = resources.ChatResourceWithRawResponse(client.chat) self.tools = resources.ToolsResourceWithRawResponse(client.tools) class AsyncArcadeWithRawResponse: def __init__(self, client: AsyncArcade) -> None: self.auth = resources.AsyncAuthResourceWithRawResponse(client.auth) - self.chat = resources.AsyncChatResourceWithRawResponse(client.chat) self.health = resources.AsyncHealthResourceWithRawResponse(client.health) + self.chat = resources.AsyncChatResourceWithRawResponse(client.chat) self.tools = resources.AsyncToolsResourceWithRawResponse(client.tools) class ArcadeWithStreamedResponse: def __init__(self, client: Arcade) -> None: self.auth = resources.AuthResourceWithStreamingResponse(client.auth) - self.chat = resources.ChatResourceWithStreamingResponse(client.chat) self.health = resources.HealthResourceWithStreamingResponse(client.health) + self.chat = resources.ChatResourceWithStreamingResponse(client.chat) self.tools = resources.ToolsResourceWithStreamingResponse(client.tools) class AsyncArcadeWithStreamedResponse: def __init__(self, client: AsyncArcade) -> None: self.auth = resources.AsyncAuthResourceWithStreamingResponse(client.auth) - self.chat = resources.AsyncChatResourceWithStreamingResponse(client.chat) self.health = resources.AsyncHealthResourceWithStreamingResponse(client.health) + self.chat = resources.AsyncChatResourceWithStreamingResponse(client.chat) self.tools = resources.AsyncToolsResourceWithStreamingResponse(client.tools) diff --git a/src/arcadepy/resources/__init__.py b/src/arcadepy/resources/__init__.py index 7ac7a1ae..648d6b2e 100644 --- a/src/arcadepy/resources/__init__.py +++ b/src/arcadepy/resources/__init__.py @@ -40,18 +40,18 @@ "AsyncAuthResourceWithRawResponse", "AuthResourceWithStreamingResponse", "AsyncAuthResourceWithStreamingResponse", - "ChatResource", - "AsyncChatResource", - "ChatResourceWithRawResponse", - "AsyncChatResourceWithRawResponse", - "ChatResourceWithStreamingResponse", - "AsyncChatResourceWithStreamingResponse", "HealthResource", "AsyncHealthResource", "HealthResourceWithRawResponse", "AsyncHealthResourceWithRawResponse", "HealthResourceWithStreamingResponse", "AsyncHealthResourceWithStreamingResponse", + "ChatResource", + "AsyncChatResource", + "ChatResourceWithRawResponse", + "AsyncChatResourceWithRawResponse", + "ChatResourceWithStreamingResponse", + "AsyncChatResourceWithStreamingResponse", "ToolsResource", "AsyncToolsResource", "ToolsResourceWithRawResponse", diff --git a/src/arcadepy/resources/auth.py b/src/arcadepy/resources/auth.py index 920786cc..467eb94c 100644 --- a/src/arcadepy/resources/auth.py +++ b/src/arcadepy/resources/auth.py @@ -19,7 +19,7 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options -from ..types.authorization_response import AuthorizationResponse +from ..types.shared.authorization_response import AuthorizationResponse __all__ = ["AuthResource", "AsyncAuthResource"] @@ -95,6 +95,7 @@ def status( *, authorization_id: str, scopes: str | NotGiven = NOT_GIVEN, + wait: int | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -102,14 +103,19 @@ def status( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AuthorizationResponse: - """ - Checks the status of an ongoing authorization process for a specific tool + """Checks the status of an ongoing authorization process for a specific tool. + + If + 'wait' param is present, does not respond until either the auth status becomes + completed or the timeout is reached. Args: authorization_id: Authorization ID scopes: Scopes + wait: Timeout in seconds (max 60) + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -129,6 +135,7 @@ def status( { "authorization_id": authorization_id, "scopes": scopes, + "wait": wait, }, auth_status_params.AuthStatusParams, ), @@ -208,6 +215,7 @@ async def status( *, authorization_id: str, scopes: str | NotGiven = NOT_GIVEN, + wait: int | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -215,14 +223,19 @@ async def status( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AuthorizationResponse: - """ - Checks the status of an ongoing authorization process for a specific tool + """Checks the status of an ongoing authorization process for a specific tool. + + If + 'wait' param is present, does not respond until either the auth status becomes + completed or the timeout is reached. Args: authorization_id: Authorization ID scopes: Scopes + wait: Timeout in seconds (max 60) + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -242,6 +255,7 @@ async def status( { "authorization_id": authorization_id, "scopes": scopes, + "wait": wait, }, auth_status_params.AuthStatusParams, ), diff --git a/src/arcadepy/resources/chat/__init__.py b/src/arcadepy/resources/chat/__init__.py new file mode 100644 index 00000000..ec960eb4 --- /dev/null +++ b/src/arcadepy/resources/chat/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .chat import ( + ChatResource, + AsyncChatResource, + ChatResourceWithRawResponse, + AsyncChatResourceWithRawResponse, + ChatResourceWithStreamingResponse, + AsyncChatResourceWithStreamingResponse, +) +from .completions import ( + CompletionsResource, + AsyncCompletionsResource, + CompletionsResourceWithRawResponse, + AsyncCompletionsResourceWithRawResponse, + CompletionsResourceWithStreamingResponse, + AsyncCompletionsResourceWithStreamingResponse, +) + +__all__ = [ + "CompletionsResource", + "AsyncCompletionsResource", + "CompletionsResourceWithRawResponse", + "AsyncCompletionsResourceWithRawResponse", + "CompletionsResourceWithStreamingResponse", + "AsyncCompletionsResourceWithStreamingResponse", + "ChatResource", + "AsyncChatResource", + "ChatResourceWithRawResponse", + "AsyncChatResourceWithRawResponse", + "ChatResourceWithStreamingResponse", + "AsyncChatResourceWithStreamingResponse", +] diff --git a/src/arcadepy/resources/chat/chat.py b/src/arcadepy/resources/chat/chat.py new file mode 100644 index 00000000..a3857eec --- /dev/null +++ b/src/arcadepy/resources/chat/chat.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from .completions import ( + CompletionsResource, + AsyncCompletionsResource, + CompletionsResourceWithRawResponse, + AsyncCompletionsResourceWithRawResponse, + CompletionsResourceWithStreamingResponse, + AsyncCompletionsResourceWithStreamingResponse, +) + +__all__ = ["ChatResource", "AsyncChatResource"] + + +class ChatResource(SyncAPIResource): + @cached_property + def completions(self) -> CompletionsResource: + return CompletionsResource(self._client) + + @cached_property + def with_raw_response(self) -> ChatResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return ChatResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ChatResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return ChatResourceWithStreamingResponse(self) + + +class AsyncChatResource(AsyncAPIResource): + @cached_property + def completions(self) -> AsyncCompletionsResource: + return AsyncCompletionsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncChatResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return AsyncChatResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return AsyncChatResourceWithStreamingResponse(self) + + +class ChatResourceWithRawResponse: + def __init__(self, chat: ChatResource) -> None: + self._chat = chat + + @cached_property + def completions(self) -> CompletionsResourceWithRawResponse: + return CompletionsResourceWithRawResponse(self._chat.completions) + + +class AsyncChatResourceWithRawResponse: + def __init__(self, chat: AsyncChatResource) -> None: + self._chat = chat + + @cached_property + def completions(self) -> AsyncCompletionsResourceWithRawResponse: + return AsyncCompletionsResourceWithRawResponse(self._chat.completions) + + +class ChatResourceWithStreamingResponse: + def __init__(self, chat: ChatResource) -> None: + self._chat = chat + + @cached_property + def completions(self) -> CompletionsResourceWithStreamingResponse: + return CompletionsResourceWithStreamingResponse(self._chat.completions) + + +class AsyncChatResourceWithStreamingResponse: + def __init__(self, chat: AsyncChatResource) -> None: + self._chat = chat + + @cached_property + def completions(self) -> AsyncCompletionsResourceWithStreamingResponse: + return AsyncCompletionsResourceWithStreamingResponse(self._chat.completions) diff --git a/src/arcadepy/resources/chat/completions.py b/src/arcadepy/resources/chat/completions.py new file mode 100644 index 00000000..bacfb6e7 --- /dev/null +++ b/src/arcadepy/resources/chat/completions.py @@ -0,0 +1,310 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Iterable +from typing_extensions import Literal + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.chat import completion_completions_params +from ..._base_client import make_request_options +from ...types.chat_response import ChatResponse +from ...types.chat_message_param import ChatMessageParam + +__all__ = ["CompletionsResource", "AsyncCompletionsResource"] + + +class CompletionsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CompletionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return CompletionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CompletionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return CompletionsResourceWithStreamingResponse(self) + + def completions( + self, + *, + frequency_penalty: int | NotGiven = NOT_GIVEN, + logit_bias: Dict[str, int] | NotGiven = NOT_GIVEN, + logprobs: bool | NotGiven = NOT_GIVEN, + max_tokens: int | NotGiven = NOT_GIVEN, + messages: Iterable[ChatMessageParam] | NotGiven = NOT_GIVEN, + model: str | NotGiven = NOT_GIVEN, + n: int | NotGiven = NOT_GIVEN, + parallel_tool_calls: object | NotGiven = NOT_GIVEN, + presence_penalty: int | NotGiven = NOT_GIVEN, + response_format: Literal["json_object", "text"] | NotGiven = NOT_GIVEN, + seed: int | NotGiven = NOT_GIVEN, + stop: List[str] | NotGiven = NOT_GIVEN, + stream: bool | NotGiven = NOT_GIVEN, + stream_options: completion_completions_params.StreamOptions | NotGiven = NOT_GIVEN, + temperature: float | NotGiven = NOT_GIVEN, + tool_choice: object | NotGiven = NOT_GIVEN, + tools: object | NotGiven = NOT_GIVEN, + top_logprobs: int | NotGiven = NOT_GIVEN, + top_p: float | NotGiven = NOT_GIVEN, + user: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> ChatResponse: + """ + Talk to different LLM Chat APIs via OpenAI's API + + Args: + logit_bias: LogitBias is must be a token id string (specified by their token ID in the + tokenizer), not a word string. incorrect: `"logit_bias":{"You": 6}`, correct: + `"logit_bias":{"1639": 6}` refs: + https://platform.openai.com/docs/api-reference/chat/create#chat/create-logit_bias + + logprobs: LogProbs indicates whether to return log probabilities of the output tokens or + not. If true, returns the log probabilities of each output token returned in the + content of message. This option is currently not available on the + gpt-4-vision-preview model. + + parallel_tool_calls: Disable the default behavior of parallel tool calls by setting it: false. + + stream_options: Options for streaming response. Only set this when you set stream: true. + + tool_choice: This can be either a string or an ToolChoice object. + + top_logprobs: TopLogProbs is an integer between 0 and 5 specifying the number of most likely + tokens to return at each token position, each with an associated log + probability. logprobs must be set to true if this parameter is used. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/v1/chat/completions", + body=maybe_transform( + { + "frequency_penalty": frequency_penalty, + "logit_bias": logit_bias, + "logprobs": logprobs, + "max_tokens": max_tokens, + "messages": messages, + "model": model, + "n": n, + "parallel_tool_calls": parallel_tool_calls, + "presence_penalty": presence_penalty, + "response_format": response_format, + "seed": seed, + "stop": stop, + "stream": stream, + "stream_options": stream_options, + "temperature": temperature, + "tool_choice": tool_choice, + "tools": tools, + "top_logprobs": top_logprobs, + "top_p": top_p, + "user": user, + }, + completion_completions_params.CompletionCompletionsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ChatResponse, + ) + + +class AsyncCompletionsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCompletionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return AsyncCompletionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCompletionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return AsyncCompletionsResourceWithStreamingResponse(self) + + async def completions( + self, + *, + frequency_penalty: int | NotGiven = NOT_GIVEN, + logit_bias: Dict[str, int] | NotGiven = NOT_GIVEN, + logprobs: bool | NotGiven = NOT_GIVEN, + max_tokens: int | NotGiven = NOT_GIVEN, + messages: Iterable[ChatMessageParam] | NotGiven = NOT_GIVEN, + model: str | NotGiven = NOT_GIVEN, + n: int | NotGiven = NOT_GIVEN, + parallel_tool_calls: object | NotGiven = NOT_GIVEN, + presence_penalty: int | NotGiven = NOT_GIVEN, + response_format: Literal["json_object", "text"] | NotGiven = NOT_GIVEN, + seed: int | NotGiven = NOT_GIVEN, + stop: List[str] | NotGiven = NOT_GIVEN, + stream: bool | NotGiven = NOT_GIVEN, + stream_options: completion_completions_params.StreamOptions | NotGiven = NOT_GIVEN, + temperature: float | NotGiven = NOT_GIVEN, + tool_choice: object | NotGiven = NOT_GIVEN, + tools: object | NotGiven = NOT_GIVEN, + top_logprobs: int | NotGiven = NOT_GIVEN, + top_p: float | NotGiven = NOT_GIVEN, + user: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> ChatResponse: + """ + Talk to different LLM Chat APIs via OpenAI's API + + Args: + logit_bias: LogitBias is must be a token id string (specified by their token ID in the + tokenizer), not a word string. incorrect: `"logit_bias":{"You": 6}`, correct: + `"logit_bias":{"1639": 6}` refs: + https://platform.openai.com/docs/api-reference/chat/create#chat/create-logit_bias + + logprobs: LogProbs indicates whether to return log probabilities of the output tokens or + not. If true, returns the log probabilities of each output token returned in the + content of message. This option is currently not available on the + gpt-4-vision-preview model. + + parallel_tool_calls: Disable the default behavior of parallel tool calls by setting it: false. + + stream_options: Options for streaming response. Only set this when you set stream: true. + + tool_choice: This can be either a string or an ToolChoice object. + + top_logprobs: TopLogProbs is an integer between 0 and 5 specifying the number of most likely + tokens to return at each token position, each with an associated log + probability. logprobs must be set to true if this parameter is used. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/v1/chat/completions", + body=await async_maybe_transform( + { + "frequency_penalty": frequency_penalty, + "logit_bias": logit_bias, + "logprobs": logprobs, + "max_tokens": max_tokens, + "messages": messages, + "model": model, + "n": n, + "parallel_tool_calls": parallel_tool_calls, + "presence_penalty": presence_penalty, + "response_format": response_format, + "seed": seed, + "stop": stop, + "stream": stream, + "stream_options": stream_options, + "temperature": temperature, + "tool_choice": tool_choice, + "tools": tools, + "top_logprobs": top_logprobs, + "top_p": top_p, + "user": user, + }, + completion_completions_params.CompletionCompletionsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ChatResponse, + ) + + +class CompletionsResourceWithRawResponse: + def __init__(self, completions: CompletionsResource) -> None: + self._completions = completions + + self.completions = to_raw_response_wrapper( + completions.completions, + ) + + +class AsyncCompletionsResourceWithRawResponse: + def __init__(self, completions: AsyncCompletionsResource) -> None: + self._completions = completions + + self.completions = async_to_raw_response_wrapper( + completions.completions, + ) + + +class CompletionsResourceWithStreamingResponse: + def __init__(self, completions: CompletionsResource) -> None: + self._completions = completions + + self.completions = to_streamed_response_wrapper( + completions.completions, + ) + + +class AsyncCompletionsResourceWithStreamingResponse: + def __init__(self, completions: AsyncCompletionsResource) -> None: + self._completions = completions + + self.completions = async_to_streamed_response_wrapper( + completions.completions, + ) diff --git a/src/arcadepy/resources/tools/__init__.py b/src/arcadepy/resources/tools/__init__.py new file mode 100644 index 00000000..f71184cc --- /dev/null +++ b/src/arcadepy/resources/tools/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .tools import ( + ToolsResource, + AsyncToolsResource, + ToolsResourceWithRawResponse, + AsyncToolsResourceWithRawResponse, + ToolsResourceWithStreamingResponse, + AsyncToolsResourceWithStreamingResponse, +) +from .definition import ( + DefinitionResource, + AsyncDefinitionResource, + DefinitionResourceWithRawResponse, + AsyncDefinitionResourceWithRawResponse, + DefinitionResourceWithStreamingResponse, + AsyncDefinitionResourceWithStreamingResponse, +) + +__all__ = [ + "DefinitionResource", + "AsyncDefinitionResource", + "DefinitionResourceWithRawResponse", + "AsyncDefinitionResourceWithRawResponse", + "DefinitionResourceWithStreamingResponse", + "AsyncDefinitionResourceWithStreamingResponse", + "ToolsResource", + "AsyncToolsResource", + "ToolsResourceWithRawResponse", + "AsyncToolsResourceWithRawResponse", + "ToolsResourceWithStreamingResponse", + "AsyncToolsResourceWithStreamingResponse", +] diff --git a/src/arcadepy/resources/tools/definition.py b/src/arcadepy/resources/tools/definition.py new file mode 100644 index 00000000..c7d06de0 --- /dev/null +++ b/src/arcadepy/resources/tools/definition.py @@ -0,0 +1,194 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.tools import definition_get_params +from ..._base_client import make_request_options +from ...types.shared.tool_definition import ToolDefinition + +__all__ = ["DefinitionResource", "AsyncDefinitionResource"] + + +class DefinitionResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> DefinitionResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return DefinitionResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DefinitionResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return DefinitionResourceWithStreamingResponse(self) + + def get( + self, + *, + director_id: str, + tool_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ToolDefinition: + """ + Returns the arcade tool specification for a specific tool + + Args: + director_id: Director ID + + tool_id: Tool ID + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/tools/definition", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "director_id": director_id, + "tool_id": tool_id, + }, + definition_get_params.DefinitionGetParams, + ), + ), + cast_to=ToolDefinition, + ) + + +class AsyncDefinitionResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncDefinitionResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return AsyncDefinitionResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDefinitionResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return AsyncDefinitionResourceWithStreamingResponse(self) + + async def get( + self, + *, + director_id: str, + tool_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ToolDefinition: + """ + Returns the arcade tool specification for a specific tool + + Args: + director_id: Director ID + + tool_id: Tool ID + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/tools/definition", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "director_id": director_id, + "tool_id": tool_id, + }, + definition_get_params.DefinitionGetParams, + ), + ), + cast_to=ToolDefinition, + ) + + +class DefinitionResourceWithRawResponse: + def __init__(self, definition: DefinitionResource) -> None: + self._definition = definition + + self.get = to_raw_response_wrapper( + definition.get, + ) + + +class AsyncDefinitionResourceWithRawResponse: + def __init__(self, definition: AsyncDefinitionResource) -> None: + self._definition = definition + + self.get = async_to_raw_response_wrapper( + definition.get, + ) + + +class DefinitionResourceWithStreamingResponse: + def __init__(self, definition: DefinitionResource) -> None: + self._definition = definition + + self.get = to_streamed_response_wrapper( + definition.get, + ) + + +class AsyncDefinitionResourceWithStreamingResponse: + def __init__(self, definition: AsyncDefinitionResource) -> None: + self._definition = definition + + self.get = async_to_streamed_response_wrapper( + definition.get, + ) diff --git a/src/arcadepy/resources/tools/tools.py b/src/arcadepy/resources/tools/tools.py new file mode 100644 index 00000000..ebfdb3da --- /dev/null +++ b/src/arcadepy/resources/tools/tools.py @@ -0,0 +1,442 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ...types import tool_list_params, tool_execute_params, tool_authorize_params +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from .definition import ( + DefinitionResource, + AsyncDefinitionResource, + DefinitionResourceWithRawResponse, + AsyncDefinitionResourceWithRawResponse, + DefinitionResourceWithStreamingResponse, + AsyncDefinitionResourceWithStreamingResponse, +) +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.response import Response +from ...types.tool_list_response import ToolListResponse +from ...types.shared.authorization_response import AuthorizationResponse + +__all__ = ["ToolsResource", "AsyncToolsResource"] + + +class ToolsResource(SyncAPIResource): + @cached_property + def definition(self) -> DefinitionResource: + return DefinitionResource(self._client) + + @cached_property + def with_raw_response(self) -> ToolsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return ToolsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ToolsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return ToolsResourceWithStreamingResponse(self) + + def list( + self, + *, + toolkit: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ToolListResponse: + """ + Returns a list of tools, optionally filtered by toolkit or auth provider + + Args: + toolkit: Toolkit Name + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/tools/list", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"toolkit": toolkit}, tool_list_params.ToolListParams), + ), + cast_to=ToolListResponse, + ) + + def authorize( + self, + *, + tool_name: str, + user_id: str, + tool_version: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> AuthorizationResponse: + """ + Authorizes a user for a specific tool by name + + Args: + tool_version: Optional: if not provided, any version is used + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/v1/tools/authorize", + body=maybe_transform( + { + "tool_name": tool_name, + "user_id": user_id, + "tool_version": tool_version, + }, + tool_authorize_params.ToolAuthorizeParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=AuthorizationResponse, + ) + + def execute( + self, + *, + tool_name: str, + inputs: str | NotGiven = NOT_GIVEN, + tool_version: str | NotGiven = NOT_GIVEN, + user_id: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> Response: + """ + Executes a tool by name and arguments + + Args: + inputs: Serialized JSON string + + tool_version: Optional: if not provided, any version is used + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return self._post( + "/v1/tools/execute", + body=maybe_transform( + { + "tool_name": tool_name, + "inputs": inputs, + "tool_version": tool_version, + "user_id": user_id, + }, + tool_execute_params.ToolExecuteParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Response, + ) + + +class AsyncToolsResource(AsyncAPIResource): + @cached_property + def definition(self) -> AsyncDefinitionResource: + return AsyncDefinitionResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncToolsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#accessing-raw-response-data-eg-headers + """ + return AsyncToolsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncToolsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/ArcadeAI/arcade-py#with_streaming_response + """ + return AsyncToolsResourceWithStreamingResponse(self) + + async def list( + self, + *, + toolkit: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ToolListResponse: + """ + Returns a list of tools, optionally filtered by toolkit or auth provider + + Args: + toolkit: Toolkit Name + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/tools/list", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"toolkit": toolkit}, tool_list_params.ToolListParams), + ), + cast_to=ToolListResponse, + ) + + async def authorize( + self, + *, + tool_name: str, + user_id: str, + tool_version: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> AuthorizationResponse: + """ + Authorizes a user for a specific tool by name + + Args: + tool_version: Optional: if not provided, any version is used + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/v1/tools/authorize", + body=await async_maybe_transform( + { + "tool_name": tool_name, + "user_id": user_id, + "tool_version": tool_version, + }, + tool_authorize_params.ToolAuthorizeParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=AuthorizationResponse, + ) + + async def execute( + self, + *, + tool_name: str, + inputs: str | NotGiven = NOT_GIVEN, + tool_version: str | NotGiven = NOT_GIVEN, + user_id: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + idempotency_key: str | None = None, + ) -> Response: + """ + Executes a tool by name and arguments + + Args: + inputs: Serialized JSON string + + tool_version: Optional: if not provided, any version is used + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + + idempotency_key: Specify a custom idempotency key for this request + """ + return await self._post( + "/v1/tools/execute", + body=await async_maybe_transform( + { + "tool_name": tool_name, + "inputs": inputs, + "tool_version": tool_version, + "user_id": user_id, + }, + tool_execute_params.ToolExecuteParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Response, + ) + + +class ToolsResourceWithRawResponse: + def __init__(self, tools: ToolsResource) -> None: + self._tools = tools + + self.list = to_raw_response_wrapper( + tools.list, + ) + self.authorize = to_raw_response_wrapper( + tools.authorize, + ) + self.execute = to_raw_response_wrapper( + tools.execute, + ) + + @cached_property + def definition(self) -> DefinitionResourceWithRawResponse: + return DefinitionResourceWithRawResponse(self._tools.definition) + + +class AsyncToolsResourceWithRawResponse: + def __init__(self, tools: AsyncToolsResource) -> None: + self._tools = tools + + self.list = async_to_raw_response_wrapper( + tools.list, + ) + self.authorize = async_to_raw_response_wrapper( + tools.authorize, + ) + self.execute = async_to_raw_response_wrapper( + tools.execute, + ) + + @cached_property + def definition(self) -> AsyncDefinitionResourceWithRawResponse: + return AsyncDefinitionResourceWithRawResponse(self._tools.definition) + + +class ToolsResourceWithStreamingResponse: + def __init__(self, tools: ToolsResource) -> None: + self._tools = tools + + self.list = to_streamed_response_wrapper( + tools.list, + ) + self.authorize = to_streamed_response_wrapper( + tools.authorize, + ) + self.execute = to_streamed_response_wrapper( + tools.execute, + ) + + @cached_property + def definition(self) -> DefinitionResourceWithStreamingResponse: + return DefinitionResourceWithStreamingResponse(self._tools.definition) + + +class AsyncToolsResourceWithStreamingResponse: + def __init__(self, tools: AsyncToolsResource) -> None: + self._tools = tools + + self.list = async_to_streamed_response_wrapper( + tools.list, + ) + self.authorize = async_to_streamed_response_wrapper( + tools.authorize, + ) + self.execute = async_to_streamed_response_wrapper( + tools.execute, + ) + + @cached_property + def definition(self) -> AsyncDefinitionResourceWithStreamingResponse: + return AsyncDefinitionResourceWithStreamingResponse(self._tools.definition) diff --git a/src/arcadepy/types/__init__.py b/src/arcadepy/types/__init__.py index 3ba9dbf0..4da6d4b7 100644 --- a/src/arcadepy/types/__init__.py +++ b/src/arcadepy/types/__init__.py @@ -2,17 +2,24 @@ from __future__ import annotations -from .shared import Error as Error +from .usage import Usage as Usage +from .choice import Choice as Choice +from .inputs import Inputs as Inputs +from .output import Output as Output +from .shared import Error as Error, ToolDefinition as ToolDefinition, AuthorizationResponse as AuthorizationResponse +from .response import Response as Response +from .parameter import Parameter as Parameter from .chat_message import ChatMessage as ChatMessage +from .requirements import Requirements as Requirements +from .value_schema import ValueSchema as ValueSchema from .chat_response import ChatResponse as ChatResponse from .health_schema import HealthSchema as HealthSchema -from .tool_response import ToolResponse as ToolResponse -from .tool_definition import ToolDefinition as ToolDefinition +from .response_output import ResponseOutput as ResponseOutput +from .tool_list_params import ToolListParams as ToolListParams from .auth_status_params import AuthStatusParams as AuthStatusParams from .chat_message_param import ChatMessageParam as ChatMessageParam +from .tool_list_response import ToolListResponse as ToolListResponse +from .toolkit_definition import ToolkitDefinition as ToolkitDefinition from .tool_execute_params import ToolExecuteParams as ToolExecuteParams from .auth_authorize_params import AuthAuthorizeParams as AuthAuthorizeParams from .tool_authorize_params import ToolAuthorizeParams as ToolAuthorizeParams -from .authorization_response import AuthorizationResponse as AuthorizationResponse -from .chat_completions_params import ChatCompletionsParams as ChatCompletionsParams -from .tool_retrieve_definition_params import ToolRetrieveDefinitionParams as ToolRetrieveDefinitionParams diff --git a/src/arcadepy/types/auth_authorize_params.py b/src/arcadepy/types/auth_authorize_params.py index d8da3d82..24b6c5ac 100644 --- a/src/arcadepy/types/auth_authorize_params.py +++ b/src/arcadepy/types/auth_authorize_params.py @@ -15,12 +15,12 @@ class AuthAuthorizeParams(TypedDict, total=False): class AuthRequirementOauth2(TypedDict, total=False): - authority: str - scopes: List[str] class AuthRequirement(TypedDict, total=False): - provider: Required[str] - oauth2: AuthRequirementOauth2 + + provider_id: str + + provider_type: str diff --git a/src/arcadepy/types/auth_status_params.py b/src/arcadepy/types/auth_status_params.py index 6026fb39..8eadbfeb 100644 --- a/src/arcadepy/types/auth_status_params.py +++ b/src/arcadepy/types/auth_status_params.py @@ -10,8 +10,11 @@ class AuthStatusParams(TypedDict, total=False): - authorization_id: Required[Annotated[str, PropertyInfo(alias="authorizationID")]] + authorization_id: Required[Annotated[str, PropertyInfo(alias="authorizationId")]] """Authorization ID""" scopes: str """Scopes""" + + wait: int + """Timeout in seconds (max 60)""" diff --git a/src/arcadepy/types/chat/__init__.py b/src/arcadepy/types/chat/__init__.py new file mode 100644 index 00000000..44798218 --- /dev/null +++ b/src/arcadepy/types/chat/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .completion_completions_params import CompletionCompletionsParams as CompletionCompletionsParams diff --git a/src/arcadepy/types/chat/completion_completions_params.py b/src/arcadepy/types/chat/completion_completions_params.py new file mode 100644 index 00000000..a3407090 --- /dev/null +++ b/src/arcadepy/types/chat/completion_completions_params.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Iterable +from typing_extensions import Literal, TypedDict + +from ..chat_message_param import ChatMessageParam + +__all__ = ["CompletionCompletionsParams", "StreamOptions"] + + +class CompletionCompletionsParams(TypedDict, total=False): + frequency_penalty: int + + logit_bias: Dict[str, int] + """ + LogitBias is must be a token id string (specified by their token ID in the + tokenizer), not a word string. incorrect: `"logit_bias":{"You": 6}`, correct: + `"logit_bias":{"1639": 6}` refs: + https://platform.openai.com/docs/api-reference/chat/create#chat/create-logit_bias + """ + + logprobs: bool + """ + LogProbs indicates whether to return log probabilities of the output tokens or + not. If true, returns the log probabilities of each output token returned in the + content of message. This option is currently not available on the + gpt-4-vision-preview model. + """ + + max_tokens: int + + messages: Iterable[ChatMessageParam] + + model: str + + n: int + + parallel_tool_calls: object + """Disable the default behavior of parallel tool calls by setting it: false.""" + + presence_penalty: int + + response_format: Literal["json_object", "text"] + + seed: int + + stop: List[str] + + stream: bool + + stream_options: StreamOptions + """Options for streaming response. Only set this when you set stream: true.""" + + temperature: float + + tool_choice: object + """This can be either a string or an ToolChoice object.""" + + tools: object + + top_logprobs: int + """ + TopLogProbs is an integer between 0 and 5 specifying the number of most likely + tokens to return at each token position, each with an associated log + probability. logprobs must be set to true if this parameter is used. + """ + + top_p: float + + user: str + + +class StreamOptions(TypedDict, total=False): + include_usage: bool + """ + If set, an additional chunk will be streamed before the data: [DONE] message. + The usage field on this chunk shows the token usage statistics for the entire + request, and the choices field will always be an empty array. All other chunks + will also include a usage field, but with a null value. + """ diff --git a/src/arcadepy/types/chat_response.py b/src/arcadepy/types/chat_response.py index 04ce655e..c3fefab2 100644 --- a/src/arcadepy/types/chat_response.py +++ b/src/arcadepy/types/chat_response.py @@ -2,28 +2,11 @@ from typing import List, Optional +from .usage import Usage +from .choice import Choice from .._models import BaseModel -from .chat_message import ChatMessage -__all__ = ["ChatResponse", "Choice", "Usage"] - - -class Choice(BaseModel): - finish_reason: Optional[str] = None - - index: Optional[int] = None - - logprobs: Optional[object] = None - - message: Optional[ChatMessage] = None - - -class Usage(BaseModel): - completion_tokens: Optional[int] = None - - prompt_tokens: Optional[int] = None - - total_tokens: Optional[int] = None +__all__ = ["ChatResponse"] class ChatResponse(BaseModel): diff --git a/src/arcadepy/types/choice.py b/src/arcadepy/types/choice.py new file mode 100644 index 00000000..578f1d96 --- /dev/null +++ b/src/arcadepy/types/choice.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .chat_message import ChatMessage +from .shared.authorization_response import AuthorizationResponse + +__all__ = ["Choice"] + + +class Choice(BaseModel): + finish_reason: Optional[str] = None + + index: Optional[int] = None + + logprobs: Optional[object] = None + + message: Optional[ChatMessage] = None + + tool_authorizations: Optional[List[AuthorizationResponse]] = None + + tool_messages: Optional[List[ChatMessage]] = None diff --git a/src/arcadepy/types/inputs.py b/src/arcadepy/types/inputs.py new file mode 100644 index 00000000..93f9b013 --- /dev/null +++ b/src/arcadepy/types/inputs.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .parameter import Parameter + +__all__ = ["Inputs"] + + +class Inputs(BaseModel): + parameters: Optional[List[Parameter]] = None diff --git a/src/arcadepy/types/output.py b/src/arcadepy/types/output.py new file mode 100644 index 00000000..e4817bff --- /dev/null +++ b/src/arcadepy/types/output.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .value_schema import ValueSchema + +__all__ = ["Output"] + + +class Output(BaseModel): + available_modes: Optional[List[str]] = None + + description: Optional[str] = None + + value_schema: Optional[ValueSchema] = None diff --git a/src/arcadepy/types/parameter.py b/src/arcadepy/types/parameter.py new file mode 100644 index 00000000..5e5c3c84 --- /dev/null +++ b/src/arcadepy/types/parameter.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel +from .value_schema import ValueSchema + +__all__ = ["Parameter"] + + +class Parameter(BaseModel): + name: str + + value_schema: ValueSchema + + description: Optional[str] = None + + inferrable: Optional[bool] = None + + required: Optional[bool] = None diff --git a/src/arcadepy/types/requirements.py b/src/arcadepy/types/requirements.py new file mode 100644 index 00000000..c792b7d3 --- /dev/null +++ b/src/arcadepy/types/requirements.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["Requirements", "Authorization", "AuthorizationOauth2"] + + +class AuthorizationOauth2(BaseModel): + scopes: Optional[List[str]] = None + + +class Authorization(BaseModel): + oauth2: Optional[AuthorizationOauth2] = None + + provider_id: Optional[str] = None + + provider_type: Optional[str] = None + + +class Requirements(BaseModel): + authorization: Optional[Authorization] = None diff --git a/src/arcadepy/types/response.py b/src/arcadepy/types/response.py index 7a4b089e..730a70ba 100644 --- a/src/arcadepy/types/response.py +++ b/src/arcadepy/types/response.py @@ -5,32 +5,15 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .response_output import ResponseOutput -__all__ = ["Response", "FinishedAt", "Output", "OutputError"] +__all__ = ["Response", "FinishedAt"] class FinishedAt(BaseModel): time_time: Optional[str] = FieldInfo(alias="time.Time", default=None) -class OutputError(BaseModel): - message: str - - additional_prompt_content: Optional[str] = None - - can_retry: Optional[bool] = None - - developer_message: Optional[str] = None - - retry_after_ms: Optional[int] = None - - -class Output(BaseModel): - value: object - - error: Optional[OutputError] = None - - class Response(BaseModel): invocation_id: str @@ -38,6 +21,6 @@ class Response(BaseModel): finished_at: Optional[FinishedAt] = None - output: Optional[Output] = None + output: Optional[ResponseOutput] = None success: Optional[bool] = None diff --git a/src/arcadepy/types/response_output.py b/src/arcadepy/types/response_output.py new file mode 100644 index 00000000..087b8087 --- /dev/null +++ b/src/arcadepy/types/response_output.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel +from .shared.authorization_response import AuthorizationResponse + +__all__ = ["ResponseOutput", "Error"] + + +class Error(BaseModel): + message: str + + additional_prompt_content: Optional[str] = None + + can_retry: Optional[bool] = None + + developer_message: Optional[str] = None + + retry_after_ms: Optional[int] = None + + +class ResponseOutput(BaseModel): + error: Optional[Error] = None + + requires_authorization: Optional[AuthorizationResponse] = None + + value: Optional[object] = None diff --git a/src/arcadepy/types/shared/__init__.py b/src/arcadepy/types/shared/__init__.py index 867de170..7737a0b8 100644 --- a/src/arcadepy/types/shared/__init__.py +++ b/src/arcadepy/types/shared/__init__.py @@ -1,3 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .error import Error as Error +from .tool_definition import ToolDefinition as ToolDefinition +from .authorization_response import AuthorizationResponse as AuthorizationResponse diff --git a/src/arcadepy/types/shared/authorization_response.py b/src/arcadepy/types/shared/authorization_response.py index 6ce92789..6d08e805 100644 --- a/src/arcadepy/types/shared/authorization_response.py +++ b/src/arcadepy/types/shared/authorization_response.py @@ -1,8 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional - -from pydantic import Field as FieldInfo +from typing import Dict, List, Optional from ..._models import BaseModel @@ -12,11 +10,13 @@ class Context(BaseModel): token: Optional[str] = None + user_info: Optional[Dict[str, object]] = None + class AuthorizationResponse(BaseModel): - authorization_id: Optional[str] = FieldInfo(alias="authorizationID", default=None) + authorization_id: Optional[str] = None - authorization_url: Optional[str] = FieldInfo(alias="authorizationURL", default=None) + authorization_url: Optional[str] = None context: Optional[Context] = None diff --git a/src/arcadepy/types/shared/tool_definition.py b/src/arcadepy/types/shared/tool_definition.py new file mode 100644 index 00000000..d1897a3b --- /dev/null +++ b/src/arcadepy/types/shared/tool_definition.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..inputs import Inputs +from ..output import Output +from ..._models import BaseModel +from ..requirements import Requirements +from ..toolkit_definition import ToolkitDefinition + +__all__ = ["ToolDefinition"] + + +class ToolDefinition(BaseModel): + inputs: Inputs + + name: str + + toolkit: ToolkitDefinition + + description: Optional[str] = None + + output: Optional[Output] = None + + requirements: Optional[Requirements] = None diff --git a/src/arcadepy/types/tool_authorize_params.py b/src/arcadepy/types/tool_authorize_params.py index 6675d73c..8454bfa1 100644 --- a/src/arcadepy/types/tool_authorize_params.py +++ b/src/arcadepy/types/tool_authorize_params.py @@ -13,4 +13,4 @@ class ToolAuthorizeParams(TypedDict, total=False): user_id: Required[str] tool_version: str - """Optional: if not provided, latest version is assumed""" + """Optional: if not provided, any version is used""" diff --git a/src/arcadepy/types/tool_execute_params.py b/src/arcadepy/types/tool_execute_params.py index 77826f67..2e8fa5bc 100644 --- a/src/arcadepy/types/tool_execute_params.py +++ b/src/arcadepy/types/tool_execute_params.py @@ -8,11 +8,12 @@ class ToolExecuteParams(TypedDict, total=False): - inputs: Required[str] - """Serialized JSON string""" - tool_name: Required[str] - tool_version: Required[str] + inputs: str + """Serialized JSON string""" + + tool_version: str + """Optional: if not provided, any version is used""" - user_id: Required[str] + user_id: str diff --git a/src/arcadepy/types/tool_list_params.py b/src/arcadepy/types/tool_list_params.py new file mode 100644 index 00000000..a623f325 --- /dev/null +++ b/src/arcadepy/types/tool_list_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ToolListParams"] + + +class ToolListParams(TypedDict, total=False): + toolkit: str + """Toolkit Name""" diff --git a/src/arcadepy/types/tool_list_response.py b/src/arcadepy/types/tool_list_response.py new file mode 100644 index 00000000..9bf3889a --- /dev/null +++ b/src/arcadepy/types/tool_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .shared.tool_definition import ToolDefinition + +__all__ = ["ToolListResponse"] + +ToolListResponse: TypeAlias = List[ToolDefinition] diff --git a/src/arcadepy/types/toolkit_definition.py b/src/arcadepy/types/toolkit_definition.py new file mode 100644 index 00000000..00ab2598 --- /dev/null +++ b/src/arcadepy/types/toolkit_definition.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["ToolkitDefinition"] + + +class ToolkitDefinition(BaseModel): + name: str + + description: Optional[str] = None + + version: Optional[str] = None diff --git a/src/arcadepy/types/tools/__init__.py b/src/arcadepy/types/tools/__init__.py new file mode 100644 index 00000000..774cfc1a --- /dev/null +++ b/src/arcadepy/types/tools/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .definition_get_params import DefinitionGetParams as DefinitionGetParams diff --git a/src/arcadepy/types/tools/definition_get_params.py b/src/arcadepy/types/tools/definition_get_params.py new file mode 100644 index 00000000..14bf163e --- /dev/null +++ b/src/arcadepy/types/tools/definition_get_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["DefinitionGetParams"] + + +class DefinitionGetParams(TypedDict, total=False): + director_id: Required[Annotated[str, PropertyInfo(alias="directorId")]] + """Director ID""" + + tool_id: Required[Annotated[str, PropertyInfo(alias="toolId")]] + """Tool ID""" diff --git a/src/arcadepy/types/usage.py b/src/arcadepy/types/usage.py new file mode 100644 index 00000000..402d410c --- /dev/null +++ b/src/arcadepy/types/usage.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["Usage"] + + +class Usage(BaseModel): + completion_tokens: Optional[int] = None + + prompt_tokens: Optional[int] = None + + total_tokens: Optional[int] = None diff --git a/src/arcadepy/types/value_schema.py b/src/arcadepy/types/value_schema.py new file mode 100644 index 00000000..76eaa838 --- /dev/null +++ b/src/arcadepy/types/value_schema.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["ValueSchema"] + + +class ValueSchema(BaseModel): + val_type: str + + enum: Optional[List[str]] = None + + inner_val_type: Optional[str] = None diff --git a/tests/api_resources/chat/__init__.py b/tests/api_resources/chat/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/chat/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/chat/test_completions.py b/tests/api_resources/chat/test_completions.py new file mode 100644 index 00000000..1dd2b00d --- /dev/null +++ b/tests/api_resources/chat/test_completions.py @@ -0,0 +1,318 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from arcadepy import Arcade, AsyncArcade +from tests.utils import assert_matches_type +from arcadepy.types import ChatResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCompletions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_completions(self, client: Arcade) -> None: + completion = client.chat.completions.completions() + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + def test_method_completions_with_all_params(self, client: Arcade) -> None: + completion = client.chat.completions.completions( + frequency_penalty=0, + logit_bias={"foo": 0}, + logprobs=True, + max_tokens=0, + messages=[ + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + ], + model="model", + n=0, + parallel_tool_calls={}, + presence_penalty=0, + response_format="json_object", + seed=0, + stop=["string", "string", "string"], + stream=True, + stream_options={"include_usage": True}, + temperature=0, + tool_choice={}, + tools={}, + top_logprobs=0, + top_p=0, + user="user", + ) + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + def test_raw_response_completions(self, client: Arcade) -> None: + response = client.chat.completions.with_raw_response.completions() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + completion = response.parse() + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + def test_streaming_response_completions(self, client: Arcade) -> None: + with client.chat.completions.with_streaming_response.completions() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + completion = response.parse() + assert_matches_type(ChatResponse, completion, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncCompletions: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_completions(self, async_client: AsyncArcade) -> None: + completion = await async_client.chat.completions.completions() + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + async def test_method_completions_with_all_params(self, async_client: AsyncArcade) -> None: + completion = await async_client.chat.completions.completions( + frequency_penalty=0, + logit_bias={"foo": 0}, + logprobs=True, + max_tokens=0, + messages=[ + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + { + "content": "content", + "role": "role", + "name": "name", + "tool_call_id": "tool_call_id", + "tool_calls": [ + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + { + "id": "id", + "function": { + "arguments": "arguments", + "name": "name", + }, + "type": "function", + }, + ], + }, + ], + model="model", + n=0, + parallel_tool_calls={}, + presence_penalty=0, + response_format="json_object", + seed=0, + stop=["string", "string", "string"], + stream=True, + stream_options={"include_usage": True}, + temperature=0, + tool_choice={}, + tools={}, + top_logprobs=0, + top_p=0, + user="user", + ) + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + async def test_raw_response_completions(self, async_client: AsyncArcade) -> None: + response = await async_client.chat.completions.with_raw_response.completions() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + completion = await response.parse() + assert_matches_type(ChatResponse, completion, path=["response"]) + + @parametrize + async def test_streaming_response_completions(self, async_client: AsyncArcade) -> None: + async with async_client.chat.completions.with_streaming_response.completions() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + completion = await response.parse() + assert_matches_type(ChatResponse, completion, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_auth.py b/tests/api_resources/test_auth.py index d0816c46..20a4a573 100644 --- a/tests/api_resources/test_auth.py +++ b/tests/api_resources/test_auth.py @@ -9,7 +9,7 @@ from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type -from arcadepy.types import AuthorizationResponse +from arcadepy.types.shared import AuthorizationResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -20,7 +20,7 @@ class TestAuth: @parametrize def test_method_authorize(self, client: Arcade) -> None: auth = client.auth.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @@ -29,11 +29,9 @@ def test_method_authorize(self, client: Arcade) -> None: def test_method_authorize_with_all_params(self, client: Arcade) -> None: auth = client.auth.authorize( auth_requirement={ - "provider": "provider", - "oauth2": { - "authority": "authority", - "scopes": ["string", "string", "string"], - }, + "oauth2": {"scopes": ["string", "string", "string"]}, + "provider_id": "provider_id", + "provider_type": "provider_type", }, user_id="user_id", ) @@ -42,7 +40,7 @@ def test_method_authorize_with_all_params(self, client: Arcade) -> None: @parametrize def test_raw_response_authorize(self, client: Arcade) -> None: response = client.auth.with_raw_response.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) @@ -54,7 +52,7 @@ def test_raw_response_authorize(self, client: Arcade) -> None: @parametrize def test_streaming_response_authorize(self, client: Arcade) -> None: with client.auth.with_streaming_response.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) as response: assert not response.is_closed @@ -68,22 +66,23 @@ def test_streaming_response_authorize(self, client: Arcade) -> None: @parametrize def test_method_status(self, client: Arcade) -> None: auth = client.auth.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize def test_method_status_with_all_params(self, client: Arcade) -> None: auth = client.auth.status( - authorization_id="authorizationID", + authorization_id="authorizationId", scopes="scopes", + wait=0, ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize def test_raw_response_status(self, client: Arcade) -> None: response = client.auth.with_raw_response.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) assert response.is_closed is True @@ -94,7 +93,7 @@ def test_raw_response_status(self, client: Arcade) -> None: @parametrize def test_streaming_response_status(self, client: Arcade) -> None: with client.auth.with_streaming_response.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -111,7 +110,7 @@ class TestAsyncAuth: @parametrize async def test_method_authorize(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @@ -120,11 +119,9 @@ async def test_method_authorize(self, async_client: AsyncArcade) -> None: async def test_method_authorize_with_all_params(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.authorize( auth_requirement={ - "provider": "provider", - "oauth2": { - "authority": "authority", - "scopes": ["string", "string", "string"], - }, + "oauth2": {"scopes": ["string", "string", "string"]}, + "provider_id": "provider_id", + "provider_type": "provider_type", }, user_id="user_id", ) @@ -133,7 +130,7 @@ async def test_method_authorize_with_all_params(self, async_client: AsyncArcade) @parametrize async def test_raw_response_authorize(self, async_client: AsyncArcade) -> None: response = await async_client.auth.with_raw_response.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) @@ -145,7 +142,7 @@ async def test_raw_response_authorize(self, async_client: AsyncArcade) -> None: @parametrize async def test_streaming_response_authorize(self, async_client: AsyncArcade) -> None: async with async_client.auth.with_streaming_response.authorize( - auth_requirement={"provider": "provider"}, + auth_requirement={}, user_id="user_id", ) as response: assert not response.is_closed @@ -159,22 +156,23 @@ async def test_streaming_response_authorize(self, async_client: AsyncArcade) -> @parametrize async def test_method_status(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize async def test_method_status_with_all_params(self, async_client: AsyncArcade) -> None: auth = await async_client.auth.status( - authorization_id="authorizationID", + authorization_id="authorizationId", scopes="scopes", + wait=0, ) assert_matches_type(AuthorizationResponse, auth, path=["response"]) @parametrize async def test_raw_response_status(self, async_client: AsyncArcade) -> None: response = await async_client.auth.with_raw_response.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) assert response.is_closed is True @@ -185,7 +183,7 @@ async def test_raw_response_status(self, async_client: AsyncArcade) -> None: @parametrize async def test_streaming_response_status(self, async_client: AsyncArcade) -> None: async with async_client.auth.with_streaming_response.status( - authorization_id="authorizationID", + authorization_id="authorizationId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/test_tools.py b/tests/api_resources/test_tools.py index 8fbcf4a6..33f01552 100644 --- a/tests/api_resources/test_tools.py +++ b/tests/api_resources/test_tools.py @@ -9,11 +9,8 @@ from arcadepy import Arcade, AsyncArcade from tests.utils import assert_matches_type -from arcadepy.types import ( - ToolResponse, - ToolDefinition, - AuthorizationResponse, -) +from arcadepy.types import Response, ToolListResponse +from arcadepy.types.shared import AuthorizationResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -21,6 +18,38 @@ class TestTools: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + def test_method_list(self, client: Arcade) -> None: + tool = client.tools.list() + assert_matches_type(ToolListResponse, tool, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Arcade) -> None: + tool = client.tools.list( + toolkit="toolkit", + ) + assert_matches_type(ToolListResponse, tool, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Arcade) -> None: + response = client.tools.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + tool = response.parse() + assert_matches_type(ToolListResponse, tool, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Arcade) -> None: + with client.tools.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + tool = response.parse() + assert_matches_type(ToolListResponse, tool, path=["response"]) + + assert cast(Any, response.is_closed) is True + @parametrize def test_method_authorize(self, client: Arcade) -> None: tool = client.tools.authorize( @@ -67,81 +96,80 @@ def test_streaming_response_authorize(self, client: Arcade) -> None: @parametrize def test_method_execute(self, client: Arcade) -> None: tool = client.tools.execute( - inputs="inputs", tool_name="tool_name", + ) + assert_matches_type(Response, tool, path=["response"]) + + @parametrize + def test_method_execute_with_all_params(self, client: Arcade) -> None: + tool = client.tools.execute( + tool_name="tool_name", + inputs="inputs", tool_version="tool_version", user_id="user_id", ) - assert_matches_type(ToolResponse, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) @parametrize def test_raw_response_execute(self, client: Arcade) -> None: response = client.tools.with_raw_response.execute( - inputs="inputs", tool_name="tool_name", - tool_version="tool_version", - user_id="user_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = response.parse() - assert_matches_type(ToolResponse, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) @parametrize def test_streaming_response_execute(self, client: Arcade) -> None: with client.tools.with_streaming_response.execute( - inputs="inputs", tool_name="tool_name", - tool_version="tool_version", - user_id="user_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = response.parse() - assert_matches_type(ToolResponse, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) assert cast(Any, response.is_closed) is True + +class TestAsyncTools: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize - def test_method_retrieve_definition(self, client: Arcade) -> None: - tool = client.tools.retrieve_definition( - director_id="director_id", - tool_id="tool_id", - ) - assert_matches_type(ToolDefinition, tool, path=["response"]) + async def test_method_list(self, async_client: AsyncArcade) -> None: + tool = await async_client.tools.list() + assert_matches_type(ToolListResponse, tool, path=["response"]) @parametrize - def test_raw_response_retrieve_definition(self, client: Arcade) -> None: - response = client.tools.with_raw_response.retrieve_definition( - director_id="director_id", - tool_id="tool_id", + async def test_method_list_with_all_params(self, async_client: AsyncArcade) -> None: + tool = await async_client.tools.list( + toolkit="toolkit", ) + assert_matches_type(ToolListResponse, tool, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncArcade) -> None: + response = await async_client.tools.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - tool = response.parse() - assert_matches_type(ToolDefinition, tool, path=["response"]) + tool = await response.parse() + assert_matches_type(ToolListResponse, tool, path=["response"]) @parametrize - def test_streaming_response_retrieve_definition(self, client: Arcade) -> None: - with client.tools.with_streaming_response.retrieve_definition( - director_id="director_id", - tool_id="tool_id", - ) as response: + async def test_streaming_response_list(self, async_client: AsyncArcade) -> None: + async with async_client.tools.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - tool = response.parse() - assert_matches_type(ToolDefinition, tool, path=["response"]) + tool = await response.parse() + assert_matches_type(ToolListResponse, tool, path=["response"]) assert cast(Any, response.is_closed) is True - -class TestAsyncTools: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) - @parametrize async def test_method_authorize(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.authorize( @@ -188,73 +216,40 @@ async def test_streaming_response_authorize(self, async_client: AsyncArcade) -> @parametrize async def test_method_execute(self, async_client: AsyncArcade) -> None: tool = await async_client.tools.execute( - inputs="inputs", tool_name="tool_name", + ) + assert_matches_type(Response, tool, path=["response"]) + + @parametrize + async def test_method_execute_with_all_params(self, async_client: AsyncArcade) -> None: + tool = await async_client.tools.execute( + tool_name="tool_name", + inputs="inputs", tool_version="tool_version", user_id="user_id", ) - assert_matches_type(ToolResponse, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) @parametrize async def test_raw_response_execute(self, async_client: AsyncArcade) -> None: response = await async_client.tools.with_raw_response.execute( - inputs="inputs", tool_name="tool_name", - tool_version="tool_version", - user_id="user_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = await response.parse() - assert_matches_type(ToolResponse, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) @parametrize async def test_streaming_response_execute(self, async_client: AsyncArcade) -> None: async with async_client.tools.with_streaming_response.execute( - inputs="inputs", tool_name="tool_name", - tool_version="tool_version", - user_id="user_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - tool = await response.parse() - assert_matches_type(ToolResponse, tool, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve_definition(self, async_client: AsyncArcade) -> None: - tool = await async_client.tools.retrieve_definition( - director_id="director_id", - tool_id="tool_id", - ) - assert_matches_type(ToolDefinition, tool, path=["response"]) - - @parametrize - async def test_raw_response_retrieve_definition(self, async_client: AsyncArcade) -> None: - response = await async_client.tools.with_raw_response.retrieve_definition( - director_id="director_id", - tool_id="tool_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - tool = await response.parse() - assert_matches_type(ToolDefinition, tool, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve_definition(self, async_client: AsyncArcade) -> None: - async with async_client.tools.with_streaming_response.retrieve_definition( - director_id="director_id", - tool_id="tool_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = await response.parse() - assert_matches_type(ToolDefinition, tool, path=["response"]) + assert_matches_type(Response, tool, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/tools/__init__.py b/tests/api_resources/tools/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/tools/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/tools/test_definition.py b/tests/api_resources/tools/test_definition.py new file mode 100644 index 00000000..1e525c30 --- /dev/null +++ b/tests/api_resources/tools/test_definition.py @@ -0,0 +1,90 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from arcadepy import Arcade, AsyncArcade +from tests.utils import assert_matches_type +from arcadepy.types.shared import ToolDefinition + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDefinition: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_get(self, client: Arcade) -> None: + definition = client.tools.definition.get( + director_id="directorId", + tool_id="toolId", + ) + assert_matches_type(ToolDefinition, definition, path=["response"]) + + @parametrize + def test_raw_response_get(self, client: Arcade) -> None: + response = client.tools.definition.with_raw_response.get( + director_id="directorId", + tool_id="toolId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + definition = response.parse() + assert_matches_type(ToolDefinition, definition, path=["response"]) + + @parametrize + def test_streaming_response_get(self, client: Arcade) -> None: + with client.tools.definition.with_streaming_response.get( + director_id="directorId", + tool_id="toolId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + definition = response.parse() + assert_matches_type(ToolDefinition, definition, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncDefinition: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_get(self, async_client: AsyncArcade) -> None: + definition = await async_client.tools.definition.get( + director_id="directorId", + tool_id="toolId", + ) + assert_matches_type(ToolDefinition, definition, path=["response"]) + + @parametrize + async def test_raw_response_get(self, async_client: AsyncArcade) -> None: + response = await async_client.tools.definition.with_raw_response.get( + director_id="directorId", + tool_id="toolId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + definition = await response.parse() + assert_matches_type(ToolDefinition, definition, path=["response"]) + + @parametrize + async def test_streaming_response_get(self, async_client: AsyncArcade) -> None: + async with async_client.tools.definition.with_streaming_response.get( + director_id="directorId", + tool_id="toolId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + definition = await response.parse() + assert_matches_type(ToolDefinition, definition, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/test_client.py b/tests/test_client.py index 04929ebb..37b24829 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -800,7 +800,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions() + response = client.chat.completions.with_raw_response.completions() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -824,7 +824,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": Omit()}) + response = client.chat.completions.with_raw_response.completions( + extra_headers={"x-stainless-retry-count": Omit()} + ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -847,7 +849,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": "42"}) + response = client.chat.completions.with_raw_response.completions( + extra_headers={"x-stainless-retry-count": "42"} + ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1621,7 +1625,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions() + response = await client.chat.completions.with_raw_response.completions() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1646,7 +1650,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": Omit()}) + response = await client.chat.completions.with_raw_response.completions( + extra_headers={"x-stainless-retry-count": Omit()} + ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1670,6 +1676,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": "42"}) + response = await client.chat.completions.with_raw_response.completions( + extra_headers={"x-stainless-retry-count": "42"} + ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From 4fe706f3fb67ea7ec08e0410be1fc42f822d7f45 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 02:50:50 +0000 Subject: [PATCH 3/4] feat(api): api update (#15) --- README.md | 12 +-- api.md | 2 +- src/arcadepy/resources/chat/completions.py | 30 +++---- src/arcadepy/types/chat/__init__.py | 2 +- .../types/chat/completion_create_params.py | 82 +++++++++++++++++++ tests/api_resources/chat/test_completions.py | 32 ++++---- tests/test_client.py | 16 ++-- 7 files changed, 127 insertions(+), 49 deletions(-) create mode 100644 src/arcadepy/types/chat/completion_create_params.py diff --git a/README.md b/README.md index e886bf44..af5ae20e 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ from arcadepy import Arcade client = Arcade() try: - client.chat.completions.completions( + client.chat.completions.create( messages=[ { "role": "user", @@ -154,7 +154,7 @@ client = Arcade( ) # Or, configure per-request: -client.with_options(max_retries=5).chat.completions.completions( +client.with_options(max_retries=5).chat.completions.create( messages=[ { "role": "user", @@ -184,7 +184,7 @@ client = Arcade( ) # Override per-request: -client.with_options(timeout=5.0).chat.completions.completions( +client.with_options(timeout=5.0).chat.completions.create( messages=[ { "role": "user", @@ -230,7 +230,7 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from arcadepy import Arcade client = Arcade() -response = client.chat.completions.with_raw_response.completions( +response = client.chat.completions.with_raw_response.create( messages=[{ "role": "user", "content": "Hello, how can I use Arcade AI?", @@ -238,7 +238,7 @@ response = client.chat.completions.with_raw_response.completions( ) print(response.headers.get('X-My-Header')) -completion = response.parse() # get the object that `chat.completions.completions()` would have returned +completion = response.parse() # get the object that `chat.completions.create()` would have returned print(completion.id) ``` @@ -253,7 +253,7 @@ The above interface eagerly reads the full response body when you make the reque To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. ```python -with client.chat.completions.with_streaming_response.completions( +with client.chat.completions.with_streaming_response.create( messages=[ { "role": "user", diff --git a/api.md b/api.md index 795764d6..4b003758 100644 --- a/api.md +++ b/api.md @@ -41,7 +41,7 @@ from arcadepy.types import ChatMessage, ChatRequest, ChatResponse, Choice, Usage Methods: -- client.chat.completions.completions(\*\*params) -> ChatResponse +- client.chat.completions.create(\*\*params) -> ChatResponse # Tools diff --git a/src/arcadepy/resources/chat/completions.py b/src/arcadepy/resources/chat/completions.py index bacfb6e7..ca188130 100644 --- a/src/arcadepy/resources/chat/completions.py +++ b/src/arcadepy/resources/chat/completions.py @@ -20,7 +20,7 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.chat import completion_completions_params +from ...types.chat import completion_create_params from ..._base_client import make_request_options from ...types.chat_response import ChatResponse from ...types.chat_message_param import ChatMessageParam @@ -48,7 +48,7 @@ def with_streaming_response(self) -> CompletionsResourceWithStreamingResponse: """ return CompletionsResourceWithStreamingResponse(self) - def completions( + def create( self, *, frequency_penalty: int | NotGiven = NOT_GIVEN, @@ -64,7 +64,7 @@ def completions( seed: int | NotGiven = NOT_GIVEN, stop: List[str] | NotGiven = NOT_GIVEN, stream: bool | NotGiven = NOT_GIVEN, - stream_options: completion_completions_params.StreamOptions | NotGiven = NOT_GIVEN, + stream_options: completion_create_params.StreamOptions | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, tool_choice: object | NotGiven = NOT_GIVEN, tools: object | NotGiven = NOT_GIVEN, @@ -138,7 +138,7 @@ def completions( "top_p": top_p, "user": user, }, - completion_completions_params.CompletionCompletionsParams, + completion_create_params.CompletionCreateParams, ), options=make_request_options( extra_headers=extra_headers, @@ -171,7 +171,7 @@ def with_streaming_response(self) -> AsyncCompletionsResourceWithStreamingRespon """ return AsyncCompletionsResourceWithStreamingResponse(self) - async def completions( + async def create( self, *, frequency_penalty: int | NotGiven = NOT_GIVEN, @@ -187,7 +187,7 @@ async def completions( seed: int | NotGiven = NOT_GIVEN, stop: List[str] | NotGiven = NOT_GIVEN, stream: bool | NotGiven = NOT_GIVEN, - stream_options: completion_completions_params.StreamOptions | NotGiven = NOT_GIVEN, + stream_options: completion_create_params.StreamOptions | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, tool_choice: object | NotGiven = NOT_GIVEN, tools: object | NotGiven = NOT_GIVEN, @@ -261,7 +261,7 @@ async def completions( "top_p": top_p, "user": user, }, - completion_completions_params.CompletionCompletionsParams, + completion_create_params.CompletionCreateParams, ), options=make_request_options( extra_headers=extra_headers, @@ -278,8 +278,8 @@ class CompletionsResourceWithRawResponse: def __init__(self, completions: CompletionsResource) -> None: self._completions = completions - self.completions = to_raw_response_wrapper( - completions.completions, + self.create = to_raw_response_wrapper( + completions.create, ) @@ -287,8 +287,8 @@ class AsyncCompletionsResourceWithRawResponse: def __init__(self, completions: AsyncCompletionsResource) -> None: self._completions = completions - self.completions = async_to_raw_response_wrapper( - completions.completions, + self.create = async_to_raw_response_wrapper( + completions.create, ) @@ -296,8 +296,8 @@ class CompletionsResourceWithStreamingResponse: def __init__(self, completions: CompletionsResource) -> None: self._completions = completions - self.completions = to_streamed_response_wrapper( - completions.completions, + self.create = to_streamed_response_wrapper( + completions.create, ) @@ -305,6 +305,6 @@ class AsyncCompletionsResourceWithStreamingResponse: def __init__(self, completions: AsyncCompletionsResource) -> None: self._completions = completions - self.completions = async_to_streamed_response_wrapper( - completions.completions, + self.create = async_to_streamed_response_wrapper( + completions.create, ) diff --git a/src/arcadepy/types/chat/__init__.py b/src/arcadepy/types/chat/__init__.py index 44798218..4a2b8db7 100644 --- a/src/arcadepy/types/chat/__init__.py +++ b/src/arcadepy/types/chat/__init__.py @@ -2,4 +2,4 @@ from __future__ import annotations -from .completion_completions_params import CompletionCompletionsParams as CompletionCompletionsParams +from .completion_create_params import CompletionCreateParams as CompletionCreateParams diff --git a/src/arcadepy/types/chat/completion_create_params.py b/src/arcadepy/types/chat/completion_create_params.py new file mode 100644 index 00000000..43b86239 --- /dev/null +++ b/src/arcadepy/types/chat/completion_create_params.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Iterable +from typing_extensions import Literal, TypedDict + +from ..chat_message_param import ChatMessageParam + +__all__ = ["CompletionCreateParams", "StreamOptions"] + + +class CompletionCreateParams(TypedDict, total=False): + frequency_penalty: int + + logit_bias: Dict[str, int] + """ + LogitBias is must be a token id string (specified by their token ID in the + tokenizer), not a word string. incorrect: `"logit_bias":{"You": 6}`, correct: + `"logit_bias":{"1639": 6}` refs: + https://platform.openai.com/docs/api-reference/chat/create#chat/create-logit_bias + """ + + logprobs: bool + """ + LogProbs indicates whether to return log probabilities of the output tokens or + not. If true, returns the log probabilities of each output token returned in the + content of message. This option is currently not available on the + gpt-4-vision-preview model. + """ + + max_tokens: int + + messages: Iterable[ChatMessageParam] + + model: str + + n: int + + parallel_tool_calls: object + """Disable the default behavior of parallel tool calls by setting it: false.""" + + presence_penalty: int + + response_format: Literal["json_object", "text"] + + seed: int + + stop: List[str] + + stream: bool + + stream_options: StreamOptions + """Options for streaming response. Only set this when you set stream: true.""" + + temperature: float + + tool_choice: object + """This can be either a string or an ToolChoice object.""" + + tools: object + + top_logprobs: int + """ + TopLogProbs is an integer between 0 and 5 specifying the number of most likely + tokens to return at each token position, each with an associated log + probability. logprobs must be set to true if this parameter is used. + """ + + top_p: float + + user: str + + +class StreamOptions(TypedDict, total=False): + include_usage: bool + """ + If set, an additional chunk will be streamed before the data: [DONE] message. + The usage field on this chunk shows the token usage statistics for the entire + request, and the choices field will always be an empty array. All other chunks + will also include a usage field, but with a null value. + """ diff --git a/tests/api_resources/chat/test_completions.py b/tests/api_resources/chat/test_completions.py index 1dd2b00d..3cdade05 100644 --- a/tests/api_resources/chat/test_completions.py +++ b/tests/api_resources/chat/test_completions.py @@ -18,13 +18,13 @@ class TestCompletions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_completions(self, client: Arcade) -> None: - completion = client.chat.completions.completions() + def test_method_create(self, client: Arcade) -> None: + completion = client.chat.completions.create() assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - def test_method_completions_with_all_params(self, client: Arcade) -> None: - completion = client.chat.completions.completions( + def test_method_create_with_all_params(self, client: Arcade) -> None: + completion = client.chat.completions.create( frequency_penalty=0, logit_bias={"foo": 0}, logprobs=True, @@ -146,8 +146,8 @@ def test_method_completions_with_all_params(self, client: Arcade) -> None: assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - def test_raw_response_completions(self, client: Arcade) -> None: - response = client.chat.completions.with_raw_response.completions() + def test_raw_response_create(self, client: Arcade) -> None: + response = client.chat.completions.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -155,8 +155,8 @@ def test_raw_response_completions(self, client: Arcade) -> None: assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - def test_streaming_response_completions(self, client: Arcade) -> None: - with client.chat.completions.with_streaming_response.completions() as response: + def test_streaming_response_create(self, client: Arcade) -> None: + with client.chat.completions.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -170,13 +170,13 @@ class TestAsyncCompletions: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_completions(self, async_client: AsyncArcade) -> None: - completion = await async_client.chat.completions.completions() + async def test_method_create(self, async_client: AsyncArcade) -> None: + completion = await async_client.chat.completions.create() assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - async def test_method_completions_with_all_params(self, async_client: AsyncArcade) -> None: - completion = await async_client.chat.completions.completions( + async def test_method_create_with_all_params(self, async_client: AsyncArcade) -> None: + completion = await async_client.chat.completions.create( frequency_penalty=0, logit_bias={"foo": 0}, logprobs=True, @@ -298,8 +298,8 @@ async def test_method_completions_with_all_params(self, async_client: AsyncArcad assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - async def test_raw_response_completions(self, async_client: AsyncArcade) -> None: - response = await async_client.chat.completions.with_raw_response.completions() + async def test_raw_response_create(self, async_client: AsyncArcade) -> None: + response = await async_client.chat.completions.with_raw_response.create() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -307,8 +307,8 @@ async def test_raw_response_completions(self, async_client: AsyncArcade) -> None assert_matches_type(ChatResponse, completion, path=["response"]) @parametrize - async def test_streaming_response_completions(self, async_client: AsyncArcade) -> None: - async with async_client.chat.completions.with_streaming_response.completions() as response: + async def test_streaming_response_create(self, async_client: AsyncArcade) -> None: + async with async_client.chat.completions.with_streaming_response.create() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 37b24829..f8ae3bf7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -800,7 +800,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.completions.with_raw_response.completions() + response = client.chat.completions.with_raw_response.create() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -824,9 +824,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.completions.with_raw_response.completions( - extra_headers={"x-stainless-retry-count": Omit()} - ) + response = client.chat.completions.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -849,9 +847,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = client.chat.completions.with_raw_response.completions( - extra_headers={"x-stainless-retry-count": "42"} - ) + response = client.chat.completions.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1625,7 +1621,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.completions.with_raw_response.completions() + response = await client.chat.completions.with_raw_response.create() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1650,7 +1646,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.completions.with_raw_response.completions( + response = await client.chat.completions.with_raw_response.create( extra_headers={"x-stainless-retry-count": Omit()} ) @@ -1676,7 +1672,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) - response = await client.chat.completions.with_raw_response.completions( + response = await client.chat.completions.with_raw_response.create( extra_headers={"x-stainless-retry-count": "42"} ) From 3d0c402da34fdddc1222da6556614e4e5eb1521a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 02:51:05 +0000 Subject: [PATCH 4/4] release: 0.1.0-alpha.3 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ pyproject.toml | 2 +- src/arcadepy/_version.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f14b480a..aaf968a1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.2" + ".": "0.1.0-alpha.3" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc8d3c0..e9382867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.1.0-alpha.3 (2024-10-14) + +Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/ArcadeAI/arcade-py/compare/v0.1.0-alpha.2...v0.1.0-alpha.3) + +### Features + +* **api:** api update ([#12](https://github.com/ArcadeAI/arcade-py/issues/12)) ([efadea8](https://github.com/ArcadeAI/arcade-py/commit/efadea87ab3842f65b9a042ad00019285199c8ba)) +* **api:** api update ([#14](https://github.com/ArcadeAI/arcade-py/issues/14)) ([744e3f3](https://github.com/ArcadeAI/arcade-py/commit/744e3f3ec16f28155847fe0f195ef5b8e620859f)) +* **api:** api update ([#15](https://github.com/ArcadeAI/arcade-py/issues/15)) ([4fe706f](https://github.com/ArcadeAI/arcade-py/commit/4fe706f3fb67ea7ec08e0410be1fc42f822d7f45)) + ## 0.1.0-alpha.2 (2024-10-14) Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/ArcadeAI/arcade-py/compare/v0.1.0-alpha.1...v0.1.0-alpha.2) diff --git a/pyproject.toml b/pyproject.toml index 352d8399..962dac26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "arcadepy" -version = "0.1.0-alpha.2" +version = "0.1.0-alpha.3" description = "The official Python library for the Arcade API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/arcadepy/_version.py b/src/arcadepy/_version.py index 0f33ca07..cac8d226 100644 --- a/src/arcadepy/_version.py +++ b/src/arcadepy/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "arcadepy" -__version__ = "0.1.0-alpha.2" # x-release-please-version +__version__ = "0.1.0-alpha.3" # x-release-please-version