diff --git a/src/llama_stack_client/_base_client.py b/src/llama_stack_client/_base_client.py index a0c4ea5b..4d199940 100644 --- a/src/llama_stack_client/_base_client.py +++ b/src/llama_stack_client/_base_client.py @@ -960,6 +960,9 @@ def request( if self.custom_auth is not None: kwargs["auth"] = self.custom_auth + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None @@ -1460,6 +1463,9 @@ async def request( if self.custom_auth is not None: kwargs["auth"] = self.custom_auth + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None diff --git a/src/llama_stack_client/_client.py b/src/llama_stack_client/_client.py index e2e2c1e5..177d0207 100644 --- a/src/llama_stack_client/_client.py +++ b/src/llama_stack_client/_client.py @@ -23,6 +23,7 @@ from ._utils import is_given, get_async_library from ._version import __version__ from .resources import ( + files, tools, models, routes, @@ -33,13 +34,14 @@ datasets, inference, providers, - responses, telemetry, vector_io, benchmarks, + embeddings, toolgroups, vector_dbs, completions, + vector_stores, scoring_functions, synthetic_data_generation, ) @@ -53,6 +55,7 @@ from .resources.chat import chat from .resources.eval import eval from .resources.agents import agents +from .resources.responses import responses from .resources.tool_runtime import tool_runtime from .resources.post_training import post_training @@ -78,10 +81,12 @@ class LlamaStackClient(SyncAPIClient): eval: eval.EvalResource inspect: inspect.InspectResource inference: inference.InferenceResource + embeddings: embeddings.EmbeddingsResource chat: chat.ChatResource completions: completions.CompletionsResource vector_io: vector_io.VectorIoResource vector_dbs: vector_dbs.VectorDBsResource + vector_stores: vector_stores.VectorStoresResource models: models.ModelsResource post_training: post_training.PostTrainingResource providers: providers.ProvidersResource @@ -93,6 +98,7 @@ class LlamaStackClient(SyncAPIClient): scoring: scoring.ScoringResource scoring_functions: scoring_functions.ScoringFunctionsResource benchmarks: benchmarks.BenchmarksResource + files: files.FilesResource with_raw_response: LlamaStackClientWithRawResponse with_streaming_response: LlamaStackClientWithStreamedResponse @@ -161,10 +167,12 @@ def __init__( self.eval = eval.EvalResource(self) self.inspect = inspect.InspectResource(self) self.inference = inference.InferenceResource(self) + self.embeddings = embeddings.EmbeddingsResource(self) self.chat = chat.ChatResource(self) self.completions = completions.CompletionsResource(self) self.vector_io = vector_io.VectorIoResource(self) self.vector_dbs = vector_dbs.VectorDBsResource(self) + self.vector_stores = vector_stores.VectorStoresResource(self) self.models = models.ModelsResource(self) self.post_training = post_training.PostTrainingResource(self) self.providers = providers.ProvidersResource(self) @@ -176,6 +184,7 @@ def __init__( self.scoring = scoring.ScoringResource(self) self.scoring_functions = scoring_functions.ScoringFunctionsResource(self) self.benchmarks = benchmarks.BenchmarksResource(self) + self.files = files.FilesResource(self) self.with_raw_response = LlamaStackClientWithRawResponse(self) self.with_streaming_response = LlamaStackClientWithStreamedResponse(self) @@ -296,10 +305,12 @@ class AsyncLlamaStackClient(AsyncAPIClient): eval: eval.AsyncEvalResource inspect: inspect.AsyncInspectResource inference: inference.AsyncInferenceResource + embeddings: embeddings.AsyncEmbeddingsResource chat: chat.AsyncChatResource completions: completions.AsyncCompletionsResource vector_io: vector_io.AsyncVectorIoResource vector_dbs: vector_dbs.AsyncVectorDBsResource + vector_stores: vector_stores.AsyncVectorStoresResource models: models.AsyncModelsResource post_training: post_training.AsyncPostTrainingResource providers: providers.AsyncProvidersResource @@ -311,6 +322,7 @@ class AsyncLlamaStackClient(AsyncAPIClient): scoring: scoring.AsyncScoringResource scoring_functions: scoring_functions.AsyncScoringFunctionsResource benchmarks: benchmarks.AsyncBenchmarksResource + files: files.AsyncFilesResource with_raw_response: AsyncLlamaStackClientWithRawResponse with_streaming_response: AsyncLlamaStackClientWithStreamedResponse @@ -379,10 +391,12 @@ def __init__( self.eval = eval.AsyncEvalResource(self) self.inspect = inspect.AsyncInspectResource(self) self.inference = inference.AsyncInferenceResource(self) + self.embeddings = embeddings.AsyncEmbeddingsResource(self) self.chat = chat.AsyncChatResource(self) self.completions = completions.AsyncCompletionsResource(self) self.vector_io = vector_io.AsyncVectorIoResource(self) self.vector_dbs = vector_dbs.AsyncVectorDBsResource(self) + self.vector_stores = vector_stores.AsyncVectorStoresResource(self) self.models = models.AsyncModelsResource(self) self.post_training = post_training.AsyncPostTrainingResource(self) self.providers = providers.AsyncProvidersResource(self) @@ -394,6 +408,7 @@ def __init__( self.scoring = scoring.AsyncScoringResource(self) self.scoring_functions = scoring_functions.AsyncScoringFunctionsResource(self) self.benchmarks = benchmarks.AsyncBenchmarksResource(self) + self.files = files.AsyncFilesResource(self) self.with_raw_response = AsyncLlamaStackClientWithRawResponse(self) self.with_streaming_response = AsyncLlamaStackClientWithStreamedResponse(self) @@ -515,10 +530,12 @@ def __init__(self, client: LlamaStackClient) -> None: self.eval = eval.EvalResourceWithRawResponse(client.eval) self.inspect = inspect.InspectResourceWithRawResponse(client.inspect) self.inference = inference.InferenceResourceWithRawResponse(client.inference) + self.embeddings = embeddings.EmbeddingsResourceWithRawResponse(client.embeddings) self.chat = chat.ChatResourceWithRawResponse(client.chat) self.completions = completions.CompletionsResourceWithRawResponse(client.completions) self.vector_io = vector_io.VectorIoResourceWithRawResponse(client.vector_io) self.vector_dbs = vector_dbs.VectorDBsResourceWithRawResponse(client.vector_dbs) + self.vector_stores = vector_stores.VectorStoresResourceWithRawResponse(client.vector_stores) self.models = models.ModelsResourceWithRawResponse(client.models) self.post_training = post_training.PostTrainingResourceWithRawResponse(client.post_training) self.providers = providers.ProvidersResourceWithRawResponse(client.providers) @@ -532,6 +549,7 @@ def __init__(self, client: LlamaStackClient) -> None: self.scoring = scoring.ScoringResourceWithRawResponse(client.scoring) self.scoring_functions = scoring_functions.ScoringFunctionsResourceWithRawResponse(client.scoring_functions) self.benchmarks = benchmarks.BenchmarksResourceWithRawResponse(client.benchmarks) + self.files = files.FilesResourceWithRawResponse(client.files) class AsyncLlamaStackClientWithRawResponse: @@ -545,10 +563,12 @@ def __init__(self, client: AsyncLlamaStackClient) -> None: self.eval = eval.AsyncEvalResourceWithRawResponse(client.eval) self.inspect = inspect.AsyncInspectResourceWithRawResponse(client.inspect) self.inference = inference.AsyncInferenceResourceWithRawResponse(client.inference) + self.embeddings = embeddings.AsyncEmbeddingsResourceWithRawResponse(client.embeddings) self.chat = chat.AsyncChatResourceWithRawResponse(client.chat) self.completions = completions.AsyncCompletionsResourceWithRawResponse(client.completions) self.vector_io = vector_io.AsyncVectorIoResourceWithRawResponse(client.vector_io) self.vector_dbs = vector_dbs.AsyncVectorDBsResourceWithRawResponse(client.vector_dbs) + self.vector_stores = vector_stores.AsyncVectorStoresResourceWithRawResponse(client.vector_stores) self.models = models.AsyncModelsResourceWithRawResponse(client.models) self.post_training = post_training.AsyncPostTrainingResourceWithRawResponse(client.post_training) self.providers = providers.AsyncProvidersResourceWithRawResponse(client.providers) @@ -564,6 +584,7 @@ def __init__(self, client: AsyncLlamaStackClient) -> None: client.scoring_functions ) self.benchmarks = benchmarks.AsyncBenchmarksResourceWithRawResponse(client.benchmarks) + self.files = files.AsyncFilesResourceWithRawResponse(client.files) class LlamaStackClientWithStreamedResponse: @@ -577,10 +598,12 @@ def __init__(self, client: LlamaStackClient) -> None: self.eval = eval.EvalResourceWithStreamingResponse(client.eval) self.inspect = inspect.InspectResourceWithStreamingResponse(client.inspect) self.inference = inference.InferenceResourceWithStreamingResponse(client.inference) + self.embeddings = embeddings.EmbeddingsResourceWithStreamingResponse(client.embeddings) self.chat = chat.ChatResourceWithStreamingResponse(client.chat) self.completions = completions.CompletionsResourceWithStreamingResponse(client.completions) self.vector_io = vector_io.VectorIoResourceWithStreamingResponse(client.vector_io) self.vector_dbs = vector_dbs.VectorDBsResourceWithStreamingResponse(client.vector_dbs) + self.vector_stores = vector_stores.VectorStoresResourceWithStreamingResponse(client.vector_stores) self.models = models.ModelsResourceWithStreamingResponse(client.models) self.post_training = post_training.PostTrainingResourceWithStreamingResponse(client.post_training) self.providers = providers.ProvidersResourceWithStreamingResponse(client.providers) @@ -596,6 +619,7 @@ def __init__(self, client: LlamaStackClient) -> None: client.scoring_functions ) self.benchmarks = benchmarks.BenchmarksResourceWithStreamingResponse(client.benchmarks) + self.files = files.FilesResourceWithStreamingResponse(client.files) class AsyncLlamaStackClientWithStreamedResponse: @@ -609,10 +633,12 @@ def __init__(self, client: AsyncLlamaStackClient) -> None: self.eval = eval.AsyncEvalResourceWithStreamingResponse(client.eval) self.inspect = inspect.AsyncInspectResourceWithStreamingResponse(client.inspect) self.inference = inference.AsyncInferenceResourceWithStreamingResponse(client.inference) + self.embeddings = embeddings.AsyncEmbeddingsResourceWithStreamingResponse(client.embeddings) self.chat = chat.AsyncChatResourceWithStreamingResponse(client.chat) self.completions = completions.AsyncCompletionsResourceWithStreamingResponse(client.completions) self.vector_io = vector_io.AsyncVectorIoResourceWithStreamingResponse(client.vector_io) self.vector_dbs = vector_dbs.AsyncVectorDBsResourceWithStreamingResponse(client.vector_dbs) + self.vector_stores = vector_stores.AsyncVectorStoresResourceWithStreamingResponse(client.vector_stores) self.models = models.AsyncModelsResourceWithStreamingResponse(client.models) self.post_training = post_training.AsyncPostTrainingResourceWithStreamingResponse(client.post_training) self.providers = providers.AsyncProvidersResourceWithStreamingResponse(client.providers) @@ -630,6 +656,7 @@ def __init__(self, client: AsyncLlamaStackClient) -> None: client.scoring_functions ) self.benchmarks = benchmarks.AsyncBenchmarksResourceWithStreamingResponse(client.benchmarks) + self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) Client = LlamaStackClient diff --git a/src/llama_stack_client/_files.py b/src/llama_stack_client/_files.py index 715cc207..cd5d4f51 100644 --- a/src/llama_stack_client/_files.py +++ b/src/llama_stack_client/_files.py @@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead." + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/llama-stack-python/tree/main#file-uploads" ) from None diff --git a/src/llama_stack_client/_models.py b/src/llama_stack_client/_models.py index 798956f1..4f214980 100644 --- a/src/llama_stack_client/_models.py +++ b/src/llama_stack_client/_models.py @@ -737,6 +737,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): idempotency_key: str json_data: Body extra_json: AnyMapping + follow_redirects: bool @final @@ -750,6 +751,7 @@ class FinalRequestOptions(pydantic.BaseModel): files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() + follow_redirects: Union[bool, None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. diff --git a/src/llama_stack_client/_types.py b/src/llama_stack_client/_types.py index ed5b188d..63631322 100644 --- a/src/llama_stack_client/_types.py +++ b/src/llama_stack_client/_types.py @@ -100,6 +100,7 @@ class RequestOptions(TypedDict, total=False): params: Query extra_json: AnyMapping idempotency_key: str + follow_redirects: bool # Sentinel class used until PEP 0661 is accepted @@ -215,3 +216,4 @@ class _GenericAlias(Protocol): class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth + follow_redirects: bool diff --git a/src/llama_stack_client/resources/__init__.py b/src/llama_stack_client/resources/__init__.py index e1c150fc..23f61be1 100644 --- a/src/llama_stack_client/resources/__init__.py +++ b/src/llama_stack_client/resources/__init__.py @@ -16,6 +16,14 @@ EvalResourceWithStreamingResponse, AsyncEvalResourceWithStreamingResponse, ) +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) from .tools import ( ToolsResource, AsyncToolsResource, @@ -136,6 +144,14 @@ BenchmarksResourceWithStreamingResponse, AsyncBenchmarksResourceWithStreamingResponse, ) +from .embeddings import ( + EmbeddingsResource, + AsyncEmbeddingsResource, + EmbeddingsResourceWithRawResponse, + AsyncEmbeddingsResourceWithRawResponse, + EmbeddingsResourceWithStreamingResponse, + AsyncEmbeddingsResourceWithStreamingResponse, +) from .toolgroups import ( ToolgroupsResource, AsyncToolgroupsResource, @@ -176,6 +192,14 @@ PostTrainingResourceWithStreamingResponse, AsyncPostTrainingResourceWithStreamingResponse, ) +from .vector_stores import ( + VectorStoresResource, + AsyncVectorStoresResource, + VectorStoresResourceWithRawResponse, + AsyncVectorStoresResourceWithRawResponse, + VectorStoresResourceWithStreamingResponse, + AsyncVectorStoresResourceWithStreamingResponse, +) from .scoring_functions import ( ScoringFunctionsResource, AsyncScoringFunctionsResource, @@ -248,6 +272,12 @@ "AsyncInferenceResourceWithRawResponse", "InferenceResourceWithStreamingResponse", "AsyncInferenceResourceWithStreamingResponse", + "EmbeddingsResource", + "AsyncEmbeddingsResource", + "EmbeddingsResourceWithRawResponse", + "AsyncEmbeddingsResourceWithRawResponse", + "EmbeddingsResourceWithStreamingResponse", + "AsyncEmbeddingsResourceWithStreamingResponse", "ChatResource", "AsyncChatResource", "ChatResourceWithRawResponse", @@ -272,6 +302,12 @@ "AsyncVectorDBsResourceWithRawResponse", "VectorDBsResourceWithStreamingResponse", "AsyncVectorDBsResourceWithStreamingResponse", + "VectorStoresResource", + "AsyncVectorStoresResource", + "VectorStoresResourceWithRawResponse", + "AsyncVectorStoresResourceWithRawResponse", + "VectorStoresResourceWithStreamingResponse", + "AsyncVectorStoresResourceWithStreamingResponse", "ModelsResource", "AsyncModelsResource", "ModelsResourceWithRawResponse", @@ -338,4 +374,10 @@ "AsyncBenchmarksResourceWithRawResponse", "BenchmarksResourceWithStreamingResponse", "AsyncBenchmarksResourceWithStreamingResponse", + "FilesResource", + "AsyncFilesResource", + "FilesResourceWithRawResponse", + "AsyncFilesResourceWithRawResponse", + "FilesResourceWithStreamingResponse", + "AsyncFilesResourceWithStreamingResponse", ] diff --git a/src/llama_stack_client/resources/embeddings.py b/src/llama_stack_client/resources/embeddings.py new file mode 100644 index 00000000..ed389ff5 --- /dev/null +++ b/src/llama_stack_client/resources/embeddings.py @@ -0,0 +1,223 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union + +import httpx + +from ..types import embedding_create_params +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 .._base_client import make_request_options +from ..types.embeddings_response import EmbeddingsResponse + +__all__ = ["EmbeddingsResource", "AsyncEmbeddingsResource"] + + +class EmbeddingsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> EmbeddingsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return EmbeddingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> EmbeddingsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return EmbeddingsResourceWithStreamingResponse(self) + + def create( + self, + *, + input: Union[str, List[str]], + model: str, + dimensions: int | NotGiven = NOT_GIVEN, + encoding_format: str | 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, + ) -> EmbeddingsResponse: + """ + Generate OpenAI-compatible embeddings for the given input using the specified + model. + + Args: + input: Input text to embed, encoded as a string or array of strings. To embed multiple + inputs in a single request, pass an array of strings. + + model: The identifier of the model to use. The model must be an embedding model + registered with Llama Stack and available via the /models endpoint. + + dimensions: (Optional) The number of dimensions the resulting output embeddings should have. + Only supported in text-embedding-3 and later models. + + encoding_format: (Optional) The format to return the embeddings in. Can be either "float" or + "base64". Defaults to "float". + + user: (Optional) A unique identifier representing your end-user, which can help OpenAI + to monitor and detect abuse. + + 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._post( + "/v1/openai/v1/embeddings", + body=maybe_transform( + { + "input": input, + "model": model, + "dimensions": dimensions, + "encoding_format": encoding_format, + "user": user, + }, + embedding_create_params.EmbeddingCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EmbeddingsResponse, + ) + + +class AsyncEmbeddingsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncEmbeddingsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return AsyncEmbeddingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncEmbeddingsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return AsyncEmbeddingsResourceWithStreamingResponse(self) + + async def create( + self, + *, + input: Union[str, List[str]], + model: str, + dimensions: int | NotGiven = NOT_GIVEN, + encoding_format: str | 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, + ) -> EmbeddingsResponse: + """ + Generate OpenAI-compatible embeddings for the given input using the specified + model. + + Args: + input: Input text to embed, encoded as a string or array of strings. To embed multiple + inputs in a single request, pass an array of strings. + + model: The identifier of the model to use. The model must be an embedding model + registered with Llama Stack and available via the /models endpoint. + + dimensions: (Optional) The number of dimensions the resulting output embeddings should have. + Only supported in text-embedding-3 and later models. + + encoding_format: (Optional) The format to return the embeddings in. Can be either "float" or + "base64". Defaults to "float". + + user: (Optional) A unique identifier representing your end-user, which can help OpenAI + to monitor and detect abuse. + + 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._post( + "/v1/openai/v1/embeddings", + body=await async_maybe_transform( + { + "input": input, + "model": model, + "dimensions": dimensions, + "encoding_format": encoding_format, + "user": user, + }, + embedding_create_params.EmbeddingCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EmbeddingsResponse, + ) + + +class EmbeddingsResourceWithRawResponse: + def __init__(self, embeddings: EmbeddingsResource) -> None: + self._embeddings = embeddings + + self.create = to_raw_response_wrapper( + embeddings.create, + ) + + +class AsyncEmbeddingsResourceWithRawResponse: + def __init__(self, embeddings: AsyncEmbeddingsResource) -> None: + self._embeddings = embeddings + + self.create = async_to_raw_response_wrapper( + embeddings.create, + ) + + +class EmbeddingsResourceWithStreamingResponse: + def __init__(self, embeddings: EmbeddingsResource) -> None: + self._embeddings = embeddings + + self.create = to_streamed_response_wrapper( + embeddings.create, + ) + + +class AsyncEmbeddingsResourceWithStreamingResponse: + def __init__(self, embeddings: AsyncEmbeddingsResource) -> None: + self._embeddings = embeddings + + self.create = async_to_streamed_response_wrapper( + embeddings.create, + ) diff --git a/src/llama_stack_client/resources/files.py b/src/llama_stack_client/resources/files.py new file mode 100644 index 00000000..d795a42f --- /dev/null +++ b/src/llama_stack_client/resources/files.py @@ -0,0 +1,572 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Mapping, cast +from typing_extensions import Literal + +import httpx + +from ..types import file_list_params, file_create_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes +from .._utils import extract_files, maybe_transform, deepcopy_minimal, 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.file import File +from .._base_client import make_request_options +from ..types.list_files_response import ListFilesResponse +from ..types.delete_file_response import DeleteFileResponse + +__all__ = ["FilesResource", "AsyncFilesResource"] + + +class FilesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return FilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return FilesResourceWithStreamingResponse(self) + + def create( + self, + *, + file: FileTypes, + purpose: Literal["assistants"], + # 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, + ) -> File: + """Upload a file that can be used across various endpoints. + + The file upload should + be a multipart form request with: + + - file: The File object (not file name) to be uploaded. + - purpose: The intended purpose of the uploaded file. + + Args: + purpose: Valid purpose values for OpenAI Files API. + + 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 + """ + body = deepcopy_minimal( + { + "file": file, + "purpose": purpose, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/v1/openai/v1/files", + body=maybe_transform(body, file_create_params.FileCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=File, + ) + + def retrieve( + self, + file_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, + ) -> File: + """ + Returns information about a specific file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/openai/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=File, + ) + + def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + purpose: Literal["assistants"] | 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, + ) -> ListFilesResponse: + """ + Returns a list of files that belong to the user's organization. + + Args: + after: A cursor for use in pagination. `after` is an object ID that defines your place + in the list. For instance, if you make a list request and receive 100 objects, + ending with obj_foo, your subsequent call can include after=obj_foo in order to + fetch the next page of the list. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 10,000, and the default is 10,000. + + order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending + order and `desc` for descending order. + + purpose: Only return files with the given purpose. + + 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/openai/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "limit": limit, + "order": order, + "purpose": purpose, + }, + file_list_params.FileListParams, + ), + ), + cast_to=ListFilesResponse, + ) + + def delete( + self, + file_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, + ) -> DeleteFileResponse: + """ + Delete a file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._delete( + f"/v1/openai/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeleteFileResponse, + ) + + def content( + self, + file_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, + ) -> object: + """ + Returns the contents of the specified file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/v1/openai/v1/files/{file_id}/content", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class AsyncFilesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return AsyncFilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return AsyncFilesResourceWithStreamingResponse(self) + + async def create( + self, + *, + file: FileTypes, + purpose: Literal["assistants"], + # 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, + ) -> File: + """Upload a file that can be used across various endpoints. + + The file upload should + be a multipart form request with: + + - file: The File object (not file name) to be uploaded. + - purpose: The intended purpose of the uploaded file. + + Args: + purpose: Valid purpose values for OpenAI Files API. + + 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 + """ + body = deepcopy_minimal( + { + "file": file, + "purpose": purpose, + } + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/v1/openai/v1/files", + body=await async_maybe_transform(body, file_create_params.FileCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=File, + ) + + async def retrieve( + self, + file_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, + ) -> File: + """ + Returns information about a specific file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/openai/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=File, + ) + + async def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + purpose: Literal["assistants"] | 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, + ) -> ListFilesResponse: + """ + Returns a list of files that belong to the user's organization. + + Args: + after: A cursor for use in pagination. `after` is an object ID that defines your place + in the list. For instance, if you make a list request and receive 100 objects, + ending with obj_foo, your subsequent call can include after=obj_foo in order to + fetch the next page of the list. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 10,000, and the default is 10,000. + + order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending + order and `desc` for descending order. + + purpose: Only return files with the given purpose. + + 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/openai/v1/files", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "limit": limit, + "order": order, + "purpose": purpose, + }, + file_list_params.FileListParams, + ), + ), + cast_to=ListFilesResponse, + ) + + async def delete( + self, + file_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, + ) -> DeleteFileResponse: + """ + Delete a file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._delete( + f"/v1/openai/v1/files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeleteFileResponse, + ) + + async def content( + self, + file_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, + ) -> object: + """ + Returns the contents of the specified file. + + Args: + 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 + """ + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/v1/openai/v1/files/{file_id}/content", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class FilesResourceWithRawResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.create = to_raw_response_wrapper( + files.create, + ) + self.retrieve = to_raw_response_wrapper( + files.retrieve, + ) + self.list = to_raw_response_wrapper( + files.list, + ) + self.delete = to_raw_response_wrapper( + files.delete, + ) + self.content = to_raw_response_wrapper( + files.content, + ) + + +class AsyncFilesResourceWithRawResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.create = async_to_raw_response_wrapper( + files.create, + ) + self.retrieve = async_to_raw_response_wrapper( + files.retrieve, + ) + self.list = async_to_raw_response_wrapper( + files.list, + ) + self.delete = async_to_raw_response_wrapper( + files.delete, + ) + self.content = async_to_raw_response_wrapper( + files.content, + ) + + +class FilesResourceWithStreamingResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.create = to_streamed_response_wrapper( + files.create, + ) + self.retrieve = to_streamed_response_wrapper( + files.retrieve, + ) + self.list = to_streamed_response_wrapper( + files.list, + ) + self.delete = to_streamed_response_wrapper( + files.delete, + ) + self.content = to_streamed_response_wrapper( + files.content, + ) + + +class AsyncFilesResourceWithStreamingResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.create = async_to_streamed_response_wrapper( + files.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + files.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + files.list, + ) + self.delete = async_to_streamed_response_wrapper( + files.delete, + ) + self.content = async_to_streamed_response_wrapper( + files.content, + ) diff --git a/src/llama_stack_client/resources/responses/__init__.py b/src/llama_stack_client/resources/responses/__init__.py new file mode 100644 index 00000000..230ef765 --- /dev/null +++ b/src/llama_stack_client/resources/responses/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .responses import ( + ResponsesResource, + AsyncResponsesResource, + ResponsesResourceWithRawResponse, + AsyncResponsesResourceWithRawResponse, + ResponsesResourceWithStreamingResponse, + AsyncResponsesResourceWithStreamingResponse, +) +from .input_items import ( + InputItemsResource, + AsyncInputItemsResource, + InputItemsResourceWithRawResponse, + AsyncInputItemsResourceWithRawResponse, + InputItemsResourceWithStreamingResponse, + AsyncInputItemsResourceWithStreamingResponse, +) + +__all__ = [ + "InputItemsResource", + "AsyncInputItemsResource", + "InputItemsResourceWithRawResponse", + "AsyncInputItemsResourceWithRawResponse", + "InputItemsResourceWithStreamingResponse", + "AsyncInputItemsResourceWithStreamingResponse", + "ResponsesResource", + "AsyncResponsesResource", + "ResponsesResourceWithRawResponse", + "AsyncResponsesResourceWithRawResponse", + "ResponsesResourceWithStreamingResponse", + "AsyncResponsesResourceWithStreamingResponse", +] diff --git a/src/llama_stack_client/resources/responses/input_items.py b/src/llama_stack_client/resources/responses/input_items.py new file mode 100644 index 00000000..5379ad4d --- /dev/null +++ b/src/llama_stack_client/resources/responses/input_items.py @@ -0,0 +1,226 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +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 ..._base_client import make_request_options +from ...types.responses import input_item_list_params +from ...types.responses.input_item_list_response import InputItemListResponse + +__all__ = ["InputItemsResource", "AsyncInputItemsResource"] + + +class InputItemsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> InputItemsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return InputItemsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> InputItemsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return InputItemsResourceWithStreamingResponse(self) + + def list( + self, + response_id: str, + *, + after: str | NotGiven = NOT_GIVEN, + before: str | NotGiven = NOT_GIVEN, + include: List[str] | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | 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, + ) -> InputItemListResponse: + """ + List input items for a given OpenAI response. + + Args: + after: An item ID to list items after, used for pagination. + + before: An item ID to list items before, used for pagination. + + include: Additional fields to include in the response. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the default is 20. + + order: The order to return the input items in. Default is desc. + + 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 + """ + if not response_id: + raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") + return self._get( + f"/v1/openai/v1/responses/{response_id}/input_items", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "before": before, + "include": include, + "limit": limit, + "order": order, + }, + input_item_list_params.InputItemListParams, + ), + ), + cast_to=InputItemListResponse, + ) + + +class AsyncInputItemsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncInputItemsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return AsyncInputItemsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncInputItemsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return AsyncInputItemsResourceWithStreamingResponse(self) + + async def list( + self, + response_id: str, + *, + after: str | NotGiven = NOT_GIVEN, + before: str | NotGiven = NOT_GIVEN, + include: List[str] | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | 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, + ) -> InputItemListResponse: + """ + List input items for a given OpenAI response. + + Args: + after: An item ID to list items after, used for pagination. + + before: An item ID to list items before, used for pagination. + + include: Additional fields to include in the response. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the default is 20. + + order: The order to return the input items in. Default is desc. + + 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 + """ + if not response_id: + raise ValueError(f"Expected a non-empty value for `response_id` but received {response_id!r}") + return await self._get( + f"/v1/openai/v1/responses/{response_id}/input_items", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "before": before, + "include": include, + "limit": limit, + "order": order, + }, + input_item_list_params.InputItemListParams, + ), + ), + cast_to=InputItemListResponse, + ) + + +class InputItemsResourceWithRawResponse: + def __init__(self, input_items: InputItemsResource) -> None: + self._input_items = input_items + + self.list = to_raw_response_wrapper( + input_items.list, + ) + + +class AsyncInputItemsResourceWithRawResponse: + def __init__(self, input_items: AsyncInputItemsResource) -> None: + self._input_items = input_items + + self.list = async_to_raw_response_wrapper( + input_items.list, + ) + + +class InputItemsResourceWithStreamingResponse: + def __init__(self, input_items: InputItemsResource) -> None: + self._input_items = input_items + + self.list = to_streamed_response_wrapper( + input_items.list, + ) + + +class AsyncInputItemsResourceWithStreamingResponse: + def __init__(self, input_items: AsyncInputItemsResource) -> None: + self._input_items = input_items + + self.list = async_to_streamed_response_wrapper( + input_items.list, + ) diff --git a/src/llama_stack_client/resources/responses.py b/src/llama_stack_client/resources/responses/responses.py similarity index 73% rename from src/llama_stack_client/resources/responses.py rename to src/llama_stack_client/resources/responses/responses.py index bb7fcdc6..ba147335 100644 --- a/src/llama_stack_client/resources/responses.py +++ b/src/llama_stack_client/resources/responses/responses.py @@ -7,26 +7,39 @@ import httpx -from ..types import response_create_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._utils import required_args, maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( +from ...types import response_list_params, response_create_params +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import required_args, 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 .._streaming import Stream, AsyncStream -from .._base_client import make_request_options -from ..types.response_object import ResponseObject -from ..types.response_object_stream import ResponseObjectStream +from .input_items import ( + InputItemsResource, + AsyncInputItemsResource, + InputItemsResourceWithRawResponse, + AsyncInputItemsResourceWithRawResponse, + InputItemsResourceWithStreamingResponse, + AsyncInputItemsResourceWithStreamingResponse, +) +from ..._streaming import Stream, AsyncStream +from ..._base_client import make_request_options +from ...types.response_object import ResponseObject +from ...types.response_list_response import ResponseListResponse +from ...types.response_object_stream import ResponseObjectStream __all__ = ["ResponsesResource", "AsyncResponsesResource"] class ResponsesResource(SyncAPIResource): + @cached_property + def input_items(self) -> InputItemsResource: + return InputItemsResource(self._client) + @cached_property def with_raw_response(self) -> ResponsesResourceWithRawResponse: """ @@ -53,10 +66,12 @@ def create( input: Union[str, Iterable[response_create_params.InputUnionMember1]], model: str, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, stream: Literal[False] | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -95,9 +110,11 @@ def create( model: str, stream: Literal[True], instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -136,9 +153,11 @@ def create( model: str, stream: bool, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -176,10 +195,12 @@ def create( input: Union[str, Iterable[response_create_params.InputUnionMember1]], model: str, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, stream: Literal[False] | Literal[True] | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -195,10 +216,12 @@ def create( "input": input, "model": model, "instructions": instructions, + "max_infer_iters": max_infer_iters, "previous_response_id": previous_response_id, "store": store, "stream": stream, "temperature": temperature, + "text": text, "tools": tools, }, response_create_params.ResponseCreateParamsStreaming @@ -246,8 +269,66 @@ def retrieve( cast_to=ResponseObject, ) + def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + model: str | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | 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, + ) -> ResponseListResponse: + """ + List all OpenAI responses. + + Args: + after: The ID of the last response to return. + + limit: The number of responses to return. + + model: The model to filter responses by. + + order: The order to sort responses by when sorted by created_at ('asc' or 'desc'). + + 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/openai/v1/responses", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "limit": limit, + "model": model, + "order": order, + }, + response_list_params.ResponseListParams, + ), + ), + cast_to=ResponseListResponse, + ) + class AsyncResponsesResource(AsyncAPIResource): + @cached_property + def input_items(self) -> AsyncInputItemsResource: + return AsyncInputItemsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncResponsesResourceWithRawResponse: """ @@ -274,10 +355,12 @@ async def create( input: Union[str, Iterable[response_create_params.InputUnionMember1]], model: str, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, stream: Literal[False] | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -316,9 +399,11 @@ async def create( model: str, stream: Literal[True], instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -357,9 +442,11 @@ async def create( model: str, stream: bool, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -397,10 +484,12 @@ async def create( input: Union[str, Iterable[response_create_params.InputUnionMember1]], model: str, instructions: str | NotGiven = NOT_GIVEN, + max_infer_iters: int | NotGiven = NOT_GIVEN, previous_response_id: str | NotGiven = NOT_GIVEN, store: bool | NotGiven = NOT_GIVEN, stream: Literal[False] | Literal[True] | NotGiven = NOT_GIVEN, temperature: float | NotGiven = NOT_GIVEN, + text: response_create_params.Text | NotGiven = NOT_GIVEN, tools: Iterable[response_create_params.Tool] | 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. @@ -416,10 +505,12 @@ async def create( "input": input, "model": model, "instructions": instructions, + "max_infer_iters": max_infer_iters, "previous_response_id": previous_response_id, "store": store, "stream": stream, "temperature": temperature, + "text": text, "tools": tools, }, response_create_params.ResponseCreateParamsStreaming @@ -467,6 +558,60 @@ async def retrieve( cast_to=ResponseObject, ) + async def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + model: str | NotGiven = NOT_GIVEN, + order: Literal["asc", "desc"] | 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, + ) -> ResponseListResponse: + """ + List all OpenAI responses. + + Args: + after: The ID of the last response to return. + + limit: The number of responses to return. + + model: The model to filter responses by. + + order: The order to sort responses by when sorted by created_at ('asc' or 'desc'). + + 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/openai/v1/responses", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "limit": limit, + "model": model, + "order": order, + }, + response_list_params.ResponseListParams, + ), + ), + cast_to=ResponseListResponse, + ) + class ResponsesResourceWithRawResponse: def __init__(self, responses: ResponsesResource) -> None: @@ -478,6 +623,13 @@ def __init__(self, responses: ResponsesResource) -> None: self.retrieve = to_raw_response_wrapper( responses.retrieve, ) + self.list = to_raw_response_wrapper( + responses.list, + ) + + @cached_property + def input_items(self) -> InputItemsResourceWithRawResponse: + return InputItemsResourceWithRawResponse(self._responses.input_items) class AsyncResponsesResourceWithRawResponse: @@ -490,6 +642,13 @@ def __init__(self, responses: AsyncResponsesResource) -> None: self.retrieve = async_to_raw_response_wrapper( responses.retrieve, ) + self.list = async_to_raw_response_wrapper( + responses.list, + ) + + @cached_property + def input_items(self) -> AsyncInputItemsResourceWithRawResponse: + return AsyncInputItemsResourceWithRawResponse(self._responses.input_items) class ResponsesResourceWithStreamingResponse: @@ -502,6 +661,13 @@ def __init__(self, responses: ResponsesResource) -> None: self.retrieve = to_streamed_response_wrapper( responses.retrieve, ) + self.list = to_streamed_response_wrapper( + responses.list, + ) + + @cached_property + def input_items(self) -> InputItemsResourceWithStreamingResponse: + return InputItemsResourceWithStreamingResponse(self._responses.input_items) class AsyncResponsesResourceWithStreamingResponse: @@ -514,3 +680,10 @@ def __init__(self, responses: AsyncResponsesResource) -> None: self.retrieve = async_to_streamed_response_wrapper( responses.retrieve, ) + self.list = async_to_streamed_response_wrapper( + responses.list, + ) + + @cached_property + def input_items(self) -> AsyncInputItemsResourceWithStreamingResponse: + return AsyncInputItemsResourceWithStreamingResponse(self._responses.input_items) diff --git a/src/llama_stack_client/resources/vector_io.py b/src/llama_stack_client/resources/vector_io.py index 7ec4691e..3d985e71 100644 --- a/src/llama_stack_client/resources/vector_io.py +++ b/src/llama_stack_client/resources/vector_io.py @@ -57,12 +57,17 @@ def insert( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """ - Insert chunks into a vector database. + """Insert chunks into a vector database. Args: chunks: The chunks to insert. + Each `Chunk` should contain content which can be + interleaved text, images, or other types. `metadata`: `dict[str, Any]` and + `embedding`: `List[float]` are optional. If `metadata` is provided, you + configure how Llama Stack formats the chunk during generation. If `embedding` is + not provided, it will be computed later. + vector_db_id: The identifier of the vector database to insert the chunks into. ttl_seconds: The time to live of the chunks. @@ -173,12 +178,17 @@ async def insert( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: - """ - Insert chunks into a vector database. + """Insert chunks into a vector database. Args: chunks: The chunks to insert. + Each `Chunk` should contain content which can be + interleaved text, images, or other types. `metadata`: `dict[str, Any]` and + `embedding`: `List[float]` are optional. If `metadata` is provided, you + configure how Llama Stack formats the chunk during generation. If `embedding` is + not provided, it will be computed later. + vector_db_id: The identifier of the vector database to insert the chunks into. ttl_seconds: The time to live of the chunks. diff --git a/src/llama_stack_client/resources/vector_stores.py b/src/llama_stack_client/resources/vector_stores.py new file mode 100644 index 00000000..f7df15c9 --- /dev/null +++ b/src/llama_stack_client/resources/vector_stores.py @@ -0,0 +1,785 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Union, Iterable + +import httpx + +from ..types import ( + vector_store_list_params, + vector_store_create_params, + vector_store_search_params, + vector_store_update_params, +) +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 .._base_client import make_request_options +from ..types.vector_store import VectorStore +from ..types.list_vector_stores_response import ListVectorStoresResponse +from ..types.vector_store_delete_response import VectorStoreDeleteResponse +from ..types.vector_store_search_response import VectorStoreSearchResponse + +__all__ = ["VectorStoresResource", "AsyncVectorStoresResource"] + + +class VectorStoresResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> VectorStoresResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return VectorStoresResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> VectorStoresResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return VectorStoresResourceWithStreamingResponse(self) + + def create( + self, + *, + name: str, + chunking_strategy: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + embedding_dimension: int | NotGiven = NOT_GIVEN, + embedding_model: str | NotGiven = NOT_GIVEN, + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + file_ids: List[str] | NotGiven = NOT_GIVEN, + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + provider_id: str | NotGiven = NOT_GIVEN, + provider_vector_db_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, + ) -> VectorStore: + """ + Creates a vector store. + + Args: + name: A name for the vector store. + + chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` + strategy. + + embedding_dimension: The dimension of the embedding vectors (default: 384). + + embedding_model: The embedding model to use for this vector store. + + expires_after: The expiration policy for a vector store. + + file_ids: A list of File IDs that the vector store should use. Useful for tools like + `file_search` that can access files. + + metadata: Set of 16 key-value pairs that can be attached to an object. + + provider_id: The ID of the provider to use for this vector store. + + provider_vector_db_id: The provider-specific vector database 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._post( + "/v1/openai/v1/vector_stores", + body=maybe_transform( + { + "name": name, + "chunking_strategy": chunking_strategy, + "embedding_dimension": embedding_dimension, + "embedding_model": embedding_model, + "expires_after": expires_after, + "file_ids": file_ids, + "metadata": metadata, + "provider_id": provider_id, + "provider_vector_db_id": provider_vector_db_id, + }, + vector_store_create_params.VectorStoreCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + def retrieve( + self, + vector_store_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, + ) -> VectorStore: + """ + Retrieves a vector store. + + Args: + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return self._get( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + def update( + self, + vector_store_id: str, + *, + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + name: 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, + ) -> VectorStore: + """ + Updates a vector store. + + Args: + expires_after: The expiration policy for a vector store. + + metadata: Set of 16 key-value pairs that can be attached to an object. + + name: The name of the vector store. + + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return self._post( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + body=maybe_transform( + { + "expires_after": expires_after, + "metadata": metadata, + "name": name, + }, + vector_store_update_params.VectorStoreUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + before: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: 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, + ) -> ListVectorStoresResponse: + """Returns a list of vector stores. + + Args: + after: A cursor for use in pagination. + + `after` is an object ID that defines your place + in the list. + + before: A cursor for use in pagination. `before` is an object ID that defines your place + in the list. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the default is 20. + + order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending + order and `desc` for descending order. + + 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/openai/v1/vector_stores", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "before": before, + "limit": limit, + "order": order, + }, + vector_store_list_params.VectorStoreListParams, + ), + ), + cast_to=ListVectorStoresResponse, + ) + + def delete( + self, + vector_store_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, + ) -> VectorStoreDeleteResponse: + """ + Delete a vector store. + + Args: + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return self._delete( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStoreDeleteResponse, + ) + + def search( + self, + vector_store_id: str, + *, + query: Union[str, List[str]], + filters: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + max_num_results: int | NotGiven = NOT_GIVEN, + ranking_options: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + rewrite_query: bool | 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, + ) -> VectorStoreSearchResponse: + """Search for chunks in a vector store. + + Searches a vector store for relevant chunks + based on a query and optional file attribute filters. + + Args: + query: The query string or array for performing the search. + + filters: Filters based on file attributes to narrow the search results. + + max_num_results: Maximum number of results to return (1 to 50 inclusive, default 10). + + ranking_options: Ranking options for fine-tuning the search results. + + rewrite_query: Whether to rewrite the natural language query for vector search (default false) + + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return self._post( + f"/v1/openai/v1/vector_stores/{vector_store_id}/search", + body=maybe_transform( + { + "query": query, + "filters": filters, + "max_num_results": max_num_results, + "ranking_options": ranking_options, + "rewrite_query": rewrite_query, + }, + vector_store_search_params.VectorStoreSearchParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStoreSearchResponse, + ) + + +class AsyncVectorStoresResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncVectorStoresResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#accessing-raw-response-data-eg-headers + """ + return AsyncVectorStoresResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncVectorStoresResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/stainless-sdks/llama-stack-python#with_streaming_response + """ + return AsyncVectorStoresResourceWithStreamingResponse(self) + + async def create( + self, + *, + name: str, + chunking_strategy: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + embedding_dimension: int | NotGiven = NOT_GIVEN, + embedding_model: str | NotGiven = NOT_GIVEN, + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + file_ids: List[str] | NotGiven = NOT_GIVEN, + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + provider_id: str | NotGiven = NOT_GIVEN, + provider_vector_db_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, + ) -> VectorStore: + """ + Creates a vector store. + + Args: + name: A name for the vector store. + + chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto` + strategy. + + embedding_dimension: The dimension of the embedding vectors (default: 384). + + embedding_model: The embedding model to use for this vector store. + + expires_after: The expiration policy for a vector store. + + file_ids: A list of File IDs that the vector store should use. Useful for tools like + `file_search` that can access files. + + metadata: Set of 16 key-value pairs that can be attached to an object. + + provider_id: The ID of the provider to use for this vector store. + + provider_vector_db_id: The provider-specific vector database 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._post( + "/v1/openai/v1/vector_stores", + body=await async_maybe_transform( + { + "name": name, + "chunking_strategy": chunking_strategy, + "embedding_dimension": embedding_dimension, + "embedding_model": embedding_model, + "expires_after": expires_after, + "file_ids": file_ids, + "metadata": metadata, + "provider_id": provider_id, + "provider_vector_db_id": provider_vector_db_id, + }, + vector_store_create_params.VectorStoreCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + async def retrieve( + self, + vector_store_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, + ) -> VectorStore: + """ + Retrieves a vector store. + + Args: + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return await self._get( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + async def update( + self, + vector_store_id: str, + *, + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + name: 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, + ) -> VectorStore: + """ + Updates a vector store. + + Args: + expires_after: The expiration policy for a vector store. + + metadata: Set of 16 key-value pairs that can be attached to an object. + + name: The name of the vector store. + + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return await self._post( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + body=await async_maybe_transform( + { + "expires_after": expires_after, + "metadata": metadata, + "name": name, + }, + vector_store_update_params.VectorStoreUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStore, + ) + + async def list( + self, + *, + after: str | NotGiven = NOT_GIVEN, + before: str | NotGiven = NOT_GIVEN, + limit: int | NotGiven = NOT_GIVEN, + order: 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, + ) -> ListVectorStoresResponse: + """Returns a list of vector stores. + + Args: + after: A cursor for use in pagination. + + `after` is an object ID that defines your place + in the list. + + before: A cursor for use in pagination. `before` is an object ID that defines your place + in the list. + + limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the default is 20. + + order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending + order and `desc` for descending order. + + 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/openai/v1/vector_stores", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "before": before, + "limit": limit, + "order": order, + }, + vector_store_list_params.VectorStoreListParams, + ), + ), + cast_to=ListVectorStoresResponse, + ) + + async def delete( + self, + vector_store_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, + ) -> VectorStoreDeleteResponse: + """ + Delete a vector store. + + Args: + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return await self._delete( + f"/v1/openai/v1/vector_stores/{vector_store_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStoreDeleteResponse, + ) + + async def search( + self, + vector_store_id: str, + *, + query: Union[str, List[str]], + filters: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + max_num_results: int | NotGiven = NOT_GIVEN, + ranking_options: Dict[str, Union[bool, float, str, Iterable[object], object, None]] | NotGiven = NOT_GIVEN, + rewrite_query: bool | 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, + ) -> VectorStoreSearchResponse: + """Search for chunks in a vector store. + + Searches a vector store for relevant chunks + based on a query and optional file attribute filters. + + Args: + query: The query string or array for performing the search. + + filters: Filters based on file attributes to narrow the search results. + + max_num_results: Maximum number of results to return (1 to 50 inclusive, default 10). + + ranking_options: Ranking options for fine-tuning the search results. + + rewrite_query: Whether to rewrite the natural language query for vector search (default false) + + 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 + """ + if not vector_store_id: + raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + return await self._post( + f"/v1/openai/v1/vector_stores/{vector_store_id}/search", + body=await async_maybe_transform( + { + "query": query, + "filters": filters, + "max_num_results": max_num_results, + "ranking_options": ranking_options, + "rewrite_query": rewrite_query, + }, + vector_store_search_params.VectorStoreSearchParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=VectorStoreSearchResponse, + ) + + +class VectorStoresResourceWithRawResponse: + def __init__(self, vector_stores: VectorStoresResource) -> None: + self._vector_stores = vector_stores + + self.create = to_raw_response_wrapper( + vector_stores.create, + ) + self.retrieve = to_raw_response_wrapper( + vector_stores.retrieve, + ) + self.update = to_raw_response_wrapper( + vector_stores.update, + ) + self.list = to_raw_response_wrapper( + vector_stores.list, + ) + self.delete = to_raw_response_wrapper( + vector_stores.delete, + ) + self.search = to_raw_response_wrapper( + vector_stores.search, + ) + + +class AsyncVectorStoresResourceWithRawResponse: + def __init__(self, vector_stores: AsyncVectorStoresResource) -> None: + self._vector_stores = vector_stores + + self.create = async_to_raw_response_wrapper( + vector_stores.create, + ) + self.retrieve = async_to_raw_response_wrapper( + vector_stores.retrieve, + ) + self.update = async_to_raw_response_wrapper( + vector_stores.update, + ) + self.list = async_to_raw_response_wrapper( + vector_stores.list, + ) + self.delete = async_to_raw_response_wrapper( + vector_stores.delete, + ) + self.search = async_to_raw_response_wrapper( + vector_stores.search, + ) + + +class VectorStoresResourceWithStreamingResponse: + def __init__(self, vector_stores: VectorStoresResource) -> None: + self._vector_stores = vector_stores + + self.create = to_streamed_response_wrapper( + vector_stores.create, + ) + self.retrieve = to_streamed_response_wrapper( + vector_stores.retrieve, + ) + self.update = to_streamed_response_wrapper( + vector_stores.update, + ) + self.list = to_streamed_response_wrapper( + vector_stores.list, + ) + self.delete = to_streamed_response_wrapper( + vector_stores.delete, + ) + self.search = to_streamed_response_wrapper( + vector_stores.search, + ) + + +class AsyncVectorStoresResourceWithStreamingResponse: + def __init__(self, vector_stores: AsyncVectorStoresResource) -> None: + self._vector_stores = vector_stores + + self.create = async_to_streamed_response_wrapper( + vector_stores.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + vector_stores.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + vector_stores.update, + ) + self.list = async_to_streamed_response_wrapper( + vector_stores.list, + ) + self.delete = async_to_streamed_response_wrapper( + vector_stores.delete, + ) + self.search = async_to_streamed_response_wrapper( + vector_stores.search, + ) diff --git a/src/llama_stack_client/types/__init__.py b/src/llama_stack_client/types/__init__.py index 815f95a1..a8316ddc 100644 --- a/src/llama_stack_client/types/__init__.py +++ b/src/llama_stack_client/types/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations from .job import Job as Job +from .file import File as File from .tool import Tool as Tool from .model import Model as Model from .trace import Trace as Trace @@ -40,6 +41,7 @@ from .tool_group import ToolGroup as ToolGroup from .event_param import EventParam as EventParam from .health_info import HealthInfo as HealthInfo +from .vector_store import VectorStore as VectorStore from .version_info import VersionInfo as VersionInfo from .provider_info import ProviderInfo as ProviderInfo from .tool_response import ToolResponse as ToolResponse @@ -47,27 +49,32 @@ from .tool_def_param import ToolDefParam as ToolDefParam from .response_object import ResponseObject as ResponseObject from .token_log_probs import TokenLogProbs as TokenLogProbs +from .file_list_params import FileListParams as FileListParams from .shield_call_step import ShieldCallStep as ShieldCallStep from .span_with_status import SpanWithStatus as SpanWithStatus from .tool_list_params import ToolListParams as ToolListParams from .evaluate_response import EvaluateResponse as EvaluateResponse from .post_training_job import PostTrainingJob as PostTrainingJob from .scoring_fn_params import ScoringFnParams as ScoringFnParams +from .file_create_params import FileCreateParams as FileCreateParams from .tool_list_response import ToolListResponse as ToolListResponse from .agent_create_params import AgentCreateParams as AgentCreateParams from .completion_response import CompletionResponse as CompletionResponse from .embeddings_response import EmbeddingsResponse as EmbeddingsResponse +from .list_files_response import ListFilesResponse as ListFilesResponse from .list_tools_response import ListToolsResponse as ListToolsResponse from .model_list_response import ModelListResponse as ModelListResponse from .route_list_response import RouteListResponse as RouteListResponse from .run_shield_response import RunShieldResponse as RunShieldResponse from .tool_execution_step import ToolExecutionStep as ToolExecutionStep from .tool_response_param import ToolResponseParam as ToolResponseParam +from .delete_file_response import DeleteFileResponse as DeleteFileResponse from .eval_candidate_param import EvalCandidateParam as EvalCandidateParam from .eval_run_eval_params import EvalRunEvalParams as EvalRunEvalParams from .list_models_response import ListModelsResponse as ListModelsResponse from .list_routes_response import ListRoutesResponse as ListRoutesResponse from .query_spans_response import QuerySpansResponse as QuerySpansResponse +from .response_list_params import ResponseListParams as ResponseListParams from .scoring_score_params import ScoringScoreParams as ScoringScoreParams from .shield_list_response import ShieldListResponse as ShieldListResponse from .agent_create_response import AgentCreateResponse as AgentCreateResponse @@ -83,6 +90,7 @@ from .list_datasets_response import ListDatasetsResponse as ListDatasetsResponse from .provider_list_response import ProviderListResponse as ProviderListResponse from .response_create_params import ResponseCreateParams as ResponseCreateParams +from .response_list_response import ResponseListResponse as ResponseListResponse from .response_object_stream import ResponseObjectStream as ResponseObjectStream from .scoring_score_response import ScoringScoreResponse as ScoringScoreResponse from .shield_register_params import ShieldRegisterParams as ShieldRegisterParams @@ -91,6 +99,7 @@ from .benchmark_list_response import BenchmarkListResponse as BenchmarkListResponse from .dataset_iterrows_params import DatasetIterrowsParams as DatasetIterrowsParams from .dataset_register_params import DatasetRegisterParams as DatasetRegisterParams +from .embedding_create_params import EmbeddingCreateParams as EmbeddingCreateParams from .list_providers_response import ListProvidersResponse as ListProvidersResponse from .scoring_fn_params_param import ScoringFnParamsParam as ScoringFnParamsParam from .toolgroup_list_response import ToolgroupListResponse as ToolgroupListResponse @@ -100,6 +109,7 @@ from .list_benchmarks_response import ListBenchmarksResponse as ListBenchmarksResponse from .list_vector_dbs_response import ListVectorDBsResponse as ListVectorDBsResponse from .safety_run_shield_params import SafetyRunShieldParams as SafetyRunShieldParams +from .vector_store_list_params import VectorStoreListParams as VectorStoreListParams from .benchmark_register_params import BenchmarkRegisterParams as BenchmarkRegisterParams from .dataset_iterrows_response import DatasetIterrowsResponse as DatasetIterrowsResponse from .dataset_register_response import DatasetRegisterResponse as DatasetRegisterResponse @@ -112,13 +122,19 @@ from .eval_run_eval_alpha_params import EvalRunEvalAlphaParams as EvalRunEvalAlphaParams from .scoring_score_batch_params import ScoringScoreBatchParams as ScoringScoreBatchParams from .telemetry_log_event_params import TelemetryLogEventParams as TelemetryLogEventParams +from .vector_store_create_params import VectorStoreCreateParams as VectorStoreCreateParams +from .vector_store_search_params import VectorStoreSearchParams as VectorStoreSearchParams +from .vector_store_update_params import VectorStoreUpdateParams as VectorStoreUpdateParams from .inference_completion_params import InferenceCompletionParams as InferenceCompletionParams from .inference_embeddings_params import InferenceEmbeddingsParams as InferenceEmbeddingsParams +from .list_vector_stores_response import ListVectorStoresResponse as ListVectorStoresResponse from .telemetry_get_span_response import TelemetryGetSpanResponse as TelemetryGetSpanResponse from .vector_db_register_response import VectorDBRegisterResponse as VectorDBRegisterResponse from .vector_db_retrieve_response import VectorDBRetrieveResponse as VectorDBRetrieveResponse from .scoring_score_batch_response import ScoringScoreBatchResponse as ScoringScoreBatchResponse from .telemetry_query_spans_params import TelemetryQuerySpansParams as TelemetryQuerySpansParams +from .vector_store_delete_response import VectorStoreDeleteResponse as VectorStoreDeleteResponse +from .vector_store_search_response import VectorStoreSearchResponse as VectorStoreSearchResponse from .telemetry_query_traces_params import TelemetryQueryTracesParams as TelemetryQueryTracesParams from .scoring_function_list_response import ScoringFunctionListResponse as ScoringFunctionListResponse from .telemetry_get_span_tree_params import TelemetryGetSpanTreeParams as TelemetryGetSpanTreeParams diff --git a/src/llama_stack_client/types/delete_file_response.py b/src/llama_stack_client/types/delete_file_response.py new file mode 100644 index 00000000..2188556f --- /dev/null +++ b/src/llama_stack_client/types/delete_file_response.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DeleteFileResponse"] + + +class DeleteFileResponse(BaseModel): + id: str + """The file identifier that was deleted""" + + deleted: bool + """Whether the file was successfully deleted""" + + object: Literal["file"] + """The object type, which is always "file" """ diff --git a/src/llama_stack_client/types/embedding_create_params.py b/src/llama_stack_client/types/embedding_create_params.py new file mode 100644 index 00000000..c87096eb --- /dev/null +++ b/src/llama_stack_client/types/embedding_create_params.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union +from typing_extensions import Required, TypedDict + +__all__ = ["EmbeddingCreateParams"] + + +class EmbeddingCreateParams(TypedDict, total=False): + input: Required[Union[str, List[str]]] + """Input text to embed, encoded as a string or array of strings. + + To embed multiple inputs in a single request, pass an array of strings. + """ + + model: Required[str] + """The identifier of the model to use. + + The model must be an embedding model registered with Llama Stack and available + via the /models endpoint. + """ + + dimensions: int + """(Optional) The number of dimensions the resulting output embeddings should have. + + Only supported in text-embedding-3 and later models. + """ + + encoding_format: str + """(Optional) The format to return the embeddings in. + + Can be either "float" or "base64". Defaults to "float". + """ + + user: str + """ + (Optional) A unique identifier representing your end-user, which can help OpenAI + to monitor and detect abuse. + """ diff --git a/src/llama_stack_client/types/embeddings_response.py b/src/llama_stack_client/types/embeddings_response.py index f36c6b97..6d37d207 100644 --- a/src/llama_stack_client/types/embeddings_response.py +++ b/src/llama_stack_client/types/embeddings_response.py @@ -1,16 +1,44 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Union +from typing_extensions import Literal from .._models import BaseModel -__all__ = ["EmbeddingsResponse"] +__all__ = ["EmbeddingsResponse", "Data", "Usage"] + + +class Data(BaseModel): + embedding: Union[List[float], str] + """ + The embedding vector as a list of floats (when encoding_format="float") or as a + base64-encoded string (when encoding_format="base64") + """ + + index: int + """The index of the embedding in the input list""" + + object: Literal["embedding"] + """The object type, which will be "embedding" """ + + +class Usage(BaseModel): + prompt_tokens: int + """The number of tokens in the input""" + + total_tokens: int + """The total number of tokens used""" class EmbeddingsResponse(BaseModel): - embeddings: List[List[float]] - """List of embedding vectors, one per input content. + data: List[Data] + """List of embedding data objects""" - Each embedding is a list of floats. The dimensionality of the embedding is - model-specific; you can check model metadata using /models/{model_id} - """ + model: str + """The model that was used to generate the embeddings""" + + object: Literal["list"] + """The object type, which will be "list" """ + + usage: Usage + """Usage information""" diff --git a/src/llama_stack_client/types/file.py b/src/llama_stack_client/types/file.py new file mode 100644 index 00000000..74ead6b7 --- /dev/null +++ b/src/llama_stack_client/types/file.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["File"] + + +class File(BaseModel): + id: str + """The file identifier, which can be referenced in the API endpoints""" + + bytes: int + """The size of the file, in bytes""" + + created_at: int + """The Unix timestamp (in seconds) for when the file was created""" + + expires_at: int + """The Unix timestamp (in seconds) for when the file expires""" + + filename: str + """The name of the file""" + + object: Literal["file"] + """The object type, which is always "file" """ + + purpose: Literal["assistants"] + """The intended purpose of the file""" diff --git a/src/llama_stack_client/types/file_create_params.py b/src/llama_stack_client/types/file_create_params.py new file mode 100644 index 00000000..8342aad2 --- /dev/null +++ b/src/llama_stack_client/types/file_create_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +from .._types import FileTypes + +__all__ = ["FileCreateParams"] + + +class FileCreateParams(TypedDict, total=False): + file: Required[FileTypes] + + purpose: Required[Literal["assistants"]] + """Valid purpose values for OpenAI Files API.""" diff --git a/src/llama_stack_client/types/file_list_params.py b/src/llama_stack_client/types/file_list_params.py new file mode 100644 index 00000000..3f7d6ed5 --- /dev/null +++ b/src/llama_stack_client/types/file_list_params.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["FileListParams"] + + +class FileListParams(TypedDict, total=False): + after: str + """A cursor for use in pagination. + + `after` is an object ID that defines your place in the list. For instance, if + you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the + list. + """ + + limit: int + """A limit on the number of objects to be returned. + + Limit can range between 1 and 10,000, and the default is 10,000. + """ + + order: Literal["asc", "desc"] + """Sort order by the `created_at` timestamp of the objects. + + `asc` for ascending order and `desc` for descending order. + """ + + purpose: Literal["assistants"] + """Only return files with the given purpose.""" diff --git a/src/llama_stack_client/types/list_files_response.py b/src/llama_stack_client/types/list_files_response.py new file mode 100644 index 00000000..cbb7d514 --- /dev/null +++ b/src/llama_stack_client/types/list_files_response.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import Literal + +from .file import File +from .._models import BaseModel + +__all__ = ["ListFilesResponse"] + + +class ListFilesResponse(BaseModel): + data: List[File] + """List of file objects""" + + first_id: str + + has_more: bool + + last_id: str + + object: Literal["list"] + """The object type, which is always "list" """ diff --git a/src/llama_stack_client/types/list_vector_stores_response.py b/src/llama_stack_client/types/list_vector_stores_response.py new file mode 100644 index 00000000..c79fd895 --- /dev/null +++ b/src/llama_stack_client/types/list_vector_stores_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .vector_store import VectorStore + +__all__ = ["ListVectorStoresResponse"] + + +class ListVectorStoresResponse(BaseModel): + data: List[VectorStore] + + has_more: bool + + object: str + + first_id: Optional[str] = None + + last_id: Optional[str] = None diff --git a/src/llama_stack_client/types/query_chunks_response.py b/src/llama_stack_client/types/query_chunks_response.py index d90e464e..f668ecac 100644 --- a/src/llama_stack_client/types/query_chunks_response.py +++ b/src/llama_stack_client/types/query_chunks_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Union +from typing import Dict, List, Union, Optional from .._models import BaseModel from .shared.interleaved_content import InterleavedContent @@ -10,9 +10,18 @@ class Chunk(BaseModel): content: InterleavedContent - """A image content item""" + """ + The content of the chunk, which can be interleaved text, images, or other types. + """ metadata: Dict[str, Union[bool, float, str, List[object], object, None]] + """ + Metadata associated with the chunk, such as document ID, source, or other + relevant information. + """ + + embedding: Optional[List[float]] = None + """Optional embedding for the chunk. If not provided, it will be computed later.""" class QueryChunksResponse(BaseModel): diff --git a/src/llama_stack_client/types/response_create_params.py b/src/llama_stack_client/types/response_create_params.py index 53cb6b62..7c0a2539 100644 --- a/src/llama_stack_client/types/response_create_params.py +++ b/src/llama_stack_client/types/response_create_params.py @@ -16,6 +16,8 @@ "InputUnionMember1OpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", "InputUnionMember1OpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", "InputUnionMember1OpenAIResponseMessageContentUnionMember2", + "Text", + "TextFormat", "Tool", "ToolOpenAIResponseInputToolWebSearch", "ToolOpenAIResponseInputToolFileSearch", @@ -40,6 +42,8 @@ class ResponseCreateParamsBase(TypedDict, total=False): instructions: str + max_infer_iters: int + previous_response_id: str """ (Optional) if specified, the new response will be a continuation of the previous @@ -51,6 +55,8 @@ class ResponseCreateParamsBase(TypedDict, total=False): temperature: float + text: Text + tools: Iterable[Tool] @@ -63,18 +69,18 @@ class InputUnionMember1OpenAIResponseOutputMessageWebSearchToolCall(TypedDict, t class InputUnionMember1OpenAIResponseOutputMessageFunctionToolCall(TypedDict, total=False): - id: Required[str] - arguments: Required[str] call_id: Required[str] name: Required[str] - status: Required[str] - type: Required[Literal["function_call"]] + id: str + + status: str + class InputUnionMember1OpenAIResponseInputFunctionToolCallOutput(TypedDict, total=False): call_id: Required[str] @@ -144,6 +150,34 @@ class InputUnionMember1OpenAIResponseMessage(TypedDict, total=False): ] +class TextFormat(TypedDict, total=False): + type: Required[Literal["text", "json_schema", "json_object"]] + """Must be "text", "json_schema", or "json_object" to identify the format type""" + + description: str + """(Optional) A description of the response format. Only used for json_schema.""" + + name: str + """The name of the response format. Only used for json_schema.""" + + schema: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """The JSON schema the response should conform to. + + In a Python SDK, this is often a `pydantic` model. Only used for json_schema. + """ + + strict: bool + """(Optional) Whether to strictly enforce the JSON schema. + + If true, the response must match the schema exactly. Only used for json_schema. + """ + + +class Text(TypedDict, total=False): + format: TextFormat + """Configuration for Responses API text format.""" + + class ToolOpenAIResponseInputToolWebSearch(TypedDict, total=False): type: Required[Literal["web_search", "web_search_preview_2025_03_11"]] diff --git a/src/llama_stack_client/types/response_list_params.py b/src/llama_stack_client/types/response_list_params.py new file mode 100644 index 00000000..ca13adfa --- /dev/null +++ b/src/llama_stack_client/types/response_list_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["ResponseListParams"] + + +class ResponseListParams(TypedDict, total=False): + after: str + """The ID of the last response to return.""" + + limit: int + """The number of responses to return.""" + + model: str + """The model to filter responses by.""" + + order: Literal["asc", "desc"] + """The order to sort responses by when sorted by created_at ('asc' or 'desc').""" diff --git a/src/llama_stack_client/types/response_list_response.py b/src/llama_stack_client/types/response_list_response.py new file mode 100644 index 00000000..72c555be --- /dev/null +++ b/src/llama_stack_client/types/response_list_response.py @@ -0,0 +1,317 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Union, Optional +from typing_extensions import Literal, Annotated, TypeAlias + +from pydantic import Field as FieldInfo + +from .._utils import PropertyInfo +from .._models import BaseModel + +__all__ = [ + "ResponseListResponse", + "Data", + "DataInput", + "DataInputOpenAIResponseOutputMessageWebSearchToolCall", + "DataInputOpenAIResponseOutputMessageFunctionToolCall", + "DataInputOpenAIResponseInputFunctionToolCallOutput", + "DataInputOpenAIResponseMessage", + "DataInputOpenAIResponseMessageContentUnionMember1", + "DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", + "DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", + "DataInputOpenAIResponseMessageContentUnionMember2", + "DataOutput", + "DataOutputOpenAIResponseMessage", + "DataOutputOpenAIResponseMessageContentUnionMember1", + "DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", + "DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", + "DataOutputOpenAIResponseMessageContentUnionMember2", + "DataOutputOpenAIResponseOutputMessageWebSearchToolCall", + "DataOutputOpenAIResponseOutputMessageFunctionToolCall", + "DataOutputOpenAIResponseOutputMessageMcpCall", + "DataOutputOpenAIResponseOutputMessageMcpListTools", + "DataOutputOpenAIResponseOutputMessageMcpListToolsTool", + "DataText", + "DataTextFormat", + "DataError", +] + + +class DataInputOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): + id: str + + status: str + + type: Literal["web_search_call"] + + +class DataInputOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataInputOpenAIResponseInputFunctionToolCallOutput(BaseModel): + call_id: str + + output: str + + type: Literal["function_call_output"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText(BaseModel): + text: str + + type: Literal["input_text"] + + +class DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage(BaseModel): + detail: Literal["low", "high", "auto"] + + type: Literal["input_image"] + + image_url: Optional[str] = None + + +DataInputOpenAIResponseMessageContentUnionMember1: TypeAlias = Annotated[ + Union[ + DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText, + DataInputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage, + ], + PropertyInfo(discriminator="type"), +] + + +class DataInputOpenAIResponseMessageContentUnionMember2(BaseModel): + text: str + + type: Literal["output_text"] + + +class DataInputOpenAIResponseMessage(BaseModel): + content: Union[ + str, + List[DataInputOpenAIResponseMessageContentUnionMember1], + List[DataInputOpenAIResponseMessageContentUnionMember2], + ] + + role: Literal["system", "developer", "user", "assistant"] + + type: Literal["message"] + + id: Optional[str] = None + + status: Optional[str] = None + + +DataInput: TypeAlias = Union[ + DataInputOpenAIResponseOutputMessageWebSearchToolCall, + DataInputOpenAIResponseOutputMessageFunctionToolCall, + DataInputOpenAIResponseInputFunctionToolCallOutput, + DataInputOpenAIResponseMessage, +] + + +class DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText(BaseModel): + text: str + + type: Literal["input_text"] + + +class DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage(BaseModel): + detail: Literal["low", "high", "auto"] + + type: Literal["input_image"] + + image_url: Optional[str] = None + + +DataOutputOpenAIResponseMessageContentUnionMember1: TypeAlias = Annotated[ + Union[ + DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText, + DataOutputOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage, + ], + PropertyInfo(discriminator="type"), +] + + +class DataOutputOpenAIResponseMessageContentUnionMember2(BaseModel): + text: str + + type: Literal["output_text"] + + +class DataOutputOpenAIResponseMessage(BaseModel): + content: Union[ + str, + List[DataOutputOpenAIResponseMessageContentUnionMember1], + List[DataOutputOpenAIResponseMessageContentUnionMember2], + ] + + role: Literal["system", "developer", "user", "assistant"] + + type: Literal["message"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataOutputOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): + id: str + + status: str + + type: Literal["web_search_call"] + + +class DataOutputOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataOutputOpenAIResponseOutputMessageMcpCall(BaseModel): + id: str + + arguments: str + + name: str + + server_label: str + + type: Literal["mcp_call"] + + error: Optional[str] = None + + output: Optional[str] = None + + +class DataOutputOpenAIResponseOutputMessageMcpListToolsTool(BaseModel): + input_schema: Dict[str, Union[bool, float, str, List[object], object, None]] + + name: str + + description: Optional[str] = None + + +class DataOutputOpenAIResponseOutputMessageMcpListTools(BaseModel): + id: str + + server_label: str + + tools: List[DataOutputOpenAIResponseOutputMessageMcpListToolsTool] + + type: Literal["mcp_list_tools"] + + +DataOutput: TypeAlias = Annotated[ + Union[ + DataOutputOpenAIResponseMessage, + DataOutputOpenAIResponseOutputMessageWebSearchToolCall, + DataOutputOpenAIResponseOutputMessageFunctionToolCall, + DataOutputOpenAIResponseOutputMessageMcpCall, + DataOutputOpenAIResponseOutputMessageMcpListTools, + ], + PropertyInfo(discriminator="type"), +] + + +class DataTextFormat(BaseModel): + type: Literal["text", "json_schema", "json_object"] + """Must be "text", "json_schema", or "json_object" to identify the format type""" + + description: Optional[str] = None + """(Optional) A description of the response format. Only used for json_schema.""" + + name: Optional[str] = None + """The name of the response format. Only used for json_schema.""" + + schema_: Optional[Dict[str, Union[bool, float, str, List[object], object, None]]] = FieldInfo( + alias="schema", default=None + ) + """The JSON schema the response should conform to. + + In a Python SDK, this is often a `pydantic` model. Only used for json_schema. + """ + + strict: Optional[bool] = None + """(Optional) Whether to strictly enforce the JSON schema. + + If true, the response must match the schema exactly. Only used for json_schema. + """ + + +class DataText(BaseModel): + format: Optional[DataTextFormat] = None + """Configuration for Responses API text format.""" + + +class DataError(BaseModel): + code: str + + message: str + + +class Data(BaseModel): + id: str + + created_at: int + + input: List[DataInput] + + model: str + + object: Literal["response"] + + output: List[DataOutput] + + parallel_tool_calls: bool + + status: str + + text: DataText + + error: Optional[DataError] = None + + previous_response_id: Optional[str] = None + + temperature: Optional[float] = None + + top_p: Optional[float] = None + + truncation: Optional[str] = None + + user: Optional[str] = None + + +class ResponseListResponse(BaseModel): + data: List[Data] + + first_id: str + + has_more: bool + + last_id: str + + object: Literal["list"] diff --git a/src/llama_stack_client/types/response_object.py b/src/llama_stack_client/types/response_object.py index 207c58ff..4ce248b1 100644 --- a/src/llama_stack_client/types/response_object.py +++ b/src/llama_stack_client/types/response_object.py @@ -1,8 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Union, Optional +from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias +from pydantic import Field as FieldInfo + from .._utils import PropertyInfo from .._models import BaseModel @@ -16,6 +18,11 @@ "OutputOpenAIResponseMessageContentUnionMember2", "OutputOpenAIResponseOutputMessageWebSearchToolCall", "OutputOpenAIResponseOutputMessageFunctionToolCall", + "OutputOpenAIResponseOutputMessageMcpCall", + "OutputOpenAIResponseOutputMessageMcpListTools", + "OutputOpenAIResponseOutputMessageMcpListToolsTool", + "Text", + "TextFormat", "Error", ] @@ -72,17 +79,51 @@ class OutputOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): class OutputOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class OutputOpenAIResponseOutputMessageMcpCall(BaseModel): id: str arguments: str - call_id: str + name: str + + server_label: str + + type: Literal["mcp_call"] + + error: Optional[str] = None + + output: Optional[str] = None + + +class OutputOpenAIResponseOutputMessageMcpListToolsTool(BaseModel): + input_schema: Dict[str, Union[bool, float, str, List[object], object, None]] name: str - status: str + description: Optional[str] = None - type: Literal["function_call"] + +class OutputOpenAIResponseOutputMessageMcpListTools(BaseModel): + id: str + + server_label: str + + tools: List[OutputOpenAIResponseOutputMessageMcpListToolsTool] + + type: Literal["mcp_list_tools"] Output: TypeAlias = Annotated[ @@ -90,11 +131,43 @@ class OutputOpenAIResponseOutputMessageFunctionToolCall(BaseModel): OutputOpenAIResponseMessage, OutputOpenAIResponseOutputMessageWebSearchToolCall, OutputOpenAIResponseOutputMessageFunctionToolCall, + OutputOpenAIResponseOutputMessageMcpCall, + OutputOpenAIResponseOutputMessageMcpListTools, ], PropertyInfo(discriminator="type"), ] +class TextFormat(BaseModel): + type: Literal["text", "json_schema", "json_object"] + """Must be "text", "json_schema", or "json_object" to identify the format type""" + + description: Optional[str] = None + """(Optional) A description of the response format. Only used for json_schema.""" + + name: Optional[str] = None + """The name of the response format. Only used for json_schema.""" + + schema_: Optional[Dict[str, Union[bool, float, str, List[object], object, None]]] = FieldInfo( + alias="schema", default=None + ) + """The JSON schema the response should conform to. + + In a Python SDK, this is often a `pydantic` model. Only used for json_schema. + """ + + strict: Optional[bool] = None + """(Optional) Whether to strictly enforce the JSON schema. + + If true, the response must match the schema exactly. Only used for json_schema. + """ + + +class Text(BaseModel): + format: Optional[TextFormat] = None + """Configuration for Responses API text format.""" + + class Error(BaseModel): code: str @@ -126,6 +199,8 @@ def output_text(self) -> str: status: str + text: Text + error: Optional[Error] = None previous_response_id: Optional[str] = None diff --git a/src/llama_stack_client/types/response_object_stream.py b/src/llama_stack_client/types/response_object_stream.py index 023b8f9d..ef140814 100644 --- a/src/llama_stack_client/types/response_object_stream.py +++ b/src/llama_stack_client/types/response_object_stream.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Union +from typing import Dict, List, Union, Optional from typing_extensions import Literal, Annotated, TypeAlias from .._utils import PropertyInfo @@ -10,6 +10,45 @@ __all__ = [ "ResponseObjectStream", "OpenAIResponseObjectStreamResponseCreated", + "OpenAIResponseObjectStreamResponseOutputItemAdded", + "OpenAIResponseObjectStreamResponseOutputItemAddedItem", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessage", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember2", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageWebSearchToolCall", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageFunctionToolCall", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpCall", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListTools", + "OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListToolsTool", + "OpenAIResponseObjectStreamResponseOutputItemDone", + "OpenAIResponseObjectStreamResponseOutputItemDoneItem", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessage", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember2", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageWebSearchToolCall", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageFunctionToolCall", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpCall", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListTools", + "OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListToolsTool", + "OpenAIResponseObjectStreamResponseOutputTextDelta", + "OpenAIResponseObjectStreamResponseOutputTextDone", + "OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta", + "OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone", + "OpenAIResponseObjectStreamResponseWebSearchCallInProgress", + "OpenAIResponseObjectStreamResponseWebSearchCallSearching", + "OpenAIResponseObjectStreamResponseWebSearchCallCompleted", + "OpenAIResponseObjectStreamResponseMcpListToolsInProgress", + "OpenAIResponseObjectStreamResponseMcpListToolsFailed", + "OpenAIResponseObjectStreamResponseMcpListToolsCompleted", + "OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta", + "OpenAIResponseObjectStreamResponseMcpCallArgumentsDone", + "OpenAIResponseObjectStreamResponseMcpCallInProgress", + "OpenAIResponseObjectStreamResponseMcpCallFailed", + "OpenAIResponseObjectStreamResponseMcpCallCompleted", "OpenAIResponseObjectStreamResponseCompleted", ] @@ -20,6 +59,420 @@ class OpenAIResponseObjectStreamResponseCreated(BaseModel): type: Literal["response.created"] +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText( + BaseModel +): + text: str + + type: Literal["input_text"] + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage( + BaseModel +): + detail: Literal["low", "high", "auto"] + + type: Literal["input_image"] + + image_url: Optional[str] = None + + +OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1: TypeAlias = Annotated[ + Union[ + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText, + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage, + ], + PropertyInfo(discriminator="type"), +] + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember2(BaseModel): + text: str + + type: Literal["output_text"] + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessage(BaseModel): + content: Union[ + str, + List[OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember1], + List[OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessageContentUnionMember2], + ] + + role: Literal["system", "developer", "user", "assistant"] + + type: Literal["message"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): + id: str + + status: str + + type: Literal["web_search_call"] + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpCall(BaseModel): + id: str + + arguments: str + + name: str + + server_label: str + + type: Literal["mcp_call"] + + error: Optional[str] = None + + output: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListToolsTool(BaseModel): + input_schema: Dict[str, Union[bool, float, str, List[object], object, None]] + + name: str + + description: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListTools(BaseModel): + id: str + + server_label: str + + tools: List[OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListToolsTool] + + type: Literal["mcp_list_tools"] + + +OpenAIResponseObjectStreamResponseOutputItemAddedItem: TypeAlias = Annotated[ + Union[ + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseMessage, + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageWebSearchToolCall, + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageFunctionToolCall, + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpCall, + OpenAIResponseObjectStreamResponseOutputItemAddedItemOpenAIResponseOutputMessageMcpListTools, + ], + PropertyInfo(discriminator="type"), +] + + +class OpenAIResponseObjectStreamResponseOutputItemAdded(BaseModel): + item: OpenAIResponseObjectStreamResponseOutputItemAddedItem + """Corresponds to the various Message types in the Responses API. + + They are all under one type because the Responses API gives them all the same + "type" value, and there is no way to tell them apart in certain scenarios. + """ + + output_index: int + + response_id: str + + sequence_number: int + + type: Literal["response.output_item.added"] + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText( + BaseModel +): + text: str + + type: Literal["input_text"] + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage( + BaseModel +): + detail: Literal["low", "high", "auto"] + + type: Literal["input_image"] + + image_url: Optional[str] = None + + +OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1: TypeAlias = Annotated[ + Union[ + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText, + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage, + ], + PropertyInfo(discriminator="type"), +] + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember2(BaseModel): + text: str + + type: Literal["output_text"] + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessage(BaseModel): + content: Union[ + str, + List[OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember1], + List[OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessageContentUnionMember2], + ] + + role: Literal["system", "developer", "user", "assistant"] + + type: Literal["message"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): + id: str + + status: str + + type: Literal["web_search_call"] + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpCall(BaseModel): + id: str + + arguments: str + + name: str + + server_label: str + + type: Literal["mcp_call"] + + error: Optional[str] = None + + output: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListToolsTool(BaseModel): + input_schema: Dict[str, Union[bool, float, str, List[object], object, None]] + + name: str + + description: Optional[str] = None + + +class OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListTools(BaseModel): + id: str + + server_label: str + + tools: List[OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListToolsTool] + + type: Literal["mcp_list_tools"] + + +OpenAIResponseObjectStreamResponseOutputItemDoneItem: TypeAlias = Annotated[ + Union[ + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseMessage, + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageWebSearchToolCall, + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageFunctionToolCall, + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpCall, + OpenAIResponseObjectStreamResponseOutputItemDoneItemOpenAIResponseOutputMessageMcpListTools, + ], + PropertyInfo(discriminator="type"), +] + + +class OpenAIResponseObjectStreamResponseOutputItemDone(BaseModel): + item: OpenAIResponseObjectStreamResponseOutputItemDoneItem + """Corresponds to the various Message types in the Responses API. + + They are all under one type because the Responses API gives them all the same + "type" value, and there is no way to tell them apart in certain scenarios. + """ + + output_index: int + + response_id: str + + sequence_number: int + + type: Literal["response.output_item.done"] + + +class OpenAIResponseObjectStreamResponseOutputTextDelta(BaseModel): + content_index: int + + delta: str + + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.output_text.delta"] + + +class OpenAIResponseObjectStreamResponseOutputTextDone(BaseModel): + content_index: int + + item_id: str + + output_index: int + + sequence_number: int + + text: str + + type: Literal["response.output_text.done"] + + +class OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta(BaseModel): + delta: str + + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.function_call_arguments.delta"] + + +class OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone(BaseModel): + arguments: str + + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.function_call_arguments.done"] + + +class OpenAIResponseObjectStreamResponseWebSearchCallInProgress(BaseModel): + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.web_search_call.in_progress"] + + +class OpenAIResponseObjectStreamResponseWebSearchCallSearching(BaseModel): + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.web_search_call.searching"] + + +class OpenAIResponseObjectStreamResponseWebSearchCallCompleted(BaseModel): + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.web_search_call.completed"] + + +class OpenAIResponseObjectStreamResponseMcpListToolsInProgress(BaseModel): + sequence_number: int + + type: Literal["response.mcp_list_tools.in_progress"] + + +class OpenAIResponseObjectStreamResponseMcpListToolsFailed(BaseModel): + sequence_number: int + + type: Literal["response.mcp_list_tools.failed"] + + +class OpenAIResponseObjectStreamResponseMcpListToolsCompleted(BaseModel): + sequence_number: int + + type: Literal["response.mcp_list_tools.completed"] + + +class OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta(BaseModel): + delta: str + + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.mcp_call.arguments.delta"] + + +class OpenAIResponseObjectStreamResponseMcpCallArgumentsDone(BaseModel): + arguments: str + + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.mcp_call.arguments.done"] + + +class OpenAIResponseObjectStreamResponseMcpCallInProgress(BaseModel): + item_id: str + + output_index: int + + sequence_number: int + + type: Literal["response.mcp_call.in_progress"] + + +class OpenAIResponseObjectStreamResponseMcpCallFailed(BaseModel): + sequence_number: int + + type: Literal["response.mcp_call.failed"] + + +class OpenAIResponseObjectStreamResponseMcpCallCompleted(BaseModel): + sequence_number: int + + type: Literal["response.mcp_call.completed"] + + class OpenAIResponseObjectStreamResponseCompleted(BaseModel): response: ResponseObject @@ -27,6 +480,26 @@ class OpenAIResponseObjectStreamResponseCompleted(BaseModel): ResponseObjectStream: TypeAlias = Annotated[ - Union[OpenAIResponseObjectStreamResponseCreated, OpenAIResponseObjectStreamResponseCompleted], + Union[ + OpenAIResponseObjectStreamResponseCreated, + OpenAIResponseObjectStreamResponseOutputItemAdded, + OpenAIResponseObjectStreamResponseOutputItemDone, + OpenAIResponseObjectStreamResponseOutputTextDelta, + OpenAIResponseObjectStreamResponseOutputTextDone, + OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta, + OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone, + OpenAIResponseObjectStreamResponseWebSearchCallInProgress, + OpenAIResponseObjectStreamResponseWebSearchCallSearching, + OpenAIResponseObjectStreamResponseWebSearchCallCompleted, + OpenAIResponseObjectStreamResponseMcpListToolsInProgress, + OpenAIResponseObjectStreamResponseMcpListToolsFailed, + OpenAIResponseObjectStreamResponseMcpListToolsCompleted, + OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta, + OpenAIResponseObjectStreamResponseMcpCallArgumentsDone, + OpenAIResponseObjectStreamResponseMcpCallInProgress, + OpenAIResponseObjectStreamResponseMcpCallFailed, + OpenAIResponseObjectStreamResponseMcpCallCompleted, + OpenAIResponseObjectStreamResponseCompleted, + ], PropertyInfo(discriminator="type"), ] diff --git a/src/llama_stack_client/types/responses/__init__.py b/src/llama_stack_client/types/responses/__init__.py new file mode 100644 index 00000000..cb934712 --- /dev/null +++ b/src/llama_stack_client/types/responses/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .input_item_list_params import InputItemListParams as InputItemListParams +from .input_item_list_response import InputItemListResponse as InputItemListResponse diff --git a/src/llama_stack_client/types/responses/input_item_list_params.py b/src/llama_stack_client/types/responses/input_item_list_params.py new file mode 100644 index 00000000..a78bd215 --- /dev/null +++ b/src/llama_stack_client/types/responses/input_item_list_params.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal, TypedDict + +__all__ = ["InputItemListParams"] + + +class InputItemListParams(TypedDict, total=False): + after: str + """An item ID to list items after, used for pagination.""" + + before: str + """An item ID to list items before, used for pagination.""" + + include: List[str] + """Additional fields to include in the response.""" + + limit: int + """A limit on the number of objects to be returned. + + Limit can range between 1 and 100, and the default is 20. + """ + + order: Literal["asc", "desc"] + """The order to return the input items in. Default is desc.""" diff --git a/src/llama_stack_client/types/responses/input_item_list_response.py b/src/llama_stack_client/types/responses/input_item_list_response.py new file mode 100644 index 00000000..1d8f5a76 --- /dev/null +++ b/src/llama_stack_client/types/responses/input_item_list_response.py @@ -0,0 +1,111 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, Annotated, TypeAlias + +from ..._utils import PropertyInfo +from ..._models import BaseModel + +__all__ = [ + "InputItemListResponse", + "Data", + "DataOpenAIResponseOutputMessageWebSearchToolCall", + "DataOpenAIResponseOutputMessageFunctionToolCall", + "DataOpenAIResponseInputFunctionToolCallOutput", + "DataOpenAIResponseMessage", + "DataOpenAIResponseMessageContentUnionMember1", + "DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText", + "DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage", + "DataOpenAIResponseMessageContentUnionMember2", +] + + +class DataOpenAIResponseOutputMessageWebSearchToolCall(BaseModel): + id: str + + status: str + + type: Literal["web_search_call"] + + +class DataOpenAIResponseOutputMessageFunctionToolCall(BaseModel): + arguments: str + + call_id: str + + name: str + + type: Literal["function_call"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataOpenAIResponseInputFunctionToolCallOutput(BaseModel): + call_id: str + + output: str + + type: Literal["function_call_output"] + + id: Optional[str] = None + + status: Optional[str] = None + + +class DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText(BaseModel): + text: str + + type: Literal["input_text"] + + +class DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage(BaseModel): + detail: Literal["low", "high", "auto"] + + type: Literal["input_image"] + + image_url: Optional[str] = None + + +DataOpenAIResponseMessageContentUnionMember1: TypeAlias = Annotated[ + Union[ + DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentText, + DataOpenAIResponseMessageContentUnionMember1OpenAIResponseInputMessageContentImage, + ], + PropertyInfo(discriminator="type"), +] + + +class DataOpenAIResponseMessageContentUnionMember2(BaseModel): + text: str + + type: Literal["output_text"] + + +class DataOpenAIResponseMessage(BaseModel): + content: Union[ + str, List[DataOpenAIResponseMessageContentUnionMember1], List[DataOpenAIResponseMessageContentUnionMember2] + ] + + role: Literal["system", "developer", "user", "assistant"] + + type: Literal["message"] + + id: Optional[str] = None + + status: Optional[str] = None + + +Data: TypeAlias = Union[ + DataOpenAIResponseOutputMessageWebSearchToolCall, + DataOpenAIResponseOutputMessageFunctionToolCall, + DataOpenAIResponseInputFunctionToolCallOutput, + DataOpenAIResponseMessage, +] + + +class InputItemListResponse(BaseModel): + data: List[Data] + + object: Literal["list"] diff --git a/src/llama_stack_client/types/tool.py b/src/llama_stack_client/types/tool.py index 59e9300f..6beb8764 100644 --- a/src/llama_stack_client/types/tool.py +++ b/src/llama_stack_client/types/tool.py @@ -29,8 +29,6 @@ class Tool(BaseModel): provider_id: str - tool_host: Literal["distribution", "client", "model_context_protocol"] - toolgroup_id: str type: Literal["tool"] diff --git a/src/llama_stack_client/types/vector_io_insert_params.py b/src/llama_stack_client/types/vector_io_insert_params.py index adc1642e..2dded485 100644 --- a/src/llama_stack_client/types/vector_io_insert_params.py +++ b/src/llama_stack_client/types/vector_io_insert_params.py @@ -12,7 +12,14 @@ class VectorIoInsertParams(TypedDict, total=False): chunks: Required[Iterable[Chunk]] - """The chunks to insert.""" + """The chunks to insert. + + Each `Chunk` should contain content which can be interleaved text, images, or + other types. `metadata`: `dict[str, Any]` and `embedding`: `List[float]` are + optional. If `metadata` is provided, you configure how Llama Stack formats the + chunk during generation. If `embedding` is not provided, it will be computed + later. + """ vector_db_id: Required[str] """The identifier of the vector database to insert the chunks into.""" @@ -23,6 +30,15 @@ class VectorIoInsertParams(TypedDict, total=False): class Chunk(TypedDict, total=False): content: Required[InterleavedContent] - """A image content item""" + """ + The content of the chunk, which can be interleaved text, images, or other types. + """ metadata: Required[Dict[str, Union[bool, float, str, Iterable[object], object, None]]] + """ + Metadata associated with the chunk, such as document ID, source, or other + relevant information. + """ + + embedding: Iterable[float] + """Optional embedding for the chunk. If not provided, it will be computed later.""" diff --git a/src/llama_stack_client/types/vector_store.py b/src/llama_stack_client/types/vector_store.py new file mode 100644 index 00000000..e766af15 --- /dev/null +++ b/src/llama_stack_client/types/vector_store.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import builtins +from typing import Dict, List, Union, Optional + +from .._models import BaseModel + +__all__ = ["VectorStore"] + + +class VectorStore(BaseModel): + id: str + + created_at: int + + file_counts: Dict[str, int] + + metadata: Dict[str, Union[bool, float, str, List[object], object, None]] + + object: str + + status: str + + usage_bytes: int + + expires_after: Optional[Dict[str, Union[bool, float, str, List[builtins.object], builtins.object, None]]] = None + + expires_at: Optional[int] = None + + last_active_at: Optional[int] = None + + name: Optional[str] = None diff --git a/src/llama_stack_client/types/vector_store_create_params.py b/src/llama_stack_client/types/vector_store_create_params.py new file mode 100644 index 00000000..18748f48 --- /dev/null +++ b/src/llama_stack_client/types/vector_store_create_params.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Union, Iterable +from typing_extensions import Required, TypedDict + +__all__ = ["VectorStoreCreateParams"] + + +class VectorStoreCreateParams(TypedDict, total=False): + name: Required[str] + """A name for the vector store.""" + + chunking_strategy: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """The chunking strategy used to chunk the file(s). + + If not set, will use the `auto` strategy. + """ + + embedding_dimension: int + """The dimension of the embedding vectors (default: 384).""" + + embedding_model: str + """The embedding model to use for this vector store.""" + + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """The expiration policy for a vector store.""" + + file_ids: List[str] + """A list of File IDs that the vector store should use. + + Useful for tools like `file_search` that can access files. + """ + + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """Set of 16 key-value pairs that can be attached to an object.""" + + provider_id: str + """The ID of the provider to use for this vector store.""" + + provider_vector_db_id: str + """The provider-specific vector database ID.""" diff --git a/src/llama_stack_client/types/vector_store_delete_response.py b/src/llama_stack_client/types/vector_store_delete_response.py new file mode 100644 index 00000000..945ada10 --- /dev/null +++ b/src/llama_stack_client/types/vector_store_delete_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["VectorStoreDeleteResponse"] + + +class VectorStoreDeleteResponse(BaseModel): + id: str + + deleted: bool + + object: str diff --git a/src/llama_stack_client/types/vector_store_list_params.py b/src/llama_stack_client/types/vector_store_list_params.py new file mode 100644 index 00000000..176a6279 --- /dev/null +++ b/src/llama_stack_client/types/vector_store_list_params.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["VectorStoreListParams"] + + +class VectorStoreListParams(TypedDict, total=False): + after: str + """A cursor for use in pagination. + + `after` is an object ID that defines your place in the list. + """ + + before: str + """A cursor for use in pagination. + + `before` is an object ID that defines your place in the list. + """ + + limit: int + """A limit on the number of objects to be returned. + + Limit can range between 1 and 100, and the default is 20. + """ + + order: str + """Sort order by the `created_at` timestamp of the objects. + + `asc` for ascending order and `desc` for descending order. + """ diff --git a/src/llama_stack_client/types/vector_store_search_params.py b/src/llama_stack_client/types/vector_store_search_params.py new file mode 100644 index 00000000..0c8545df --- /dev/null +++ b/src/llama_stack_client/types/vector_store_search_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List, Union, Iterable +from typing_extensions import Required, TypedDict + +__all__ = ["VectorStoreSearchParams"] + + +class VectorStoreSearchParams(TypedDict, total=False): + query: Required[Union[str, List[str]]] + """The query string or array for performing the search.""" + + filters: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """Filters based on file attributes to narrow the search results.""" + + max_num_results: int + """Maximum number of results to return (1 to 50 inclusive, default 10).""" + + ranking_options: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """Ranking options for fine-tuning the search results.""" + + rewrite_query: bool + """Whether to rewrite the natural language query for vector search (default false)""" diff --git a/src/llama_stack_client/types/vector_store_search_response.py b/src/llama_stack_client/types/vector_store_search_response.py new file mode 100644 index 00000000..7b596e03 --- /dev/null +++ b/src/llama_stack_client/types/vector_store_search_response.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Union, Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["VectorStoreSearchResponse", "Data", "DataContent"] + + +class DataContent(BaseModel): + text: str + + type: Literal["text"] + + +class Data(BaseModel): + content: List[DataContent] + + file_id: str + + filename: str + + score: float + + attributes: Optional[Dict[str, Union[str, float, bool]]] = None + + +class VectorStoreSearchResponse(BaseModel): + data: List[Data] + + has_more: bool + + object: str + + search_query: str + + next_page: Optional[str] = None diff --git a/src/llama_stack_client/types/vector_store_update_params.py b/src/llama_stack_client/types/vector_store_update_params.py new file mode 100644 index 00000000..d1e069ed --- /dev/null +++ b/src/llama_stack_client/types/vector_store_update_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union, Iterable +from typing_extensions import TypedDict + +__all__ = ["VectorStoreUpdateParams"] + + +class VectorStoreUpdateParams(TypedDict, total=False): + expires_after: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """The expiration policy for a vector store.""" + + metadata: Dict[str, Union[bool, float, str, Iterable[object], object, None]] + """Set of 16 key-value pairs that can be attached to an object.""" + + name: str + """The name of the vector store.""" diff --git a/tests/api_resources/responses/__init__.py b/tests/api_resources/responses/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/responses/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/responses/test_input_items.py b/tests/api_resources/responses/test_input_items.py new file mode 100644 index 00000000..c1b25556 --- /dev/null +++ b/tests/api_resources/responses/test_input_items.py @@ -0,0 +1,122 @@ +# 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 tests.utils import assert_matches_type +from llama_stack_client import LlamaStackClient, AsyncLlamaStackClient +from llama_stack_client.types.responses import InputItemListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestInputItems: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: LlamaStackClient) -> None: + input_item = client.responses.input_items.list( + response_id="response_id", + ) + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: LlamaStackClient) -> None: + input_item = client.responses.input_items.list( + response_id="response_id", + after="after", + before="before", + include=["string"], + limit=0, + order="asc", + ) + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: LlamaStackClient) -> None: + response = client.responses.input_items.with_raw_response.list( + response_id="response_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + input_item = response.parse() + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: LlamaStackClient) -> None: + with client.responses.input_items.with_streaming_response.list( + response_id="response_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + input_item = response.parse() + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): + client.responses.input_items.with_raw_response.list( + response_id="", + ) + + +class TestAsyncInputItems: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_list(self, async_client: AsyncLlamaStackClient) -> None: + input_item = await async_client.responses.input_items.list( + response_id="response_id", + ) + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + input_item = await async_client.responses.input_items.list( + response_id="response_id", + after="after", + before="before", + include=["string"], + limit=0, + order="asc", + ) + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.responses.input_items.with_raw_response.list( + response_id="response_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + input_item = await response.parse() + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.responses.input_items.with_streaming_response.list( + response_id="response_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + input_item = await response.parse() + assert_matches_type(InputItemListResponse, input_item, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `response_id` but received ''"): + await async_client.responses.input_items.with_raw_response.list( + response_id="", + ) diff --git a/tests/api_resources/test_embeddings.py b/tests/api_resources/test_embeddings.py new file mode 100644 index 00000000..6f997c32 --- /dev/null +++ b/tests/api_resources/test_embeddings.py @@ -0,0 +1,112 @@ +# 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 tests.utils import assert_matches_type +from llama_stack_client import LlamaStackClient, AsyncLlamaStackClient +from llama_stack_client.types import EmbeddingsResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestEmbeddings: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: LlamaStackClient) -> None: + embedding = client.embeddings.create( + input="string", + model="model", + ) + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: LlamaStackClient) -> None: + embedding = client.embeddings.create( + input="string", + model="model", + dimensions=0, + encoding_format="encoding_format", + user="user", + ) + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: LlamaStackClient) -> None: + response = client.embeddings.with_raw_response.create( + input="string", + model="model", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + embedding = response.parse() + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: LlamaStackClient) -> None: + with client.embeddings.with_streaming_response.create( + input="string", + model="model", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + embedding = response.parse() + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncEmbeddings: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncLlamaStackClient) -> None: + embedding = await async_client.embeddings.create( + input="string", + model="model", + ) + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + embedding = await async_client.embeddings.create( + input="string", + model="model", + dimensions=0, + encoding_format="encoding_format", + user="user", + ) + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.embeddings.with_raw_response.create( + input="string", + model="model", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + embedding = await response.parse() + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.embeddings.with_streaming_response.create( + input="string", + model="model", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + embedding = await response.parse() + assert_matches_type(EmbeddingsResponse, embedding, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py new file mode 100644 index 00000000..8dbcedec --- /dev/null +++ b/tests/api_resources/test_files.py @@ -0,0 +1,388 @@ +# 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 tests.utils import assert_matches_type +from llama_stack_client import LlamaStackClient, AsyncLlamaStackClient +from llama_stack_client.types import File, ListFilesResponse, DeleteFileResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFiles: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: LlamaStackClient) -> None: + file = client.files.create( + file=b"raw file contents", + purpose="assistants", + ) + assert_matches_type(File, file, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: LlamaStackClient) -> None: + response = client.files.with_raw_response.create( + file=b"raw file contents", + purpose="assistants", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(File, file, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: LlamaStackClient) -> None: + with client.files.with_streaming_response.create( + file=b"raw file contents", + purpose="assistants", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(File, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: LlamaStackClient) -> None: + file = client.files.retrieve( + "file_id", + ) + assert_matches_type(File, file, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: LlamaStackClient) -> None: + response = client.files.with_raw_response.retrieve( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(File, file, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: LlamaStackClient) -> None: + with client.files.with_streaming_response.retrieve( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(File, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: LlamaStackClient) -> None: + file = client.files.list() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: LlamaStackClient) -> None: + file = client.files.list( + after="after", + limit=0, + order="asc", + purpose="assistants", + ) + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: LlamaStackClient) -> None: + response = client.files.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: LlamaStackClient) -> None: + with client.files.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: LlamaStackClient) -> None: + file = client.files.delete( + "file_id", + ) + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: LlamaStackClient) -> None: + response = client.files.with_raw_response.delete( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: LlamaStackClient) -> None: + with client.files.with_streaming_response.delete( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.delete( + "", + ) + + @parametrize + def test_method_content(self, client: LlamaStackClient) -> None: + file = client.files.content( + "file_id", + ) + assert_matches_type(object, file, path=["response"]) + + @parametrize + def test_raw_response_content(self, client: LlamaStackClient) -> None: + response = client.files.with_raw_response.content( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + @parametrize + def test_streaming_response_content(self, client: LlamaStackClient) -> None: + with client.files.with_streaming_response.content( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_content(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.files.with_raw_response.content( + "", + ) + + +class TestAsyncFiles: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.create( + file=b"raw file contents", + purpose="assistants", + ) + assert_matches_type(File, file, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.files.with_raw_response.create( + file=b"raw file contents", + purpose="assistants", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(File, file, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.files.with_streaming_response.create( + file=b"raw file contents", + purpose="assistants", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(File, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.retrieve( + "file_id", + ) + assert_matches_type(File, file, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.files.with_raw_response.retrieve( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(File, file, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.files.with_streaming_response.retrieve( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(File, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.list() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.list( + after="after", + limit=0, + order="asc", + purpose="assistants", + ) + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.files.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.files.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(ListFilesResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.delete( + "file_id", + ) + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.files.with_raw_response.delete( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.files.with_streaming_response.delete( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(DeleteFileResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.delete( + "", + ) + + @parametrize + async def test_method_content(self, async_client: AsyncLlamaStackClient) -> None: + file = await async_client.files.content( + "file_id", + ) + assert_matches_type(object, file, path=["response"]) + + @parametrize + async def test_raw_response_content(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.files.with_raw_response.content( + "file_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + @parametrize + async def test_streaming_response_content(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.files.with_streaming_response.content( + "file_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(object, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_content(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.files.with_raw_response.content( + "", + ) diff --git a/tests/api_resources/test_responses.py b/tests/api_resources/test_responses.py index 74e13e8d..e3343d3e 100644 --- a/tests/api_resources/test_responses.py +++ b/tests/api_resources/test_responses.py @@ -9,7 +9,7 @@ from tests.utils import assert_matches_type from llama_stack_client import LlamaStackClient, AsyncLlamaStackClient -from llama_stack_client.types import ResponseObject +from llama_stack_client.types import ResponseObject, ResponseListResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -31,10 +31,20 @@ def test_method_create_with_all_params_overload_1(self, client: LlamaStackClient input="string", model="model", instructions="instructions", + max_infer_iters=0, previous_response_id="previous_response_id", store=True, stream=False, temperature=0, + text={ + "format": { + "type": "text", + "description": "description", + "name": "name", + "schema": {"foo": True}, + "strict": True, + } + }, tools=[ { "type": "web_search", @@ -86,9 +96,19 @@ def test_method_create_with_all_params_overload_2(self, client: LlamaStackClient model="model", stream=True, instructions="instructions", + max_infer_iters=0, previous_response_id="previous_response_id", store=True, temperature=0, + text={ + "format": { + "type": "text", + "description": "description", + "name": "name", + "schema": {"foo": True}, + "strict": True, + } + }, tools=[ { "type": "web_search", @@ -163,6 +183,41 @@ def test_path_params_retrieve(self, client: LlamaStackClient) -> None: "", ) + @parametrize + def test_method_list(self, client: LlamaStackClient) -> None: + response = client.responses.list() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: LlamaStackClient) -> None: + response = client.responses.list( + after="after", + limit=0, + model="model", + order="asc", + ) + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: LlamaStackClient) -> None: + http_response = client.responses.with_raw_response.list() + + assert http_response.is_closed is True + assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" + response = http_response.parse() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: LlamaStackClient) -> None: + with client.responses.with_streaming_response.list() as http_response: + assert not http_response.is_closed + assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" + + response = http_response.parse() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + assert cast(Any, http_response.is_closed) is True + class TestAsyncResponses: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @@ -181,10 +236,20 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn input="string", model="model", instructions="instructions", + max_infer_iters=0, previous_response_id="previous_response_id", store=True, stream=False, temperature=0, + text={ + "format": { + "type": "text", + "description": "description", + "name": "name", + "schema": {"foo": True}, + "strict": True, + } + }, tools=[ { "type": "web_search", @@ -236,9 +301,19 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn model="model", stream=True, instructions="instructions", + max_infer_iters=0, previous_response_id="previous_response_id", store=True, temperature=0, + text={ + "format": { + "type": "text", + "description": "description", + "name": "name", + "schema": {"foo": True}, + "strict": True, + } + }, tools=[ { "type": "web_search", @@ -312,3 +387,38 @@ async def test_path_params_retrieve(self, async_client: AsyncLlamaStackClient) - await async_client.responses.with_raw_response.retrieve( "", ) + + @parametrize + async def test_method_list(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.responses.list() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.responses.list( + after="after", + limit=0, + model="model", + order="asc", + ) + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLlamaStackClient) -> None: + http_response = await async_client.responses.with_raw_response.list() + + assert http_response.is_closed is True + assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" + response = await http_response.parse() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.responses.with_streaming_response.list() as http_response: + assert not http_response.is_closed + assert http_response.http_request.headers.get("X-Stainless-Lang") == "python" + + response = await http_response.parse() + assert_matches_type(ResponseListResponse, response, path=["response"]) + + assert cast(Any, http_response.is_closed) is True diff --git a/tests/api_resources/test_vector_io.py b/tests/api_resources/test_vector_io.py index 6e1cd5e0..dada826d 100644 --- a/tests/api_resources/test_vector_io.py +++ b/tests/api_resources/test_vector_io.py @@ -37,6 +37,7 @@ def test_method_insert_with_all_params(self, client: LlamaStackClient) -> None: { "content": "string", "metadata": {"foo": True}, + "embedding": [0], } ], vector_db_id="vector_db_id", @@ -147,6 +148,7 @@ async def test_method_insert_with_all_params(self, async_client: AsyncLlamaStack { "content": "string", "metadata": {"foo": True}, + "embedding": [0], } ], vector_db_id="vector_db_id", diff --git a/tests/api_resources/test_vector_stores.py b/tests/api_resources/test_vector_stores.py new file mode 100644 index 00000000..81b59ac1 --- /dev/null +++ b/tests/api_resources/test_vector_stores.py @@ -0,0 +1,545 @@ +# 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 tests.utils import assert_matches_type +from llama_stack_client import LlamaStackClient, AsyncLlamaStackClient +from llama_stack_client.types import ( + VectorStore, + ListVectorStoresResponse, + VectorStoreDeleteResponse, + VectorStoreSearchResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestVectorStores: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.create( + name="name", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.create( + name="name", + chunking_strategy={"foo": True}, + embedding_dimension=0, + embedding_model="embedding_model", + expires_after={"foo": True}, + file_ids=["string"], + metadata={"foo": True}, + provider_id="provider_id", + provider_vector_db_id="provider_vector_db_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.retrieve( + "vector_store_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.retrieve( + "vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.retrieve( + "vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + client.vector_stores.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_update(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.update( + vector_store_id="vector_store_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.update( + vector_store_id="vector_store_id", + expires_after={"foo": True}, + metadata={"foo": True}, + name="name", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.update( + vector_store_id="vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.update( + vector_store_id="vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + client.vector_stores.with_raw_response.update( + vector_store_id="", + ) + + @parametrize + def test_method_list(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.list() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.list( + after="after", + before="before", + limit=0, + order="order", + ) + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.delete( + "vector_store_id", + ) + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + @parametrize + def test_raw_response_delete(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.delete( + "vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_delete(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.delete( + "vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + client.vector_stores.with_raw_response.delete( + "", + ) + + @parametrize + def test_method_search(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.search( + vector_store_id="vector_store_id", + query="string", + ) + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + def test_method_search_with_all_params(self, client: LlamaStackClient) -> None: + vector_store = client.vector_stores.search( + vector_store_id="vector_store_id", + query="string", + filters={"foo": True}, + max_num_results=0, + ranking_options={"foo": True}, + rewrite_query=True, + ) + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + def test_raw_response_search(self, client: LlamaStackClient) -> None: + response = client.vector_stores.with_raw_response.search( + vector_store_id="vector_store_id", + query="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = response.parse() + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + def test_streaming_response_search(self, client: LlamaStackClient) -> None: + with client.vector_stores.with_streaming_response.search( + vector_store_id="vector_store_id", + query="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = response.parse() + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_search(self, client: LlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + client.vector_stores.with_raw_response.search( + vector_store_id="", + query="string", + ) + + +class TestAsyncVectorStores: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_create(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.create( + name="name", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.create( + name="name", + chunking_strategy={"foo": True}, + embedding_dimension=0, + embedding_model="embedding_model", + expires_after={"foo": True}, + file_ids=["string"], + metadata={"foo": True}, + provider_id="provider_id", + provider_vector_db_id="provider_vector_db_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.retrieve( + "vector_store_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.retrieve( + "vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.retrieve( + "vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + await async_client.vector_stores.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_update(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.update( + vector_store_id="vector_store_id", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.update( + vector_store_id="vector_store_id", + expires_after={"foo": True}, + metadata={"foo": True}, + name="name", + ) + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.update( + vector_store_id="vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.update( + vector_store_id="vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(VectorStore, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + await async_client.vector_stores.with_raw_response.update( + vector_store_id="", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.list() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.list( + after="after", + before="before", + limit=0, + order="order", + ) + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(ListVectorStoresResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.delete( + "vector_store_id", + ) + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.delete( + "vector_store_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.delete( + "vector_store_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + await async_client.vector_stores.with_raw_response.delete( + "", + ) + + @parametrize + async def test_method_search(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.search( + vector_store_id="vector_store_id", + query="string", + ) + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + async def test_method_search_with_all_params(self, async_client: AsyncLlamaStackClient) -> None: + vector_store = await async_client.vector_stores.search( + vector_store_id="vector_store_id", + query="string", + filters={"foo": True}, + max_num_results=0, + ranking_options={"foo": True}, + rewrite_query=True, + ) + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + async def test_raw_response_search(self, async_client: AsyncLlamaStackClient) -> None: + response = await async_client.vector_stores.with_raw_response.search( + vector_store_id="vector_store_id", + query="string", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vector_store = await response.parse() + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + @parametrize + async def test_streaming_response_search(self, async_client: AsyncLlamaStackClient) -> None: + async with async_client.vector_stores.with_streaming_response.search( + vector_store_id="vector_store_id", + query="string", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vector_store = await response.parse() + assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_search(self, async_client: AsyncLlamaStackClient) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + await async_client.vector_stores.with_raw_response.search( + vector_store_id="", + query="string", + ) diff --git a/tests/test_client.py b/tests/test_client.py index 7ad6e189..b3d169b0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -836,6 +836,33 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" + class TestAsyncLlamaStackClient: client = AsyncLlamaStackClient(base_url=base_url, _strict_response_validation=True) @@ -1674,3 +1701,30 @@ async def test_main() -> None: raise AssertionError("calling get_platform using asyncify resulted in a hung process") time.sleep(0.1) + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + await self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected"