Commit 79a0b401

Stainless Bot <107565488+stainless-bot@users.noreply.github.com>
2024-05-10 04:19:42
feat(api): add message image content (#1405)
1 parent 064a34a
src/openai/resources/beta/threads/messages.py
@@ -2,7 +2,7 @@
 
 from __future__ import annotations
 
-from typing import Iterable, Optional
+from typing import Union, Iterable, Optional
 from typing_extensions import Literal
 
 import httpx
@@ -24,6 +24,7 @@ from ...._base_client import (
 from ....types.beta.threads import message_list_params, message_create_params, message_update_params
 from ....types.beta.threads.message import Message
 from ....types.beta.threads.message_deleted import MessageDeleted
+from ....types.beta.threads.message_content_part_param import MessageContentPartParam
 
 __all__ = ["Messages", "AsyncMessages"]
 
@@ -41,7 +42,7 @@ class Messages(SyncAPIResource):
         self,
         thread_id: str,
         *,
-        content: str,
+        content: Union[str, Iterable[MessageContentPartParam]],
         role: Literal["user", "assistant"],
         attachments: Optional[Iterable[message_create_params.Attachment]] | NotGiven = NOT_GIVEN,
         metadata: Optional[object] | NotGiven = NOT_GIVEN,
@@ -56,7 +57,7 @@ class Messages(SyncAPIResource):
         Create a message.
 
         Args:
-          content: The content of the message.
+          content: The text contents of the message.
 
           role:
               The role of the entity that is creating the message. Allowed values include:
@@ -304,7 +305,7 @@ class AsyncMessages(AsyncAPIResource):
         self,
         thread_id: str,
         *,
-        content: str,
+        content: Union[str, Iterable[MessageContentPartParam]],
         role: Literal["user", "assistant"],
         attachments: Optional[Iterable[message_create_params.Attachment]] | NotGiven = NOT_GIVEN,
         metadata: Optional[object] | NotGiven = NOT_GIVEN,
@@ -319,7 +320,7 @@ class AsyncMessages(AsyncAPIResource):
         Create a message.
 
         Args:
-          content: The content of the message.
+          content: The text contents of the message.
 
           role:
               The role of the entity that is creating the message. Allowed values include:
src/openai/resources/files.py
@@ -81,7 +81,8 @@ class Files(SyncAPIResource):
 
               Use "assistants" for
               [Assistants](https://platform.openai.com/docs/api-reference/assistants) and
-              [Messages](https://platform.openai.com/docs/api-reference/messages), "batch" for
+              [Message](https://platform.openai.com/docs/api-reference/messages) files,
+              "vision" for Assistants image file inputs, "batch" for
               [Batch API](https://platform.openai.com/docs/guides/batch), and "fine-tune" for
               [Fine-tuning](https://platform.openai.com/docs/api-reference/fine-tuning).
 
@@ -353,7 +354,8 @@ class AsyncFiles(AsyncAPIResource):
 
               Use "assistants" for
               [Assistants](https://platform.openai.com/docs/api-reference/assistants) and
-              [Messages](https://platform.openai.com/docs/api-reference/messages), "batch" for
+              [Message](https://platform.openai.com/docs/api-reference/messages) files,
+              "vision" for Assistants image file inputs, "batch" for
               [Batch API](https://platform.openai.com/docs/guides/batch), and "fine-tune" for
               [Fine-tuning](https://platform.openai.com/docs/api-reference/fine-tuning).
 
src/openai/types/beta/threads/__init__.py
@@ -5,16 +5,20 @@ from __future__ import annotations
 from .run import Run as Run
 from .text import Text as Text
 from .message import Message as Message
+from .image_url import ImageURL as ImageURL
 from .annotation import Annotation as Annotation
 from .image_file import ImageFile as ImageFile
 from .run_status import RunStatus as RunStatus
 from .text_delta import TextDelta as TextDelta
 from .message_delta import MessageDelta as MessageDelta
+from .image_url_delta import ImageURLDelta as ImageURLDelta
+from .image_url_param import ImageURLParam as ImageURLParam
 from .message_content import MessageContent as MessageContent
 from .message_deleted import MessageDeleted as MessageDeleted
 from .run_list_params import RunListParams as RunListParams
 from .annotation_delta import AnnotationDelta as AnnotationDelta
 from .image_file_delta import ImageFileDelta as ImageFileDelta
+from .image_file_param import ImageFileParam as ImageFileParam
 from .text_delta_block import TextDeltaBlock as TextDeltaBlock
 from .run_create_params import RunCreateParams as RunCreateParams
 from .run_update_params import RunUpdateParams as RunUpdateParams
@@ -22,13 +26,19 @@ from .text_content_block import TextContentBlock as TextContentBlock
 from .message_delta_event import MessageDeltaEvent as MessageDeltaEvent
 from .message_list_params import MessageListParams as MessageListParams
 from .file_path_annotation import FilePathAnnotation as FilePathAnnotation
+from .image_url_delta_block import ImageURLDeltaBlock as ImageURLDeltaBlock
 from .message_content_delta import MessageContentDelta as MessageContentDelta
 from .message_create_params import MessageCreateParams as MessageCreateParams
 from .message_update_params import MessageUpdateParams as MessageUpdateParams
 from .image_file_delta_block import ImageFileDeltaBlock as ImageFileDeltaBlock
+from .image_url_content_block import ImageURLContentBlock as ImageURLContentBlock
 from .file_citation_annotation import FileCitationAnnotation as FileCitationAnnotation
 from .image_file_content_block import ImageFileContentBlock as ImageFileContentBlock
+from .text_content_block_param import TextContentBlockParam as TextContentBlockParam
 from .file_path_delta_annotation import FilePathDeltaAnnotation as FilePathDeltaAnnotation
+from .message_content_part_param import MessageContentPartParam as MessageContentPartParam
+from .image_url_content_block_param import ImageURLContentBlockParam as ImageURLContentBlockParam
 from .file_citation_delta_annotation import FileCitationDeltaAnnotation as FileCitationDeltaAnnotation
+from .image_file_content_block_param import ImageFileContentBlockParam as ImageFileContentBlockParam
 from .run_submit_tool_outputs_params import RunSubmitToolOutputsParams as RunSubmitToolOutputsParams
 from .required_action_function_tool_call import RequiredActionFunctionToolCall as RequiredActionFunctionToolCall
src/openai/types/beta/threads/image_file.py
@@ -1,6 +1,7 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
-
+from typing import Optional
+from typing_extensions import Literal
 
 from ...._models import BaseModel
 
@@ -11,5 +12,12 @@ class ImageFile(BaseModel):
     file_id: str
     """
     The [File](https://platform.openai.com/docs/api-reference/files) ID of the image
-    in the message content.
+    in the message content. Set `purpose="vision"` when uploading the File if you
+    need to later display the file content.
+    """
+
+    detail: Optional[Literal["auto", "low", "high"]] = None
+    """Specifies the detail level of the image if specified by the user.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`.
     """
src/openai/types/beta/threads/image_file_content_block_param.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 .image_file_param import ImageFileParam
+
+__all__ = ["ImageFileContentBlockParam"]
+
+
+class ImageFileContentBlockParam(TypedDict, total=False):
+    image_file: Required[ImageFileParam]
+
+    type: Required[Literal["image_file"]]
+    """Always `image_file`."""
src/openai/types/beta/threads/image_file_delta.py
@@ -1,6 +1,7 @@
 # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
 
 from typing import Optional
+from typing_extensions import Literal
 
 from ...._models import BaseModel
 
@@ -8,8 +9,15 @@ __all__ = ["ImageFileDelta"]
 
 
 class ImageFileDelta(BaseModel):
+    detail: Optional[Literal["auto", "low", "high"]] = None
+    """Specifies the detail level of the image if specified by the user.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`.
+    """
+
     file_id: Optional[str] = None
     """
     The [File](https://platform.openai.com/docs/api-reference/files) ID of the image
-    in the message content.
+    in the message content. Set `purpose="vision"` when uploading the File if you
+    need to later display the file content.
     """
src/openai/types/beta/threads/image_file_param.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ImageFileParam"]
+
+
+class ImageFileParam(TypedDict, total=False):
+    file_id: Required[str]
+    """
+    The [File](https://platform.openai.com/docs/api-reference/files) ID of the image
+    in the message content. Set `purpose="vision"` when uploading the File if you
+    need to later display the file content.
+    """
+
+    detail: Literal["auto", "low", "high"]
+    """Specifies the detail level of the image if specified by the user.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`.
+    """
src/openai/types/beta/threads/image_url.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["ImageURL"]
+
+
+class ImageURL(BaseModel):
+    url: str
+    """
+    The external URL of the image, must be a supported image types: jpeg, jpg, png,
+    gif, webp.
+    """
+
+    detail: Optional[Literal["auto", "low", "high"]] = None
+    """Specifies the detail level of the image.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`. Default
+    value is `auto`
+    """
src/openai/types/beta/threads/image_url_content_block.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .image_url import ImageURL
+from ...._models import BaseModel
+
+__all__ = ["ImageURLContentBlock"]
+
+
+class ImageURLContentBlock(BaseModel):
+    image_url: ImageURL
+
+    type: Literal["image_url"]
+    """The type of the content part."""
src/openai/types/beta/threads/image_url_content_block_param.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 .image_url_param import ImageURLParam
+
+__all__ = ["ImageURLContentBlockParam"]
+
+
+class ImageURLContentBlockParam(TypedDict, total=False):
+    image_url: Required[ImageURLParam]
+
+    type: Required[Literal["image_url"]]
+    """The type of the content part."""
src/openai/types/beta/threads/image_url_delta.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["ImageURLDelta"]
+
+
+class ImageURLDelta(BaseModel):
+    detail: Optional[Literal["auto", "low", "high"]] = None
+    """Specifies the detail level of the image.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`.
+    """
+
+    url: Optional[str] = None
+    """
+    The URL of the image, must be a supported image types: jpeg, jpg, png, gif,
+    webp.
+    """
src/openai/types/beta/threads/image_url_delta_block.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+from .image_url_delta import ImageURLDelta
+
+__all__ = ["ImageURLDeltaBlock"]
+
+
+class ImageURLDeltaBlock(BaseModel):
+    index: int
+    """The index of the content part in the message."""
+
+    type: Literal["image_url"]
+    """Always `image_url`."""
+
+    image_url: Optional[ImageURLDelta] = None
src/openai/types/beta/threads/image_url_param.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ImageURLParam"]
+
+
+class ImageURLParam(TypedDict, total=False):
+    url: Required[str]
+    """
+    The external URL of the image, must be a supported image types: jpeg, jpg, png,
+    gif, webp.
+    """
+
+    detail: Literal["auto", "low", "high"]
+    """Specifies the detail level of the image.
+
+    `low` uses fewer tokens, you can opt in to high resolution using `high`. Default
+    value is `auto`
+    """
src/openai/types/beta/threads/message_content.py
@@ -5,8 +5,11 @@ from typing_extensions import Annotated
 
 from ...._utils import PropertyInfo
 from .text_content_block import TextContentBlock
+from .image_url_content_block import ImageURLContentBlock
 from .image_file_content_block import ImageFileContentBlock
 
 __all__ = ["MessageContent"]
 
-MessageContent = Annotated[Union[ImageFileContentBlock, TextContentBlock], PropertyInfo(discriminator="type")]
+MessageContent = Annotated[
+    Union[ImageFileContentBlock, ImageURLContentBlock, TextContentBlock], PropertyInfo(discriminator="type")
+]
src/openai/types/beta/threads/message_content_delta.py
@@ -5,8 +5,11 @@ from typing_extensions import Annotated
 
 from ...._utils import PropertyInfo
 from .text_delta_block import TextDeltaBlock
+from .image_url_delta_block import ImageURLDeltaBlock
 from .image_file_delta_block import ImageFileDeltaBlock
 
 __all__ = ["MessageContentDelta"]
 
-MessageContentDelta = Annotated[Union[ImageFileDeltaBlock, TextDeltaBlock], PropertyInfo(discriminator="type")]
+MessageContentDelta = Annotated[
+    Union[ImageFileDeltaBlock, TextDeltaBlock, ImageURLDeltaBlock], PropertyInfo(discriminator="type")
+]
src/openai/types/beta/threads/message_content_part_param.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+
+from .text_content_block_param import TextContentBlockParam
+from .image_url_content_block_param import ImageURLContentBlockParam
+from .image_file_content_block_param import ImageFileContentBlockParam
+
+__all__ = ["MessageContentPartParam"]
+
+MessageContentPartParam = Union[ImageFileContentBlockParam, ImageURLContentBlockParam, TextContentBlockParam]
src/openai/types/beta/threads/message_create_params.py
@@ -6,14 +6,15 @@ from typing import Union, Iterable, Optional
 from typing_extensions import Literal, Required, TypedDict
 
 from ..file_search_tool_param import FileSearchToolParam
+from .message_content_part_param import MessageContentPartParam
 from ..code_interpreter_tool_param import CodeInterpreterToolParam
 
 __all__ = ["MessageCreateParams", "Attachment", "AttachmentTool"]
 
 
 class MessageCreateParams(TypedDict, total=False):
-    content: Required[str]
-    """The content of the message."""
+    content: Required[Union[str, Iterable[MessageContentPartParam]]]
+    """The text contents of the message."""
 
     role: Required[Literal["user", "assistant"]]
     """The role of the entity that is creating the message. Allowed values include:
src/openai/types/beta/threads/run_create_params.py
@@ -7,6 +7,7 @@ from typing_extensions import Literal, Required, TypedDict
 
 from ..assistant_tool_param import AssistantToolParam
 from ..file_search_tool_param import FileSearchToolParam
+from .message_content_part_param import MessageContentPartParam
 from ..code_interpreter_tool_param import CodeInterpreterToolParam
 from ..assistant_tool_choice_option_param import AssistantToolChoiceOptionParam
 from ..assistant_response_format_option_param import AssistantResponseFormatOptionParam
@@ -175,8 +176,8 @@ class AdditionalMessageAttachment(TypedDict, total=False):
 
 
 class AdditionalMessage(TypedDict, total=False):
-    content: Required[str]
-    """The content of the message."""
+    content: Required[Union[str, Iterable[MessageContentPartParam]]]
+    """The text contents of the message."""
 
     role: Required[Literal["user", "assistant"]]
     """The role of the entity that is creating the message. Allowed values include:
src/openai/types/beta/threads/text_content_block_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["TextContentBlockParam"]
+
+
+class TextContentBlockParam(TypedDict, total=False):
+    text: Required[str]
+    """Text content to be sent to the model"""
+
+    type: Required[Literal["text"]]
+    """Always `text`."""
src/openai/types/beta/thread_create_and_run_params.py
@@ -9,6 +9,7 @@ from .function_tool_param import FunctionToolParam
 from .file_search_tool_param import FileSearchToolParam
 from .code_interpreter_tool_param import CodeInterpreterToolParam
 from .assistant_tool_choice_option_param import AssistantToolChoiceOptionParam
+from .threads.message_content_part_param import MessageContentPartParam
 from .assistant_response_format_option_param import AssistantResponseFormatOptionParam
 
 __all__ = [
@@ -184,8 +185,8 @@ class ThreadMessageAttachment(TypedDict, total=False):
 
 
 class ThreadMessage(TypedDict, total=False):
-    content: Required[str]
-    """The content of the message."""
+    content: Required[Union[str, Iterable[MessageContentPartParam]]]
+    """The text contents of the message."""
 
     role: Required[Literal["user", "assistant"]]
     """The role of the entity that is creating the message. Allowed values include:
src/openai/types/beta/thread_create_params.py
@@ -7,6 +7,7 @@ from typing_extensions import Literal, Required, TypedDict
 
 from .file_search_tool_param import FileSearchToolParam
 from .code_interpreter_tool_param import CodeInterpreterToolParam
+from .threads.message_content_part_param import MessageContentPartParam
 
 __all__ = [
     "ThreadCreateParams",
@@ -56,8 +57,8 @@ class MessageAttachment(TypedDict, total=False):
 
 
 class Message(TypedDict, total=False):
-    content: Required[str]
-    """The content of the message."""
+    content: Required[Union[str, Iterable[MessageContentPartParam]]]
+    """The text contents of the message."""
 
     role: Required[Literal["user", "assistant"]]
     """The role of the entity that is creating the message. Allowed values include:
src/openai/types/file_create_params.py
@@ -18,7 +18,8 @@ class FileCreateParams(TypedDict, total=False):
 
     Use "assistants" for
     [Assistants](https://platform.openai.com/docs/api-reference/assistants) and
-    [Messages](https://platform.openai.com/docs/api-reference/messages), "batch" for
+    [Message](https://platform.openai.com/docs/api-reference/messages) files,
+    "vision" for Assistants image file inputs, "batch" for
     [Batch API](https://platform.openai.com/docs/guides/batch), and "fine-tune" for
     [Fine-tuning](https://platform.openai.com/docs/api-reference/fine-tuning).
     """
src/openai/types/file_object.py
@@ -24,11 +24,13 @@ class FileObject(BaseModel):
     object: Literal["file"]
     """The object type, which is always `file`."""
 
-    purpose: Literal["assistants", "assistants_output", "batch", "batch_output", "fine-tune", "fine-tune-results"]
+    purpose: Literal[
+        "assistants", "assistants_output", "batch", "batch_output", "fine-tune", "fine-tune-results", "vision"
+    ]
     """The intended purpose of the file.
 
     Supported values are `assistants`, `assistants_output`, `batch`, `batch_output`,
-    `fine-tune`, and `fine-tune-results`.
+    `fine-tune`, `fine-tune-results` and `vision`.
     """
 
     status: Literal["uploaded", "processed", "error"]
tests/api_resources/beta/threads/test_messages.py
@@ -25,7 +25,7 @@ class TestMessages:
     def test_method_create(self, client: OpenAI) -> None:
         message = client.beta.threads.messages.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         )
         assert_matches_type(Message, message, path=["response"])
@@ -34,7 +34,7 @@ class TestMessages:
     def test_method_create_with_all_params(self, client: OpenAI) -> None:
         message = client.beta.threads.messages.create(
             "string",
-            content="x",
+            content="string",
             role="user",
             attachments=[
                 {
@@ -58,7 +58,7 @@ class TestMessages:
     def test_raw_response_create(self, client: OpenAI) -> None:
         response = client.beta.threads.messages.with_raw_response.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         )
 
@@ -71,7 +71,7 @@ class TestMessages:
     def test_streaming_response_create(self, client: OpenAI) -> None:
         with client.beta.threads.messages.with_streaming_response.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         ) as response:
             assert not response.is_closed
@@ -87,7 +87,7 @@ class TestMessages:
         with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"):
             client.beta.threads.messages.with_raw_response.create(
                 "",
-                content="x",
+                content="string",
                 role="user",
             )
 
@@ -302,7 +302,7 @@ class TestAsyncMessages:
     async def test_method_create(self, async_client: AsyncOpenAI) -> None:
         message = await async_client.beta.threads.messages.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         )
         assert_matches_type(Message, message, path=["response"])
@@ -311,7 +311,7 @@ class TestAsyncMessages:
     async def test_method_create_with_all_params(self, async_client: AsyncOpenAI) -> None:
         message = await async_client.beta.threads.messages.create(
             "string",
-            content="x",
+            content="string",
             role="user",
             attachments=[
                 {
@@ -335,7 +335,7 @@ class TestAsyncMessages:
     async def test_raw_response_create(self, async_client: AsyncOpenAI) -> None:
         response = await async_client.beta.threads.messages.with_raw_response.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         )
 
@@ -348,7 +348,7 @@ class TestAsyncMessages:
     async def test_streaming_response_create(self, async_client: AsyncOpenAI) -> None:
         async with async_client.beta.threads.messages.with_streaming_response.create(
             "string",
-            content="x",
+            content="string",
             role="user",
         ) as response:
             assert not response.is_closed
@@ -364,7 +364,7 @@ class TestAsyncMessages:
         with pytest.raises(ValueError, match=r"Expected a non-empty value for `thread_id` but received ''"):
             await async_client.beta.threads.messages.with_raw_response.create(
                 "",
-                content="x",
+                content="string",
                 role="user",
             )
 
tests/api_resources/beta/threads/test_runs.py
@@ -39,7 +39,7 @@ class TestRuns:
             additional_messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -70,7 +70,7 @@ class TestRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -101,7 +101,7 @@ class TestRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -202,7 +202,7 @@ class TestRuns:
             additional_messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -233,7 +233,7 @@ class TestRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -264,7 +264,7 @@ class TestRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -703,7 +703,7 @@ class TestAsyncRuns:
             additional_messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -734,7 +734,7 @@ class TestAsyncRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -765,7 +765,7 @@ class TestAsyncRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -866,7 +866,7 @@ class TestAsyncRuns:
             additional_messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -897,7 +897,7 @@ class TestAsyncRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -928,7 +928,7 @@ class TestAsyncRuns:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
tests/api_resources/beta/test_threads.py
@@ -32,7 +32,7 @@ class TestThreads:
             messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -63,7 +63,7 @@ class TestThreads:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -94,7 +94,7 @@ class TestThreads:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -309,7 +309,7 @@ class TestThreads:
                 "messages": [
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -340,7 +340,7 @@ class TestThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -371,7 +371,7 @@ class TestThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -477,7 +477,7 @@ class TestThreads:
                 "messages": [
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -508,7 +508,7 @@ class TestThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -539,7 +539,7 @@ class TestThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -637,7 +637,7 @@ class TestAsyncThreads:
             messages=[
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -668,7 +668,7 @@ class TestAsyncThreads:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -699,7 +699,7 @@ class TestAsyncThreads:
                 },
                 {
                     "role": "user",
-                    "content": "x",
+                    "content": "string",
                     "attachments": [
                         {
                             "file_id": "string",
@@ -914,7 +914,7 @@ class TestAsyncThreads:
                 "messages": [
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -945,7 +945,7 @@ class TestAsyncThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -976,7 +976,7 @@ class TestAsyncThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -1082,7 +1082,7 @@ class TestAsyncThreads:
                 "messages": [
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -1113,7 +1113,7 @@ class TestAsyncThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
@@ -1144,7 +1144,7 @@ class TestAsyncThreads:
                     },
                     {
                         "role": "user",
-                        "content": "x",
+                        "content": "string",
                         "attachments": [
                             {
                                 "file_id": "string",
.stats.yml
@@ -1,2 +1,2 @@
 configured_endpoints: 64
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-2e14236d4015bf3b956290ea8b656224a0c7b206a356c6af2a7ae43fdbceb04c.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-084b8f68408c6b689a55200a78bcf233769bfcd8e999d9fadaeb399152b05bcd.yml
api.md
@@ -374,14 +374,20 @@ from openai.types.beta.threads import (
     ImageFileContentBlock,
     ImageFileDelta,
     ImageFileDeltaBlock,
+    ImageURL,
+    ImageURLContentBlock,
+    ImageURLDelta,
+    ImageURLDeltaBlock,
     Message,
     MessageContent,
     MessageContentDelta,
+    MessageContentPartParam,
     MessageDeleted,
     MessageDelta,
     MessageDeltaEvent,
     Text,
     TextContentBlock,
+    TextContentBlockParam,
     TextDelta,
     TextDeltaBlock,
 )