1# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
  2
  3from __future__ import annotations
  4
  5from typing import TYPE_CHECKING, Dict, Union, Optional
  6from typing_extensions import Literal, assert_never
  7
  8import httpx
  9
 10from ... import _legacy_response
 11from ...types import FileChunkingStrategyParam
 12from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
 13from ..._utils import is_given, maybe_transform, async_maybe_transform
 14from ..._compat import cached_property
 15from ..._resource import SyncAPIResource, AsyncAPIResource
 16from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper
 17from ...pagination import SyncPage, AsyncPage, SyncCursorPage, AsyncCursorPage
 18from ..._base_client import AsyncPaginator, make_request_options
 19from ...types.vector_stores import file_list_params, file_create_params, file_update_params
 20from ...types.file_chunking_strategy_param import FileChunkingStrategyParam
 21from ...types.vector_stores.vector_store_file import VectorStoreFile
 22from ...types.vector_stores.file_content_response import FileContentResponse
 23from ...types.vector_stores.vector_store_file_deleted import VectorStoreFileDeleted
 24
 25__all__ = ["Files", "AsyncFiles"]
 26
 27
 28class Files(SyncAPIResource):
 29    @cached_property
 30    def with_raw_response(self) -> FilesWithRawResponse:
 31        """
 32        This property can be used as a prefix for any HTTP method call to return
 33        the raw response object instead of the parsed content.
 34
 35        For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers
 36        """
 37        return FilesWithRawResponse(self)
 38
 39    @cached_property
 40    def with_streaming_response(self) -> FilesWithStreamingResponse:
 41        """
 42        An alternative to `.with_raw_response` that doesn't eagerly read the response body.
 43
 44        For more information, see https://www.github.com/openai/openai-python#with_streaming_response
 45        """
 46        return FilesWithStreamingResponse(self)
 47
 48    def create(
 49        self,
 50        vector_store_id: str,
 51        *,
 52        file_id: str,
 53        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
 54        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
 55        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
 56        # The extra values given here take precedence over values defined on the client or passed to this method.
 57        extra_headers: Headers | None = None,
 58        extra_query: Query | None = None,
 59        extra_body: Body | None = None,
 60        timeout: float | httpx.Timeout | None | NotGiven = not_given,
 61    ) -> VectorStoreFile:
 62        """
 63        Create a vector store file by attaching a
 64        [File](https://platform.openai.com/docs/api-reference/files) to a
 65        [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object).
 66
 67        Args:
 68          file_id: A [File](https://platform.openai.com/docs/api-reference/files) ID that the
 69              vector store should use. Useful for tools like `file_search` that can access
 70              files.
 71
 72          attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful
 73              for storing additional information about the object in a structured format, and
 74              querying for objects via API or the dashboard. Keys are strings with a maximum
 75              length of 64 characters. Values are strings with a maximum length of 512
 76              characters, booleans, or numbers.
 77
 78          chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto`
 79              strategy. Only applicable if `file_ids` is non-empty.
 80
 81          extra_headers: Send extra headers
 82
 83          extra_query: Add additional query parameters to the request
 84
 85          extra_body: Add additional JSON properties to the request
 86
 87          timeout: Override the client-level default timeout for this request, in seconds
 88        """
 89        if not vector_store_id:
 90            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
 91        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
 92        return self._post(
 93            f"/vector_stores/{vector_store_id}/files",
 94            body=maybe_transform(
 95                {
 96                    "file_id": file_id,
 97                    "attributes": attributes,
 98                    "chunking_strategy": chunking_strategy,
 99                },
100                file_create_params.FileCreateParams,
101            ),
102            options=make_request_options(
103                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
104            ),
105            cast_to=VectorStoreFile,
106        )
107
108    def retrieve(
109        self,
110        file_id: str,
111        *,
112        vector_store_id: str,
113        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
114        # The extra values given here take precedence over values defined on the client or passed to this method.
115        extra_headers: Headers | None = None,
116        extra_query: Query | None = None,
117        extra_body: Body | None = None,
118        timeout: float | httpx.Timeout | None | NotGiven = not_given,
119    ) -> VectorStoreFile:
120        """
121        Retrieves a vector store file.
122
123        Args:
124          extra_headers: Send extra headers
125
126          extra_query: Add additional query parameters to the request
127
128          extra_body: Add additional JSON properties to the request
129
130          timeout: Override the client-level default timeout for this request, in seconds
131        """
132        if not vector_store_id:
133            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
134        if not file_id:
135            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
136        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
137        return self._get(
138            f"/vector_stores/{vector_store_id}/files/{file_id}",
139            options=make_request_options(
140                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
141            ),
142            cast_to=VectorStoreFile,
143        )
144
145    def update(
146        self,
147        file_id: str,
148        *,
149        vector_store_id: str,
150        attributes: Optional[Dict[str, Union[str, float, bool]]],
151        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
152        # The extra values given here take precedence over values defined on the client or passed to this method.
153        extra_headers: Headers | None = None,
154        extra_query: Query | None = None,
155        extra_body: Body | None = None,
156        timeout: float | httpx.Timeout | None | NotGiven = not_given,
157    ) -> VectorStoreFile:
158        """
159        Update attributes on a vector store file.
160
161        Args:
162          attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful
163              for storing additional information about the object in a structured format, and
164              querying for objects via API or the dashboard. Keys are strings with a maximum
165              length of 64 characters. Values are strings with a maximum length of 512
166              characters, booleans, or numbers.
167
168          extra_headers: Send extra headers
169
170          extra_query: Add additional query parameters to the request
171
172          extra_body: Add additional JSON properties to the request
173
174          timeout: Override the client-level default timeout for this request, in seconds
175        """
176        if not vector_store_id:
177            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
178        if not file_id:
179            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
180        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
181        return self._post(
182            f"/vector_stores/{vector_store_id}/files/{file_id}",
183            body=maybe_transform({"attributes": attributes}, file_update_params.FileUpdateParams),
184            options=make_request_options(
185                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
186            ),
187            cast_to=VectorStoreFile,
188        )
189
190    def list(
191        self,
192        vector_store_id: str,
193        *,
194        after: str | Omit = omit,
195        before: str | Omit = omit,
196        filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit,
197        limit: int | Omit = omit,
198        order: Literal["asc", "desc"] | Omit = omit,
199        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
200        # The extra values given here take precedence over values defined on the client or passed to this method.
201        extra_headers: Headers | None = None,
202        extra_query: Query | None = None,
203        extra_body: Body | None = None,
204        timeout: float | httpx.Timeout | None | NotGiven = not_given,
205    ) -> SyncCursorPage[VectorStoreFile]:
206        """
207        Returns a list of vector store files.
208
209        Args:
210          after: A cursor for use in pagination. `after` is an object ID that defines your place
211              in the list. For instance, if you make a list request and receive 100 objects,
212              ending with obj_foo, your subsequent call can include after=obj_foo in order to
213              fetch the next page of the list.
214
215          before: A cursor for use in pagination. `before` is an object ID that defines your place
216              in the list. For instance, if you make a list request and receive 100 objects,
217              starting with obj_foo, your subsequent call can include before=obj_foo in order
218              to fetch the previous page of the list.
219
220          filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`.
221
222          limit: A limit on the number of objects to be returned. Limit can range between 1 and
223              100, and the default is 20.
224
225          order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending
226              order and `desc` for descending order.
227
228          extra_headers: Send extra headers
229
230          extra_query: Add additional query parameters to the request
231
232          extra_body: Add additional JSON properties to the request
233
234          timeout: Override the client-level default timeout for this request, in seconds
235        """
236        if not vector_store_id:
237            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
238        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
239        return self._get_api_list(
240            f"/vector_stores/{vector_store_id}/files",
241            page=SyncCursorPage[VectorStoreFile],
242            options=make_request_options(
243                extra_headers=extra_headers,
244                extra_query=extra_query,
245                extra_body=extra_body,
246                timeout=timeout,
247                query=maybe_transform(
248                    {
249                        "after": after,
250                        "before": before,
251                        "filter": filter,
252                        "limit": limit,
253                        "order": order,
254                    },
255                    file_list_params.FileListParams,
256                ),
257            ),
258            model=VectorStoreFile,
259        )
260
261    def delete(
262        self,
263        file_id: str,
264        *,
265        vector_store_id: str,
266        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
267        # The extra values given here take precedence over values defined on the client or passed to this method.
268        extra_headers: Headers | None = None,
269        extra_query: Query | None = None,
270        extra_body: Body | None = None,
271        timeout: float | httpx.Timeout | None | NotGiven = not_given,
272    ) -> VectorStoreFileDeleted:
273        """Delete a vector store file.
274
275        This will remove the file from the vector store but
276        the file itself will not be deleted. To delete the file, use the
277        [delete file](https://platform.openai.com/docs/api-reference/files/delete)
278        endpoint.
279
280        Args:
281          extra_headers: Send extra headers
282
283          extra_query: Add additional query parameters to the request
284
285          extra_body: Add additional JSON properties to the request
286
287          timeout: Override the client-level default timeout for this request, in seconds
288        """
289        if not vector_store_id:
290            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
291        if not file_id:
292            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
293        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
294        return self._delete(
295            f"/vector_stores/{vector_store_id}/files/{file_id}",
296            options=make_request_options(
297                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
298            ),
299            cast_to=VectorStoreFileDeleted,
300        )
301
302    def create_and_poll(
303        self,
304        file_id: str,
305        *,
306        vector_store_id: str,
307        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
308        poll_interval_ms: int | Omit = omit,
309        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
310    ) -> VectorStoreFile:
311        """Attach a file to the given vector store and wait for it to be processed."""
312        self.create(
313            vector_store_id=vector_store_id, file_id=file_id, chunking_strategy=chunking_strategy, attributes=attributes
314        )
315
316        return self.poll(
317            file_id,
318            vector_store_id=vector_store_id,
319            poll_interval_ms=poll_interval_ms,
320        )
321
322    def poll(
323        self,
324        file_id: str,
325        *,
326        vector_store_id: str,
327        poll_interval_ms: int | Omit = omit,
328    ) -> VectorStoreFile:
329        """Wait for the vector store file to finish processing.
330
331        Note: this will return even if the file failed to process, you need to check
332        file.last_error and file.status to handle these cases
333        """
334        headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"}
335        if is_given(poll_interval_ms):
336            headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms)
337
338        while True:
339            response = self.with_raw_response.retrieve(
340                file_id,
341                vector_store_id=vector_store_id,
342                extra_headers=headers,
343            )
344
345            file = response.parse()
346            if file.status == "in_progress":
347                if not is_given(poll_interval_ms):
348                    from_header = response.headers.get("openai-poll-after-ms")
349                    if from_header is not None:
350                        poll_interval_ms = int(from_header)
351                    else:
352                        poll_interval_ms = 1000
353
354                self._sleep(poll_interval_ms / 1000)
355            elif file.status == "cancelled" or file.status == "completed" or file.status == "failed":
356                return file
357            else:
358                if TYPE_CHECKING:  # type: ignore[unreachable]
359                    assert_never(file.status)
360                else:
361                    return file
362
363    def upload(
364        self,
365        *,
366        vector_store_id: str,
367        file: FileTypes,
368        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
369    ) -> VectorStoreFile:
370        """Upload a file to the `files` API and then attach it to the given vector store.
371
372        Note the file will be asynchronously processed (you can use the alternative
373        polling helper method to wait for processing to complete).
374        """
375        file_obj = self._client.files.create(file=file, purpose="assistants")
376        return self.create(vector_store_id=vector_store_id, file_id=file_obj.id, chunking_strategy=chunking_strategy)
377
378    def upload_and_poll(
379        self,
380        *,
381        vector_store_id: str,
382        file: FileTypes,
383        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
384        poll_interval_ms: int | Omit = omit,
385        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
386    ) -> VectorStoreFile:
387        """Add a file to a vector store and poll until processing is complete."""
388        file_obj = self._client.files.create(file=file, purpose="assistants")
389        return self.create_and_poll(
390            vector_store_id=vector_store_id,
391            file_id=file_obj.id,
392            chunking_strategy=chunking_strategy,
393            poll_interval_ms=poll_interval_ms,
394            attributes=attributes,
395        )
396
397    def content(
398        self,
399        file_id: str,
400        *,
401        vector_store_id: str,
402        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
403        # The extra values given here take precedence over values defined on the client or passed to this method.
404        extra_headers: Headers | None = None,
405        extra_query: Query | None = None,
406        extra_body: Body | None = None,
407        timeout: float | httpx.Timeout | None | NotGiven = not_given,
408    ) -> SyncPage[FileContentResponse]:
409        """
410        Retrieve the parsed contents of a vector store file.
411
412        Args:
413          extra_headers: Send extra headers
414
415          extra_query: Add additional query parameters to the request
416
417          extra_body: Add additional JSON properties to the request
418
419          timeout: Override the client-level default timeout for this request, in seconds
420        """
421        if not vector_store_id:
422            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
423        if not file_id:
424            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
425        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
426        return self._get_api_list(
427            f"/vector_stores/{vector_store_id}/files/{file_id}/content",
428            page=SyncPage[FileContentResponse],
429            options=make_request_options(
430                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
431            ),
432            model=FileContentResponse,
433        )
434
435
436class AsyncFiles(AsyncAPIResource):
437    @cached_property
438    def with_raw_response(self) -> AsyncFilesWithRawResponse:
439        """
440        This property can be used as a prefix for any HTTP method call to return
441        the raw response object instead of the parsed content.
442
443        For more information, see https://www.github.com/openai/openai-python#accessing-raw-response-data-eg-headers
444        """
445        return AsyncFilesWithRawResponse(self)
446
447    @cached_property
448    def with_streaming_response(self) -> AsyncFilesWithStreamingResponse:
449        """
450        An alternative to `.with_raw_response` that doesn't eagerly read the response body.
451
452        For more information, see https://www.github.com/openai/openai-python#with_streaming_response
453        """
454        return AsyncFilesWithStreamingResponse(self)
455
456    async def create(
457        self,
458        vector_store_id: str,
459        *,
460        file_id: str,
461        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
462        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
463        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
464        # The extra values given here take precedence over values defined on the client or passed to this method.
465        extra_headers: Headers | None = None,
466        extra_query: Query | None = None,
467        extra_body: Body | None = None,
468        timeout: float | httpx.Timeout | None | NotGiven = not_given,
469    ) -> VectorStoreFile:
470        """
471        Create a vector store file by attaching a
472        [File](https://platform.openai.com/docs/api-reference/files) to a
473        [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object).
474
475        Args:
476          file_id: A [File](https://platform.openai.com/docs/api-reference/files) ID that the
477              vector store should use. Useful for tools like `file_search` that can access
478              files.
479
480          attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful
481              for storing additional information about the object in a structured format, and
482              querying for objects via API or the dashboard. Keys are strings with a maximum
483              length of 64 characters. Values are strings with a maximum length of 512
484              characters, booleans, or numbers.
485
486          chunking_strategy: The chunking strategy used to chunk the file(s). If not set, will use the `auto`
487              strategy. Only applicable if `file_ids` is non-empty.
488
489          extra_headers: Send extra headers
490
491          extra_query: Add additional query parameters to the request
492
493          extra_body: Add additional JSON properties to the request
494
495          timeout: Override the client-level default timeout for this request, in seconds
496        """
497        if not vector_store_id:
498            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
499        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
500        return await self._post(
501            f"/vector_stores/{vector_store_id}/files",
502            body=await async_maybe_transform(
503                {
504                    "file_id": file_id,
505                    "attributes": attributes,
506                    "chunking_strategy": chunking_strategy,
507                },
508                file_create_params.FileCreateParams,
509            ),
510            options=make_request_options(
511                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
512            ),
513            cast_to=VectorStoreFile,
514        )
515
516    async def retrieve(
517        self,
518        file_id: str,
519        *,
520        vector_store_id: str,
521        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
522        # The extra values given here take precedence over values defined on the client or passed to this method.
523        extra_headers: Headers | None = None,
524        extra_query: Query | None = None,
525        extra_body: Body | None = None,
526        timeout: float | httpx.Timeout | None | NotGiven = not_given,
527    ) -> VectorStoreFile:
528        """
529        Retrieves a vector store file.
530
531        Args:
532          extra_headers: Send extra headers
533
534          extra_query: Add additional query parameters to the request
535
536          extra_body: Add additional JSON properties to the request
537
538          timeout: Override the client-level default timeout for this request, in seconds
539        """
540        if not vector_store_id:
541            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
542        if not file_id:
543            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
544        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
545        return await self._get(
546            f"/vector_stores/{vector_store_id}/files/{file_id}",
547            options=make_request_options(
548                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
549            ),
550            cast_to=VectorStoreFile,
551        )
552
553    async def update(
554        self,
555        file_id: str,
556        *,
557        vector_store_id: str,
558        attributes: Optional[Dict[str, Union[str, float, bool]]],
559        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
560        # The extra values given here take precedence over values defined on the client or passed to this method.
561        extra_headers: Headers | None = None,
562        extra_query: Query | None = None,
563        extra_body: Body | None = None,
564        timeout: float | httpx.Timeout | None | NotGiven = not_given,
565    ) -> VectorStoreFile:
566        """
567        Update attributes on a vector store file.
568
569        Args:
570          attributes: Set of 16 key-value pairs that can be attached to an object. This can be useful
571              for storing additional information about the object in a structured format, and
572              querying for objects via API or the dashboard. Keys are strings with a maximum
573              length of 64 characters. Values are strings with a maximum length of 512
574              characters, booleans, or numbers.
575
576          extra_headers: Send extra headers
577
578          extra_query: Add additional query parameters to the request
579
580          extra_body: Add additional JSON properties to the request
581
582          timeout: Override the client-level default timeout for this request, in seconds
583        """
584        if not vector_store_id:
585            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
586        if not file_id:
587            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
588        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
589        return await self._post(
590            f"/vector_stores/{vector_store_id}/files/{file_id}",
591            body=await async_maybe_transform({"attributes": attributes}, file_update_params.FileUpdateParams),
592            options=make_request_options(
593                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
594            ),
595            cast_to=VectorStoreFile,
596        )
597
598    def list(
599        self,
600        vector_store_id: str,
601        *,
602        after: str | Omit = omit,
603        before: str | Omit = omit,
604        filter: Literal["in_progress", "completed", "failed", "cancelled"] | Omit = omit,
605        limit: int | Omit = omit,
606        order: Literal["asc", "desc"] | Omit = omit,
607        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
608        # The extra values given here take precedence over values defined on the client or passed to this method.
609        extra_headers: Headers | None = None,
610        extra_query: Query | None = None,
611        extra_body: Body | None = None,
612        timeout: float | httpx.Timeout | None | NotGiven = not_given,
613    ) -> AsyncPaginator[VectorStoreFile, AsyncCursorPage[VectorStoreFile]]:
614        """
615        Returns a list of vector store files.
616
617        Args:
618          after: A cursor for use in pagination. `after` is an object ID that defines your place
619              in the list. For instance, if you make a list request and receive 100 objects,
620              ending with obj_foo, your subsequent call can include after=obj_foo in order to
621              fetch the next page of the list.
622
623          before: A cursor for use in pagination. `before` is an object ID that defines your place
624              in the list. For instance, if you make a list request and receive 100 objects,
625              starting with obj_foo, your subsequent call can include before=obj_foo in order
626              to fetch the previous page of the list.
627
628          filter: Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`.
629
630          limit: A limit on the number of objects to be returned. Limit can range between 1 and
631              100, and the default is 20.
632
633          order: Sort order by the `created_at` timestamp of the objects. `asc` for ascending
634              order and `desc` for descending order.
635
636          extra_headers: Send extra headers
637
638          extra_query: Add additional query parameters to the request
639
640          extra_body: Add additional JSON properties to the request
641
642          timeout: Override the client-level default timeout for this request, in seconds
643        """
644        if not vector_store_id:
645            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
646        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
647        return self._get_api_list(
648            f"/vector_stores/{vector_store_id}/files",
649            page=AsyncCursorPage[VectorStoreFile],
650            options=make_request_options(
651                extra_headers=extra_headers,
652                extra_query=extra_query,
653                extra_body=extra_body,
654                timeout=timeout,
655                query=maybe_transform(
656                    {
657                        "after": after,
658                        "before": before,
659                        "filter": filter,
660                        "limit": limit,
661                        "order": order,
662                    },
663                    file_list_params.FileListParams,
664                ),
665            ),
666            model=VectorStoreFile,
667        )
668
669    async def delete(
670        self,
671        file_id: str,
672        *,
673        vector_store_id: str,
674        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
675        # The extra values given here take precedence over values defined on the client or passed to this method.
676        extra_headers: Headers | None = None,
677        extra_query: Query | None = None,
678        extra_body: Body | None = None,
679        timeout: float | httpx.Timeout | None | NotGiven = not_given,
680    ) -> VectorStoreFileDeleted:
681        """Delete a vector store file.
682
683        This will remove the file from the vector store but
684        the file itself will not be deleted. To delete the file, use the
685        [delete file](https://platform.openai.com/docs/api-reference/files/delete)
686        endpoint.
687
688        Args:
689          extra_headers: Send extra headers
690
691          extra_query: Add additional query parameters to the request
692
693          extra_body: Add additional JSON properties to the request
694
695          timeout: Override the client-level default timeout for this request, in seconds
696        """
697        if not vector_store_id:
698            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
699        if not file_id:
700            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
701        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
702        return await self._delete(
703            f"/vector_stores/{vector_store_id}/files/{file_id}",
704            options=make_request_options(
705                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
706            ),
707            cast_to=VectorStoreFileDeleted,
708        )
709
710    async def create_and_poll(
711        self,
712        file_id: str,
713        *,
714        vector_store_id: str,
715        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
716        poll_interval_ms: int | Omit = omit,
717        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
718    ) -> VectorStoreFile:
719        """Attach a file to the given vector store and wait for it to be processed."""
720        await self.create(
721            vector_store_id=vector_store_id, file_id=file_id, chunking_strategy=chunking_strategy, attributes=attributes
722        )
723
724        return await self.poll(
725            file_id,
726            vector_store_id=vector_store_id,
727            poll_interval_ms=poll_interval_ms,
728        )
729
730    async def poll(
731        self,
732        file_id: str,
733        *,
734        vector_store_id: str,
735        poll_interval_ms: int | Omit = omit,
736    ) -> VectorStoreFile:
737        """Wait for the vector store file to finish processing.
738
739        Note: this will return even if the file failed to process, you need to check
740        file.last_error and file.status to handle these cases
741        """
742        headers: dict[str, str] = {"X-Stainless-Poll-Helper": "true"}
743        if is_given(poll_interval_ms):
744            headers["X-Stainless-Custom-Poll-Interval"] = str(poll_interval_ms)
745
746        while True:
747            response = await self.with_raw_response.retrieve(
748                file_id,
749                vector_store_id=vector_store_id,
750                extra_headers=headers,
751            )
752
753            file = response.parse()
754            if file.status == "in_progress":
755                if not is_given(poll_interval_ms):
756                    from_header = response.headers.get("openai-poll-after-ms")
757                    if from_header is not None:
758                        poll_interval_ms = int(from_header)
759                    else:
760                        poll_interval_ms = 1000
761
762                await self._sleep(poll_interval_ms / 1000)
763            elif file.status == "cancelled" or file.status == "completed" or file.status == "failed":
764                return file
765            else:
766                if TYPE_CHECKING:  # type: ignore[unreachable]
767                    assert_never(file.status)
768                else:
769                    return file
770
771    async def upload(
772        self,
773        *,
774        vector_store_id: str,
775        file: FileTypes,
776        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
777    ) -> VectorStoreFile:
778        """Upload a file to the `files` API and then attach it to the given vector store.
779
780        Note the file will be asynchronously processed (you can use the alternative
781        polling helper method to wait for processing to complete).
782        """
783        file_obj = await self._client.files.create(file=file, purpose="assistants")
784        return await self.create(
785            vector_store_id=vector_store_id, file_id=file_obj.id, chunking_strategy=chunking_strategy
786        )
787
788    async def upload_and_poll(
789        self,
790        *,
791        vector_store_id: str,
792        file: FileTypes,
793        attributes: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit,
794        poll_interval_ms: int | Omit = omit,
795        chunking_strategy: FileChunkingStrategyParam | Omit = omit,
796    ) -> VectorStoreFile:
797        """Add a file to a vector store and poll until processing is complete."""
798        file_obj = await self._client.files.create(file=file, purpose="assistants")
799        return await self.create_and_poll(
800            vector_store_id=vector_store_id,
801            file_id=file_obj.id,
802            poll_interval_ms=poll_interval_ms,
803            chunking_strategy=chunking_strategy,
804            attributes=attributes,
805        )
806
807    def content(
808        self,
809        file_id: str,
810        *,
811        vector_store_id: str,
812        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
813        # The extra values given here take precedence over values defined on the client or passed to this method.
814        extra_headers: Headers | None = None,
815        extra_query: Query | None = None,
816        extra_body: Body | None = None,
817        timeout: float | httpx.Timeout | None | NotGiven = not_given,
818    ) -> AsyncPaginator[FileContentResponse, AsyncPage[FileContentResponse]]:
819        """
820        Retrieve the parsed contents of a vector store file.
821
822        Args:
823          extra_headers: Send extra headers
824
825          extra_query: Add additional query parameters to the request
826
827          extra_body: Add additional JSON properties to the request
828
829          timeout: Override the client-level default timeout for this request, in seconds
830        """
831        if not vector_store_id:
832            raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}")
833        if not file_id:
834            raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
835        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
836        return self._get_api_list(
837            f"/vector_stores/{vector_store_id}/files/{file_id}/content",
838            page=AsyncPage[FileContentResponse],
839            options=make_request_options(
840                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
841            ),
842            model=FileContentResponse,
843        )
844
845
846class FilesWithRawResponse:
847    def __init__(self, files: Files) -> None:
848        self._files = files
849
850        self.create = _legacy_response.to_raw_response_wrapper(
851            files.create,
852        )
853        self.retrieve = _legacy_response.to_raw_response_wrapper(
854            files.retrieve,
855        )
856        self.update = _legacy_response.to_raw_response_wrapper(
857            files.update,
858        )
859        self.list = _legacy_response.to_raw_response_wrapper(
860            files.list,
861        )
862        self.delete = _legacy_response.to_raw_response_wrapper(
863            files.delete,
864        )
865        self.content = _legacy_response.to_raw_response_wrapper(
866            files.content,
867        )
868
869
870class AsyncFilesWithRawResponse:
871    def __init__(self, files: AsyncFiles) -> None:
872        self._files = files
873
874        self.create = _legacy_response.async_to_raw_response_wrapper(
875            files.create,
876        )
877        self.retrieve = _legacy_response.async_to_raw_response_wrapper(
878            files.retrieve,
879        )
880        self.update = _legacy_response.async_to_raw_response_wrapper(
881            files.update,
882        )
883        self.list = _legacy_response.async_to_raw_response_wrapper(
884            files.list,
885        )
886        self.delete = _legacy_response.async_to_raw_response_wrapper(
887            files.delete,
888        )
889        self.content = _legacy_response.async_to_raw_response_wrapper(
890            files.content,
891        )
892
893
894class FilesWithStreamingResponse:
895    def __init__(self, files: Files) -> None:
896        self._files = files
897
898        self.create = to_streamed_response_wrapper(
899            files.create,
900        )
901        self.retrieve = to_streamed_response_wrapper(
902            files.retrieve,
903        )
904        self.update = to_streamed_response_wrapper(
905            files.update,
906        )
907        self.list = to_streamed_response_wrapper(
908            files.list,
909        )
910        self.delete = to_streamed_response_wrapper(
911            files.delete,
912        )
913        self.content = to_streamed_response_wrapper(
914            files.content,
915        )
916
917
918class AsyncFilesWithStreamingResponse:
919    def __init__(self, files: AsyncFiles) -> None:
920        self._files = files
921
922        self.create = async_to_streamed_response_wrapper(
923            files.create,
924        )
925        self.retrieve = async_to_streamed_response_wrapper(
926            files.retrieve,
927        )
928        self.update = async_to_streamed_response_wrapper(
929            files.update,
930        )
931        self.list = async_to_streamed_response_wrapper(
932            files.list,
933        )
934        self.delete = async_to_streamed_response_wrapper(
935            files.delete,
936        )
937        self.content = async_to_streamed_response_wrapper(
938            files.content,
939        )