diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 49df20d2b8..c4563a87af 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.21.0" + ".": "2.22.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 1d0140eb64..6d954e3ef8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 148 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-0db5326a0fb6a30ffad9242c72872c3388ef927e8a4549ddd20aec3420541209.yml -openapi_spec_hash: 9523fe30739802e15c88f4e7aac44e7f -config_hash: 948733484caf41e71093c6582dbc319c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-95886b357a553078e7f15505fe1c518c7daf11506946049c75eadf89d44da863.yml +openapi_spec_hash: 8dfdf1e1d1dbe58b236b89203aa2a1b0 +config_hash: 4c2841519fd72fe44c18de4c18db231f diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f558b3626..34bfd056ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 2.22.0 (2026-02-23) + +Full Changelog: [v2.21.0...v2.22.0](https://github.com/openai/openai-python/compare/v2.21.0...v2.22.0) + +### Features + +* **api:** websockets for responses api ([c01f6fb](https://github.com/openai/openai-python/commit/c01f6fb0d55b7454f73c4904ea7a1954553085dc)) + + +### Chores + +* **internal:** add request options to SSE classes ([cdb4315](https://github.com/openai/openai-python/commit/cdb4315ee29d5260bb373625d74cb523b4e3859c)) +* update mock server docs ([91f4da8](https://github.com/openai/openai-python/commit/91f4da80ec3dba5d3566961560dfd6feb9c2feb0)) + + +### Documentation + +* **api:** add batch size limit to file_batches parameter descriptions ([16ae76a](https://github.com/openai/openai-python/commit/16ae76a20a47f94c91ee2ca0b2ada274633abab3)) +* **api:** enhance method descriptions across audio, chat, realtime, skills, uploads, videos ([21f9e5a](https://github.com/openai/openai-python/commit/21f9e5aaf6ae27f0235fddb3ffa30fe73337f59b)) +* **api:** update safety_identifier documentation in chat completions and responses ([d74bfff](https://github.com/openai/openai-python/commit/d74bfff62c1c2b32d4dc88fd47ae7b1b2a962017)) + ## 2.21.0 (2026-02-13) Full Changelog: [v2.20.0...v2.21.0](https://github.com/openai/openai-python/compare/v2.20.0...v2.21.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c14e652328..3a1cf70bb8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```sh -# you will need npm installed -$ npx prism mock path/to/your/openapi.yml +$ ./scripts/mock ``` ```sh diff --git a/examples/responses/websocket.py b/examples/responses/websocket.py new file mode 100644 index 0000000000..2c51d8ef02 --- /dev/null +++ b/examples/responses/websocket.py @@ -0,0 +1,436 @@ +from __future__ import annotations + +import json +import argparse +from typing import TYPE_CHECKING, Dict, Union, Literal, Optional, TypedDict, NamedTuple, cast + +from openai import OpenAI +from openai.types.responses import ( + FunctionToolParam, + ToolChoiceOptions, + ResponseInputParam, + ResponseFailedEvent, + ResponseCompletedEvent, + ResponseInputItemParam, + ResponseIncompleteEvent, + ToolChoiceFunctionParam, +) + +if TYPE_CHECKING: + from openai.resources.responses.responses import ResponsesConnection + +ToolName = Literal["get_sku_inventory", "get_supplier_eta", "get_quality_alerts"] +ToolChoice = Union[ToolChoiceOptions, ToolChoiceFunctionParam] + + +class DemoTurn(TypedDict): + tool_name: ToolName + prompt: str + + +class SKUArguments(TypedDict): + sku: str + + +class SKUInventoryOutput(TypedDict): + sku: str + warehouse: str + on_hand_units: int + reserved_units: int + reorder_point: int + safety_stock: int + + +class SupplierShipment(TypedDict): + shipment_id: str + eta_date: str + quantity: int + risk: str + + +class SupplierETAOutput(TypedDict): + sku: str + supplier_shipments: list[SupplierShipment] + + +class QualityAlert(TypedDict): + alert_id: str + status: str + severity: str + summary: str + + +class QualityAlertsOutput(TypedDict): + sku: str + alerts: list[QualityAlert] + + +class FunctionCallOutputItem(TypedDict): + type: Literal["function_call_output"] + call_id: str + output: str + + +class FunctionCallRequest(NamedTuple): + name: str + arguments_json: str + call_id: str + + +class RunResponseResult(NamedTuple): + text: str + response_id: str + function_calls: list[FunctionCallRequest] + + +class RunTurnResult(NamedTuple): + assistant_text: str + response_id: str + + +ToolOutput = Union[SKUInventoryOutput, SupplierETAOutput, QualityAlertsOutput] + +TOOLS: list[FunctionToolParam] = [ + { + "type": "function", + "name": "get_sku_inventory", + "description": "Return froge pond inventory details for a SKU.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", + } + }, + "required": ["sku"], + "additionalProperties": False, + }, + }, + { + "type": "function", + "name": "get_supplier_eta", + "description": "Return tadpole supplier restock ETA data for a SKU.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", + } + }, + "required": ["sku"], + "additionalProperties": False, + }, + }, + { + "type": "function", + "name": "get_quality_alerts", + "description": "Return recent froge quality alerts for a SKU.", + "strict": True, + "parameters": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "description": "Stock-keeping unit identifier, such as sku-froge-lily-pad-deluxe.", + } + }, + "required": ["sku"], + "additionalProperties": False, + }, + }, +] + +DEMO_TURNS: list[DemoTurn] = [ + { + "tool_name": "get_sku_inventory", + "prompt": "Use get_sku_inventory for sku='sku-froge-lily-pad-deluxe' and summarize current pond stock health in one sentence.", + }, + { + "tool_name": "get_supplier_eta", + "prompt": "Now use get_supplier_eta for the same SKU and summarize restock ETA and tadpole shipment risk.", + }, + { + "tool_name": "get_quality_alerts", + "prompt": "Finally use get_quality_alerts for the same SKU and summarize unresolved froge quality concerns in one short paragraph.", + }, +] + +BETA_HEADER_VALUE = "responses_websockets=2026-02-06" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description=("Run a 3-turn Responses WebSocket demo with function calling and chained previous_response_id.") + ) + parser.add_argument("--model", default="gpt-5.2", help="Model used in the `response.create` payload.") + parser.add_argument( + "--use-beta-header", + action="store_true", + help=f"Include `OpenAI-Beta: {BETA_HEADER_VALUE}` for beta websocket behavior.", + ) + parser.add_argument( + "--show-events", + action="store_true", + help="Print non-text event types while streaming.", + ) + parser.add_argument( + "--show-tool-io", + action="store_true", + help="Print each tool call and tool output payload.", + ) + return parser.parse_args() + + +def parse_tool_name(name: str) -> ToolName: + if name not in {"get_sku_inventory", "get_supplier_eta", "get_quality_alerts"}: + raise ValueError(f"Unsupported tool requested: {name}") + return cast(ToolName, name) + + +def parse_sku_arguments(raw_arguments: str) -> SKUArguments: + parsed_raw = json.loads(raw_arguments) + if not isinstance(parsed_raw, dict): + raise ValueError(f"Tool arguments must be a JSON object: {raw_arguments}") + + parsed = cast(Dict[str, object], parsed_raw) + sku_value = parsed.get("sku") + if not isinstance(sku_value, str): + raise ValueError(f"Tool arguments must include a string `sku`: {raw_arguments}") + + return {"sku": sku_value} + + +def call_tool(name: ToolName, arguments: SKUArguments) -> ToolOutput: + sku = arguments["sku"] + + if name == "get_sku_inventory": + return { + "sku": sku, + "warehouse": "pond-west-1", + "on_hand_units": 84, + "reserved_units": 26, + "reorder_point": 60, + "safety_stock": 40, + } + + if name == "get_supplier_eta": + return { + "sku": sku, + "supplier_shipments": [ + { + "shipment_id": "frog_ship_2201", + "eta_date": "2026-02-24", + "quantity": 180, + "risk": "low", + }, + { + "shipment_id": "frog_ship_2205", + "eta_date": "2026-03-03", + "quantity": 220, + "risk": "medium", + }, + ], + } + + if name == "get_quality_alerts": + return { + "sku": sku, + "alerts": [ + { + "alert_id": "frog_qa_781", + "status": "open", + "severity": "high", + "summary": "Lily-pad coating chipping in lot LP-42", + }, + { + "alert_id": "frog_qa_795", + "status": "in_progress", + "severity": "medium", + "summary": "Pond-crate scuff rate above threshold", + }, + { + "alert_id": "frog_qa_802", + "status": "resolved", + "severity": "low", + "summary": "Froge label alignment issue corrected", + }, + ], + } + + raise ValueError(f"Unknown tool: {name}") + + +def run_response( + *, + connection: ResponsesConnection, + model: str, + previous_response_id: Optional[str], + input_payload: Union[str, ResponseInputParam], + tools: list[FunctionToolParam], + tool_choice: ToolChoice, + show_events: bool, +) -> RunResponseResult: + connection.response.create( + model=model, + input=input_payload, + stream=True, + previous_response_id=previous_response_id, + tools=tools, + tool_choice=tool_choice, + ) + + text_parts: list[str] = [] + function_calls: list[FunctionCallRequest] = [] + response_id: Optional[str] = None + + for event in connection: + if event.type == "response.output_text.delta": + text_parts.append(event.delta) + continue + + if event.type == "response.output_item.done" and event.item.type == "function_call": + function_calls.append( + FunctionCallRequest( + name=event.item.name, + arguments_json=event.item.arguments, + call_id=event.item.call_id, + ) + ) + continue + + if getattr(event, "type", None) == "error": + raise RuntimeError(f"WebSocket error event: {event!r}") + + if isinstance(event, (ResponseCompletedEvent, ResponseFailedEvent, ResponseIncompleteEvent)): + response_id = event.response.id + if not isinstance(event, ResponseCompletedEvent): + raise RuntimeError(f"Response ended with {event.type} (id={response_id})") + if show_events: + print(f"[{event.type}]") + break + + if getattr(event, "type", None) == "response.done": + # Responses over WebSocket currently emit `response.done` as the final event. + # The payload still includes `response.id`, which we use for chaining. + event_response = getattr(event, "response", None) + event_response_id: Optional[str] = None + if isinstance(event_response, dict): + event_response_dict = cast(Dict[str, object], event_response) + raw_event_response_id = event_response_dict.get("id") + if isinstance(raw_event_response_id, str): + event_response_id = raw_event_response_id + else: + raw_event_response_id = getattr(event_response, "id", None) + if isinstance(raw_event_response_id, str): + event_response_id = raw_event_response_id + + if not isinstance(event_response_id, str): + raise RuntimeError(f"response.done event did not include a valid response.id: {event!r}") + + response_id = event_response_id + if show_events: + print("[response.done]") + break + + if show_events: + print(f"[{event.type}]") + + if response_id is None: + raise RuntimeError("No terminal response event received.") + + return RunResponseResult( + text="".join(text_parts), + response_id=response_id, + function_calls=function_calls, + ) + + +def run_turn( + *, + connection: ResponsesConnection, + model: str, + previous_response_id: Optional[str], + turn_prompt: str, + forced_tool_name: ToolName, + show_events: bool, + show_tool_io: bool, +) -> RunTurnResult: + accumulated_text_parts: list[str] = [] + + current_input: Union[str, ResponseInputParam] = turn_prompt + current_tool_choice: ToolChoice = {"type": "function", "name": forced_tool_name} + current_previous_response_id = previous_response_id + + while True: + response_result = run_response( + connection=connection, + model=model, + previous_response_id=current_previous_response_id, + input_payload=current_input, + tools=TOOLS, + tool_choice=current_tool_choice, + show_events=show_events, + ) + + if response_result.text: + accumulated_text_parts.append(response_result.text) + + current_previous_response_id = response_result.response_id + if not response_result.function_calls: + break + + tool_outputs: ResponseInputParam = [] + for function_call in response_result.function_calls: + tool_name = parse_tool_name(function_call.name) + arguments = parse_sku_arguments(function_call.arguments_json) + output_payload = call_tool(tool_name, arguments) + if show_tool_io: + print(f"[tool_call] {function_call.name}({function_call.arguments_json})") + print(f"[tool_output] {json.dumps(output_payload)}") + + function_call_output: FunctionCallOutputItem = { + "type": "function_call_output", + "call_id": function_call.call_id, + "output": json.dumps(output_payload), + } + tool_outputs.append(cast(ResponseInputItemParam, function_call_output)) + + current_input = tool_outputs + current_tool_choice = "none" + + return RunTurnResult( + assistant_text="".join(accumulated_text_parts).strip(), + response_id=current_previous_response_id, + ) + + +def main() -> None: + args = parse_args() + + client = OpenAI() + extra_headers = {"OpenAI-Beta": BETA_HEADER_VALUE} if args.use_beta_header else {} + + with client.responses.connect(extra_headers=extra_headers) as connection: + previous_response_id: Optional[str] = None + for index, turn in enumerate(DEMO_TURNS, start=1): + print(f"\n=== Turn {index} ===") + print(f"User: {turn['prompt']}") + turn_result = run_turn( + connection=connection, + model=args.model, + previous_response_id=previous_response_id, + turn_prompt=turn["prompt"], + forced_tool_name=turn["tool_name"], + show_events=args.show_events, + show_tool_io=args.show_tool_io, + ) + previous_response_id = turn_result.response_id + print(f"Assistant: {turn_result.assistant_text}") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index fe2e394592..4358af79c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "2.21.0" +version = "2.22.0" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/openai/_legacy_response.py b/src/openai/_legacy_response.py index cfabaa2fc2..1a58c2dfc3 100644 --- a/src/openai/_legacy_response.py +++ b/src/openai/_legacy_response.py @@ -221,6 +221,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: ), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -231,6 +232,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -244,6 +246,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) diff --git a/src/openai/_response.py b/src/openai/_response.py index 350da38dd4..f286d38e6c 100644 --- a/src/openai/_response.py +++ b/src/openai/_response.py @@ -152,6 +152,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: ), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -162,6 +163,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -175,6 +177,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) diff --git a/src/openai/_streaming.py b/src/openai/_streaming.py index 61a742668a..86b81c324f 100644 --- a/src/openai/_streaming.py +++ b/src/openai/_streaming.py @@ -4,7 +4,7 @@ import json import inspect from types import TracebackType -from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx @@ -14,6 +14,7 @@ if TYPE_CHECKING: from ._client import OpenAI, AsyncOpenAI + from ._models import FinalRequestOptions _T = TypeVar("_T") @@ -23,7 +24,7 @@ class Stream(Generic[_T]): """Provides the core interface to iterate over a synchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEBytesDecoder def __init__( @@ -32,10 +33,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: OpenAI, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() @@ -125,7 +128,7 @@ class AsyncStream(Generic[_T]): """Provides the core interface to iterate over an asynchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEDecoder | SSEBytesDecoder def __init__( @@ -134,10 +137,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: AsyncOpenAI, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() diff --git a/src/openai/_version.py b/src/openai/_version.py index 0d4ef7b71c..7bea27c44f 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "openai" -__version__ = "2.21.0" # x-release-please-version +__version__ = "2.22.0" # x-release-please-version diff --git a/src/openai/resources/audio/speech.py b/src/openai/resources/audio/speech.py index f2c8d635f3..96a32f9268 100644 --- a/src/openai/resources/audio/speech.py +++ b/src/openai/resources/audio/speech.py @@ -67,6 +67,8 @@ def create( """ Generates audio from the input text. + Returns the audio file content, or a stream of audio events. + Args: input: The text to generate audio for. The maximum length is 4096 characters. @@ -164,6 +166,8 @@ async def create( """ Generates audio from the input text. + Returns the audio file content, or a stream of audio events. + Args: input: The text to generate audio for. The maximum length is 4096 characters. diff --git a/src/openai/resources/audio/transcriptions.py b/src/openai/resources/audio/transcriptions.py index 599534855d..bc6e9f22de 100644 --- a/src/openai/resources/audio/transcriptions.py +++ b/src/openai/resources/audio/transcriptions.py @@ -85,6 +85,9 @@ def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: @@ -235,6 +238,9 @@ def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: @@ -343,6 +349,9 @@ def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: @@ -533,6 +542,9 @@ async def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: @@ -678,6 +690,9 @@ async def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: @@ -786,6 +801,9 @@ async def create( """ Transcribes audio into the input language. + Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + format, or a stream of transcript events. + Args: file: The audio file object (not file name) to transcribe, in one of these formats: diff --git a/src/openai/resources/beta/chatkit/sessions.py b/src/openai/resources/beta/chatkit/sessions.py index a814f1058e..abfa496a56 100644 --- a/src/openai/resources/beta/chatkit/sessions.py +++ b/src/openai/resources/beta/chatkit/sessions.py @@ -63,7 +63,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ - Create a ChatKit session + Create a ChatKit session. Args: user: A free-form string that identifies your end user; ensures this Session can @@ -117,7 +117,9 @@ def cancel( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ - Cancel a ChatKit session + Cancel an active ChatKit session and return its most recent metadata. + + Cancelling prevents new requests from using the issued client secret. Args: extra_headers: Send extra headers @@ -176,7 +178,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ - Create a ChatKit session + Create a ChatKit session. Args: user: A free-form string that identifies your end user; ensures this Session can @@ -230,7 +232,9 @@ async def cancel( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatSession: """ - Cancel a ChatKit session + Cancel an active ChatKit session and return its most recent metadata. + + Cancelling prevents new requests from using the issued client secret. Args: extra_headers: Send extra headers diff --git a/src/openai/resources/beta/chatkit/threads.py b/src/openai/resources/beta/chatkit/threads.py index 37cd57295a..7a2d4c4a30 100644 --- a/src/openai/resources/beta/chatkit/threads.py +++ b/src/openai/resources/beta/chatkit/threads.py @@ -55,7 +55,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatKitThread: """ - Retrieve a ChatKit thread + Retrieve a ChatKit thread by its identifier. Args: extra_headers: Send extra headers @@ -93,7 +93,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[ChatKitThread]: """ - List ChatKit threads + List ChatKit threads with optional pagination and user filters. Args: after: List items created after this thread item ID. Defaults to null for the first @@ -152,7 +152,7 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleteResponse: """ - Delete a ChatKit thread + Delete a ChatKit thread along with its items and stored attachments. Args: extra_headers: Send extra headers @@ -190,7 +190,7 @@ def list_items( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[Data]: """ - List ChatKit thread items + List items that belong to a ChatKit thread. Args: after: List items created after this thread item ID. Defaults to null for the first @@ -268,7 +268,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ChatKitThread: """ - Retrieve a ChatKit thread + Retrieve a ChatKit thread by its identifier. Args: extra_headers: Send extra headers @@ -306,7 +306,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[ChatKitThread, AsyncConversationCursorPage[ChatKitThread]]: """ - List ChatKit threads + List ChatKit threads with optional pagination and user filters. Args: after: List items created after this thread item ID. Defaults to null for the first @@ -365,7 +365,7 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ThreadDeleteResponse: """ - Delete a ChatKit thread + Delete a ChatKit thread along with its items and stored attachments. Args: extra_headers: Send extra headers @@ -403,7 +403,7 @@ def list_items( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Data, AsyncConversationCursorPage[Data]]: """ - List ChatKit thread items + List items that belong to a ChatKit thread. Args: after: List items created after this thread item ID. Defaults to null for the first diff --git a/src/openai/resources/chat/completions/completions.py b/src/openai/resources/chat/completions/completions.py index fb1887a7d5..5d56d05d87 100644 --- a/src/openai/resources/chat/completions/completions.py +++ b/src/openai/resources/chat/completions/completions.py @@ -301,6 +301,9 @@ def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -436,8 +439,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to @@ -603,6 +607,9 @@ def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -747,8 +754,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to @@ -905,6 +913,9 @@ def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -1049,8 +1060,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to @@ -1785,6 +1797,9 @@ async def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -1920,8 +1935,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to @@ -2087,6 +2103,9 @@ async def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -2231,8 +2250,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to @@ -2389,6 +2409,9 @@ async def create( unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning). + Returns a chat completion object, or a streamed sequence of chat completion + chunk objects if the request is streamed. + Args: messages: A list of messages comprising the conversation so far. Depending on the [model](https://platform.openai.com/docs/models) you use, different message @@ -2533,8 +2556,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). seed: This feature is in Beta. If specified, our system will make a best effort to diff --git a/src/openai/resources/completions.py b/src/openai/resources/completions.py index 2f2284a622..4b6e29395b 100644 --- a/src/openai/resources/completions.py +++ b/src/openai/resources/completions.py @@ -76,6 +76,9 @@ def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to @@ -231,6 +234,9 @@ def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to @@ -386,6 +392,9 @@ def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to @@ -626,6 +635,9 @@ async def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to @@ -781,6 +793,9 @@ async def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to @@ -936,6 +951,9 @@ async def create( """ Creates a completion for the provided prompt and parameters. + Returns a completion object, or a sequence of completion objects if the request + is streamed. + Args: model: ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to diff --git a/src/openai/resources/realtime/client_secrets.py b/src/openai/resources/realtime/client_secrets.py index 5ceba7bef1..d9947dd7e8 100644 --- a/src/openai/resources/realtime/client_secrets.py +++ b/src/openai/resources/realtime/client_secrets.py @@ -52,6 +52,20 @@ def create( """ Create a Realtime client secret with an associated session configuration. + Client secrets are short-lived tokens that can be passed to a client app, such + as a web frontend or mobile client, which grants access to the Realtime API + without leaking your main API key. You can configure a custom TTL for each + client secret. + + You can also attach session configuration options to the client secret, which + will be applied to any sessions created using that client secret, but these can + also be overridden by the client connection. + + [Learn more about authentication with client secrets over WebRTC](https://platform.openai.com/docs/guides/realtime-webrtc). + + Returns the created client secret and the effective session object. The client + secret is a string that looks like `ek_1234`. + Args: expires_after: Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The @@ -120,6 +134,20 @@ async def create( """ Create a Realtime client secret with an associated session configuration. + Client secrets are short-lived tokens that can be passed to a client app, such + as a web frontend or mobile client, which grants access to the Realtime API + without leaking your main API key. You can configure a custom TTL for each + client secret. + + You can also attach session configuration options to the client secret, which + will be applied to any sessions created using that client secret, but these can + also be overridden by the client connection. + + [Learn more about authentication with client secrets over WebRTC](https://platform.openai.com/docs/guides/realtime-webrtc). + + Returns the created client secret and the effective session object. The client + secret is a string that looks like `ek_1234`. + Args: expires_after: Configuration for the client secret expiration. Expiration refers to the time after which a client secret will no longer be valid for creating sessions. The diff --git a/src/openai/resources/responses/api.md b/src/openai/resources/responses/api.md index 6eb1b999fa..36c95d7b83 100644 --- a/src/openai/resources/responses/api.md +++ b/src/openai/resources/responses/api.md @@ -127,6 +127,8 @@ from openai.types.responses import ( ResponseWebSearchCallCompletedEvent, ResponseWebSearchCallInProgressEvent, ResponseWebSearchCallSearchingEvent, + ResponsesClientEvent, + ResponsesServerEvent, SkillReference, Tool, ToolChoiceAllowed, diff --git a/src/openai/resources/responses/input_tokens.py b/src/openai/resources/responses/input_tokens.py index 8664164655..0056727fa0 100644 --- a/src/openai/resources/responses/input_tokens.py +++ b/src/openai/resources/responses/input_tokens.py @@ -65,7 +65,10 @@ def count( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InputTokenCountResponse: """ - Get input token counts + Returns input token counts of the request. + + Returns an object with `object` set to `response.input_tokens` and an + `input_tokens` count. Args: conversation: The conversation that this response belongs to. Items from this conversation are @@ -188,7 +191,10 @@ async def count( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> InputTokenCountResponse: """ - Get input token counts + Returns input token counts of the request. + + Returns an object with `object` set to `response.input_tokens` and an + `input_tokens` count. Args: conversation: The conversation that this response belongs to. Items from this conversation are diff --git a/src/openai/resources/responses/responses.py b/src/openai/resources/responses/responses.py index 79034b7e18..2ad1e6716c 100644 --- a/src/openai/resources/responses/responses.py +++ b/src/openai/resources/responses/responses.py @@ -2,17 +2,22 @@ from __future__ import annotations +import json +import logging from copy import copy -from typing import Any, List, Type, Union, Iterable, Optional, cast +from types import TracebackType +from typing import TYPE_CHECKING, Any, List, Type, Union, Iterable, Iterator, Optional, AsyncIterator, cast from functools import partial from typing_extensions import Literal, overload import httpx +from pydantic import BaseModel from ... import _legacy_response from ..._types import NOT_GIVEN, Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given -from ..._utils import is_given, maybe_transform, async_maybe_transform +from ..._utils import is_given, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property +from ..._models import construct_type_unchecked from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper from .input_items import ( @@ -33,11 +38,13 @@ InputTokensWithStreamingResponse, AsyncInputTokensWithStreamingResponse, ) -from ..._base_client import make_request_options +from ..._exceptions import OpenAIError +from ..._base_client import _merge_mappings, make_request_options from ...types.responses import ( response_create_params, response_compact_params, response_retrieve_params, + responses_client_event_param, ) from ...lib._parsing._responses import ( TextFormatT, @@ -51,16 +58,28 @@ from ...types.responses.parsed_response import ParsedResponse from ...lib.streaming.responses._responses import ResponseStreamManager, AsyncResponseStreamManager from ...types.responses.compacted_response import CompactedResponse +from ...types.websocket_connection_options import WebsocketConnectionOptions from ...types.responses.response_includable import ResponseIncludable from ...types.shared_params.responses_model import ResponsesModel from ...types.responses.response_input_param import ResponseInputParam from ...types.responses.response_prompt_param import ResponsePromptParam from ...types.responses.response_stream_event import ResponseStreamEvent +from ...types.responses.responses_client_event import ResponsesClientEvent +from ...types.responses.responses_server_event import ResponsesServerEvent from ...types.responses.response_input_item_param import ResponseInputItemParam from ...types.responses.response_text_config_param import ResponseTextConfigParam +from ...types.responses.responses_client_event_param import ResponsesClientEventParam + +if TYPE_CHECKING: + from websockets.sync.client import ClientConnection as WebsocketConnection + from websockets.asyncio.client import ClientConnection as AsyncWebsocketConnection + + from ..._client import OpenAI, AsyncOpenAI __all__ = ["Responses", "AsyncResponses"] +log: logging.Logger = logging.getLogger(__name__) + class Responses(SyncAPIResource): @cached_property @@ -238,8 +257,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -493,8 +513,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -741,8 +762,9 @@ def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -1645,8 +1667,14 @@ def compact( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CompactedResponse: - """ - Compact conversation + """Compact a conversation. + + Returns a compacted response object. + + Learn when and how to compact long-running conversations in the + [conversation state guide](https://platform.openai.com/docs/guides/conversation-state#managing-the-context-window). + For ZDR-compatible compaction details, see + [Compaction (advanced)](https://platform.openai.com/docs/guides/conversation-state#compaction-advanced). Args: model: Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a @@ -1692,6 +1720,23 @@ def compact( cast_to=CompactedResponse, ) + def connect( + self, + extra_query: Query = {}, + extra_headers: Headers = {}, + websocket_connection_options: WebsocketConnectionOptions = {}, + ) -> ResponsesConnectionManager: + """Connect to a persistent Responses API WebSocket. + + Send `response.create` events and receive response stream events over the socket. + """ + return ResponsesConnectionManager( + client=self._client, + extra_query=extra_query, + extra_headers=extra_headers, + websocket_connection_options=websocket_connection_options, + ) + class AsyncResponses(AsyncAPIResource): @cached_property @@ -1869,8 +1914,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -2124,8 +2170,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -2372,8 +2419,9 @@ async def create( safety_identifier: A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). service_tier: Specifies the processing type used for serving the request. @@ -3280,8 +3328,14 @@ async def compact( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CompactedResponse: - """ - Compact conversation + """Compact a conversation. + + Returns a compacted response object. + + Learn when and how to compact long-running conversations in the + [conversation state guide](https://platform.openai.com/docs/guides/conversation-state#managing-the-context-window). + For ZDR-compatible compaction details, see + [Compaction (advanced)](https://platform.openai.com/docs/guides/conversation-state#compaction-advanced). Args: model: Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a @@ -3327,6 +3381,23 @@ async def compact( cast_to=CompactedResponse, ) + def connect( + self, + extra_query: Query = {}, + extra_headers: Headers = {}, + websocket_connection_options: WebsocketConnectionOptions = {}, + ) -> AsyncResponsesConnectionManager: + """Connect to a persistent Responses API WebSocket. + + Send `response.create` events and receive response stream events over the socket. + """ + return AsyncResponsesConnectionManager( + client=self._client, + extra_query=extra_query, + extra_headers=extra_headers, + websocket_connection_options=websocket_connection_options, + ) + class ResponsesWithRawResponse: def __init__(self, responses: Responses) -> None: @@ -3486,3 +3557,491 @@ def _make_tools(tools: Iterable[ParseableToolParam] | Omit) -> List[ToolParam] | converted_tools.append(new_tool.cast()) return converted_tools + + +class AsyncResponsesConnection: + """Represents a live WebSocket connection to the Responses API""" + + response: AsyncResponsesResponseResource + + _connection: AsyncWebsocketConnection + + def __init__(self, connection: AsyncWebsocketConnection) -> None: + self._connection = connection + + self.response = AsyncResponsesResponseResource(self) + + async def __aiter__(self) -> AsyncIterator[ResponsesServerEvent]: + """ + An infinite-iterator that will continue to yield events until + the connection is closed. + """ + from websockets.exceptions import ConnectionClosedOK + + try: + while True: + yield await self.recv() + except ConnectionClosedOK: + return + + async def recv(self) -> ResponsesServerEvent: + """ + Receive the next message from the connection and parses it into a `ResponsesServerEvent` object. + + Canceling this method is safe. There's no risk of losing data. + """ + return self.parse_event(await self.recv_bytes()) + + async def recv_bytes(self) -> bytes: + """Receive the next message from the connection as raw bytes. + + Canceling this method is safe. There's no risk of losing data. + + If you want to parse the message into a `ResponsesServerEvent` object like `.recv()` does, + then you can call `.parse_event(data)`. + """ + message = await self._connection.recv(decode=False) + log.debug(f"Received websocket message: %s", message) + return message + + async def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None: + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(await async_maybe_transform(event, ResponsesClientEventParam)) + ) + await self._connection.send(data) + + async def close(self, *, code: int = 1000, reason: str = "") -> None: + await self._connection.close(code=code, reason=reason) + + def parse_event(self, data: str | bytes) -> ResponsesServerEvent: + """ + Converts a raw `str` or `bytes` message into a `ResponsesServerEvent` object. + + This is helpful if you're using `.recv_bytes()`. + """ + return cast( + ResponsesServerEvent, + construct_type_unchecked(value=json.loads(data), type_=cast(Any, ResponsesServerEvent)), + ) + + +class AsyncResponsesConnectionManager: + """ + Context manager over a `AsyncResponsesConnection` that is returned by `responses.connect()` + + This context manager ensures that the connection will be closed when it exits. + + --- + + Note that if your application doesn't work well with the context manager approach then you + can call the `.enter()` method directly to initiate a connection. + + **Warning**: You must remember to close the connection with `.close()`. + + ```py + connection = await client.responses.connect(...).enter() + # ... + await connection.close() + ``` + """ + + def __init__( + self, + *, + client: AsyncOpenAI, + extra_query: Query, + extra_headers: Headers, + websocket_connection_options: WebsocketConnectionOptions, + ) -> None: + self.__client = client + self.__connection: AsyncResponsesConnection | None = None + self.__extra_query = extra_query + self.__extra_headers = extra_headers + self.__websocket_connection_options = websocket_connection_options + + async def __aenter__(self) -> AsyncResponsesConnection: + """ + 👋 If your application doesn't work well with the context manager approach then you + can call this method directly to initiate a connection. + + **Warning**: You must remember to close the connection with `.close()`. + + ```py + connection = await client.responses.connect(...).enter() + # ... + await connection.close() + ``` + """ + try: + from websockets.asyncio.client import connect + except ImportError as exc: + raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc + + url = self._prepare_url().copy_with( + params={ + **self.__client.base_url.params, + **self.__extra_query, + }, + ) + log.debug("Connecting to %s", url) + if self.__websocket_connection_options: + log.debug("Connection options: %s", self.__websocket_connection_options) + + self.__connection = AsyncResponsesConnection( + await connect( + str(url), + user_agent_header=self.__client.user_agent, + additional_headers=_merge_mappings( + { + **self.__client.auth_headers, + }, + self.__extra_headers, + ), + **self.__websocket_connection_options, + ) + ) + + return self.__connection + + enter = __aenter__ + + def _prepare_url(self) -> httpx.URL: + if self.__client.websocket_base_url is not None: + base_url = httpx.URL(self.__client.websocket_base_url) + else: + base_url = self.__client._base_url.copy_with(scheme="wss") + + merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/responses" + return base_url.copy_with(raw_path=merge_raw_path) + + async def __aexit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None + ) -> None: + if self.__connection is not None: + await self.__connection.close() + + +class ResponsesConnection: + """Represents a live WebSocket connection to the Responses API""" + + response: ResponsesResponseResource + + _connection: WebsocketConnection + + def __init__(self, connection: WebsocketConnection) -> None: + self._connection = connection + + self.response = ResponsesResponseResource(self) + + def __iter__(self) -> Iterator[ResponsesServerEvent]: + """ + An infinite-iterator that will continue to yield events until + the connection is closed. + """ + from websockets.exceptions import ConnectionClosedOK + + try: + while True: + yield self.recv() + except ConnectionClosedOK: + return + + def recv(self) -> ResponsesServerEvent: + """ + Receive the next message from the connection and parses it into a `ResponsesServerEvent` object. + + Canceling this method is safe. There's no risk of losing data. + """ + return self.parse_event(self.recv_bytes()) + + def recv_bytes(self) -> bytes: + """Receive the next message from the connection as raw bytes. + + Canceling this method is safe. There's no risk of losing data. + + If you want to parse the message into a `ResponsesServerEvent` object like `.recv()` does, + then you can call `.parse_event(data)`. + """ + message = self._connection.recv(decode=False) + log.debug(f"Received websocket message: %s", message) + return message + + def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None: + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(maybe_transform(event, ResponsesClientEventParam)) + ) + self._connection.send(data) + + def close(self, *, code: int = 1000, reason: str = "") -> None: + self._connection.close(code=code, reason=reason) + + def parse_event(self, data: str | bytes) -> ResponsesServerEvent: + """ + Converts a raw `str` or `bytes` message into a `ResponsesServerEvent` object. + + This is helpful if you're using `.recv_bytes()`. + """ + return cast( + ResponsesServerEvent, + construct_type_unchecked(value=json.loads(data), type_=cast(Any, ResponsesServerEvent)), + ) + + +class ResponsesConnectionManager: + """ + Context manager over a `ResponsesConnection` that is returned by `responses.connect()` + + This context manager ensures that the connection will be closed when it exits. + + --- + + Note that if your application doesn't work well with the context manager approach then you + can call the `.enter()` method directly to initiate a connection. + + **Warning**: You must remember to close the connection with `.close()`. + + ```py + connection = client.responses.connect(...).enter() + # ... + connection.close() + ``` + """ + + def __init__( + self, + *, + client: OpenAI, + extra_query: Query, + extra_headers: Headers, + websocket_connection_options: WebsocketConnectionOptions, + ) -> None: + self.__client = client + self.__connection: ResponsesConnection | None = None + self.__extra_query = extra_query + self.__extra_headers = extra_headers + self.__websocket_connection_options = websocket_connection_options + + def __enter__(self) -> ResponsesConnection: + """ + 👋 If your application doesn't work well with the context manager approach then you + can call this method directly to initiate a connection. + + **Warning**: You must remember to close the connection with `.close()`. + + ```py + connection = client.responses.connect(...).enter() + # ... + connection.close() + ``` + """ + try: + from websockets.sync.client import connect + except ImportError as exc: + raise OpenAIError("You need to install `openai[realtime]` to use this method") from exc + + url = self._prepare_url().copy_with( + params={ + **self.__client.base_url.params, + **self.__extra_query, + }, + ) + log.debug("Connecting to %s", url) + if self.__websocket_connection_options: + log.debug("Connection options: %s", self.__websocket_connection_options) + + self.__connection = ResponsesConnection( + connect( + str(url), + user_agent_header=self.__client.user_agent, + additional_headers=_merge_mappings( + { + **self.__client.auth_headers, + }, + self.__extra_headers, + ), + **self.__websocket_connection_options, + ) + ) + + return self.__connection + + enter = __enter__ + + def _prepare_url(self) -> httpx.URL: + if self.__client.websocket_base_url is not None: + base_url = httpx.URL(self.__client.websocket_base_url) + else: + base_url = self.__client._base_url.copy_with(scheme="wss") + + merge_raw_path = base_url.raw_path.rstrip(b"/") + b"/responses" + return base_url.copy_with(raw_path=merge_raw_path) + + def __exit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None + ) -> None: + if self.__connection is not None: + self.__connection.close() + + +class BaseResponsesConnectionResource: + def __init__(self, connection: ResponsesConnection) -> None: + self._connection = connection + + +class ResponsesResponseResource(BaseResponsesConnectionResource): + def create( + self, + *, + background: Optional[bool] | Omit = omit, + context_management: Optional[Iterable[responses_client_event_param.ContextManagement]] | Omit = omit, + conversation: Optional[responses_client_event_param.Conversation] | Omit = omit, + include: Optional[List[ResponseIncludable]] | Omit = omit, + input: Union[str, ResponseInputParam] | Omit = omit, + instructions: Optional[str] | Omit = omit, + max_output_tokens: Optional[int] | Omit = omit, + max_tool_calls: Optional[int] | Omit = omit, + metadata: Optional[Metadata] | Omit = omit, + model: ResponsesModel | Omit = omit, + parallel_tool_calls: Optional[bool] | Omit = omit, + previous_response_id: Optional[str] | Omit = omit, + prompt: Optional[ResponsePromptParam] | Omit = omit, + prompt_cache_key: str | Omit = omit, + prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, + reasoning: Optional[Reasoning] | Omit = omit, + safety_identifier: str | Omit = omit, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, + store: Optional[bool] | Omit = omit, + stream: Optional[bool] | Omit = omit, + stream_options: Optional[responses_client_event_param.StreamOptions] | Omit = omit, + temperature: Optional[float] | Omit = omit, + text: ResponseTextConfigParam | Omit = omit, + tool_choice: responses_client_event_param.ToolChoice | Omit = omit, + tools: Iterable[ToolParam] | Omit = omit, + top_logprobs: Optional[int] | Omit = omit, + top_p: Optional[float] | Omit = omit, + truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, + user: str | Omit = omit, + ) -> None: + self._connection.send( + cast( + ResponsesClientEventParam, + strip_not_given( + { + "type": "response.create", + "background": background, + "context_management": context_management, + "conversation": conversation, + "include": include, + "input": input, + "instructions": instructions, + "max_output_tokens": max_output_tokens, + "max_tool_calls": max_tool_calls, + "metadata": metadata, + "model": model, + "parallel_tool_calls": parallel_tool_calls, + "previous_response_id": previous_response_id, + "prompt": prompt, + "prompt_cache_key": prompt_cache_key, + "prompt_cache_retention": prompt_cache_retention, + "reasoning": reasoning, + "safety_identifier": safety_identifier, + "service_tier": service_tier, + "store": store, + "stream": stream, + "stream_options": stream_options, + "temperature": temperature, + "text": text, + "tool_choice": tool_choice, + "tools": tools, + "top_logprobs": top_logprobs, + "top_p": top_p, + "truncation": truncation, + "user": user, + } + ), + ) + ) + + +class BaseAsyncResponsesConnectionResource: + def __init__(self, connection: AsyncResponsesConnection) -> None: + self._connection = connection + + +class AsyncResponsesResponseResource(BaseAsyncResponsesConnectionResource): + async def create( + self, + *, + background: Optional[bool] | Omit = omit, + context_management: Optional[Iterable[responses_client_event_param.ContextManagement]] | Omit = omit, + conversation: Optional[responses_client_event_param.Conversation] | Omit = omit, + include: Optional[List[ResponseIncludable]] | Omit = omit, + input: Union[str, ResponseInputParam] | Omit = omit, + instructions: Optional[str] | Omit = omit, + max_output_tokens: Optional[int] | Omit = omit, + max_tool_calls: Optional[int] | Omit = omit, + metadata: Optional[Metadata] | Omit = omit, + model: ResponsesModel | Omit = omit, + parallel_tool_calls: Optional[bool] | Omit = omit, + previous_response_id: Optional[str] | Omit = omit, + prompt: Optional[ResponsePromptParam] | Omit = omit, + prompt_cache_key: str | Omit = omit, + prompt_cache_retention: Optional[Literal["in-memory", "24h"]] | Omit = omit, + reasoning: Optional[Reasoning] | Omit = omit, + safety_identifier: str | Omit = omit, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | Omit = omit, + store: Optional[bool] | Omit = omit, + stream: Optional[bool] | Omit = omit, + stream_options: Optional[responses_client_event_param.StreamOptions] | Omit = omit, + temperature: Optional[float] | Omit = omit, + text: ResponseTextConfigParam | Omit = omit, + tool_choice: responses_client_event_param.ToolChoice | Omit = omit, + tools: Iterable[ToolParam] | Omit = omit, + top_logprobs: Optional[int] | Omit = omit, + top_p: Optional[float] | Omit = omit, + truncation: Optional[Literal["auto", "disabled"]] | Omit = omit, + user: str | Omit = omit, + ) -> None: + await self._connection.send( + cast( + ResponsesClientEventParam, + strip_not_given( + { + "type": "response.create", + "background": background, + "context_management": context_management, + "conversation": conversation, + "include": include, + "input": input, + "instructions": instructions, + "max_output_tokens": max_output_tokens, + "max_tool_calls": max_tool_calls, + "metadata": metadata, + "model": model, + "parallel_tool_calls": parallel_tool_calls, + "previous_response_id": previous_response_id, + "prompt": prompt, + "prompt_cache_key": prompt_cache_key, + "prompt_cache_retention": prompt_cache_retention, + "reasoning": reasoning, + "safety_identifier": safety_identifier, + "service_tier": service_tier, + "store": store, + "stream": stream, + "stream_options": stream_options, + "temperature": temperature, + "text": text, + "tool_choice": tool_choice, + "tools": tools, + "top_logprobs": top_logprobs, + "top_p": top_p, + "truncation": truncation, + "user": user, + } + ), + ) + ) diff --git a/src/openai/resources/skills/content.py b/src/openai/resources/skills/content.py index 98c1531a94..c912fd3eb3 100644 --- a/src/openai/resources/skills/content.py +++ b/src/openai/resources/skills/content.py @@ -51,7 +51,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ - Get Skill Content + Download a skill zip bundle by its ID. Args: extra_headers: Send extra headers @@ -106,7 +106,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ - Get Skill Content + Download a skill zip bundle by its ID. Args: extra_headers: Send extra headers diff --git a/src/openai/resources/skills/skills.py b/src/openai/resources/skills/skills.py index b0e929bccf..77bed029df 100644 --- a/src/openai/resources/skills/skills.py +++ b/src/openai/resources/skills/skills.py @@ -88,7 +88,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Create Skill + Create a new skill. Args: files: Skill files to upload (directory upload) or a single zip file. @@ -130,7 +130,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Get Skill + Get a skill by its ID. Args: extra_headers: Send extra headers @@ -164,7 +164,7 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Update Skill Default Version + Update the default version pointer for a skill. Args: default_version: The skill version number to set as default. @@ -202,7 +202,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[Skill]: """ - List Skills + List all skills for the current project. Args: after: Identifier for the last item from the previous pagination request @@ -252,7 +252,7 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkill: """ - Delete Skill + Delete a skill by its ID. Args: extra_headers: Send extra headers @@ -314,7 +314,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Create Skill + Create a new skill. Args: files: Skill files to upload (directory upload) or a single zip file. @@ -356,7 +356,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Get Skill + Get a skill by its ID. Args: extra_headers: Send extra headers @@ -390,7 +390,7 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Skill: """ - Update Skill Default Version + Update the default version pointer for a skill. Args: default_version: The skill version number to set as default. @@ -430,7 +430,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Skill, AsyncCursorPage[Skill]]: """ - List Skills + List all skills for the current project. Args: after: Identifier for the last item from the previous pagination request @@ -480,7 +480,7 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkill: """ - Delete Skill + Delete a skill by its ID. Args: extra_headers: Send extra headers diff --git a/src/openai/resources/skills/versions/content.py b/src/openai/resources/skills/versions/content.py index 4494ca0e2f..182a563dde 100644 --- a/src/openai/resources/skills/versions/content.py +++ b/src/openai/resources/skills/versions/content.py @@ -52,7 +52,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ - Get Skill Version Content + Download a skill version zip bundle. Args: version: The skill version number. @@ -112,7 +112,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: """ - Get Skill Version Content + Download a skill version zip bundle. Args: version: The skill version number. diff --git a/src/openai/resources/skills/versions/versions.py b/src/openai/resources/skills/versions/versions.py index 890a20774e..610a24240a 100644 --- a/src/openai/resources/skills/versions/versions.py +++ b/src/openai/resources/skills/versions/versions.py @@ -78,7 +78,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ - Create Skill Version + Create a new immutable skill version. Args: default: Whether to set this version as the default. @@ -130,7 +130,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ - Get Skill Version + Get a specific skill version. Args: version: The version number to retrieve. @@ -170,7 +170,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncCursorPage[SkillVersion]: """ - List Skill Versions + List skill versions for a skill. Args: after: The skill version ID to start after. @@ -222,7 +222,7 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkillVersion: """ - Delete Skill Version + Delete a skill version. Args: version: The skill version number. @@ -286,7 +286,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ - Create Skill Version + Create a new immutable skill version. Args: default: Whether to set this version as the default. @@ -338,7 +338,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SkillVersion: """ - Get Skill Version + Get a specific skill version. Args: version: The version number to retrieve. @@ -378,7 +378,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[SkillVersion, AsyncCursorPage[SkillVersion]]: """ - List Skill Versions + List skill versions for a skill. Args: after: The skill version ID to start after. @@ -430,7 +430,7 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> DeletedSkillVersion: """ - Delete Skill Version + Delete a skill version. Args: version: The skill version number. diff --git a/src/openai/resources/uploads/uploads.py b/src/openai/resources/uploads/uploads.py index e8c047bd4f..2873b913ba 100644 --- a/src/openai/resources/uploads/uploads.py +++ b/src/openai/resources/uploads/uploads.py @@ -198,6 +198,8 @@ def create( the documentation on [creating a File](https://platform.openai.com/docs/api-reference/files/create). + Returns the Upload object with status `pending`. + Args: bytes: The number of bytes in the file you are uploading. @@ -257,6 +259,8 @@ def cancel( No Parts may be added after an Upload is cancelled. + Returns the Upload object with status `cancelled`. + Args: extra_headers: Send extra headers @@ -302,7 +306,9 @@ def complete( The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after - an Upload is completed. + an Upload is completed. Returns the Upload object with status `completed`, + including an additional `file` property containing the created usable File + object. Args: part_ids: The ordered list of Part IDs. @@ -505,6 +511,8 @@ async def create( the documentation on [creating a File](https://platform.openai.com/docs/api-reference/files/create). + Returns the Upload object with status `pending`. + Args: bytes: The number of bytes in the file you are uploading. @@ -564,6 +572,8 @@ async def cancel( No Parts may be added after an Upload is cancelled. + Returns the Upload object with status `cancelled`. + Args: extra_headers: Send extra headers @@ -609,7 +619,9 @@ async def complete( The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after - an Upload is completed. + an Upload is completed. Returns the Upload object with status `completed`, + including an additional `file` property containing the created usable File + object. Args: part_ids: The ordered list of Part IDs. diff --git a/src/openai/resources/vector_stores/file_batches.py b/src/openai/resources/vector_stores/file_batches.py index fca1ef89fa..13ffa66d1a 100644 --- a/src/openai/resources/vector_stores/file_batches.py +++ b/src/openai/resources/vector_stores/file_batches.py @@ -79,12 +79,14 @@ def create( file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied - to all files in the batch. Mutually exclusive with `files`. + to all files in the batch. The maximum batch size is 2000 files. Mutually + exclusive with `files`. files: A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must - be specified for each file. Mutually exclusive with `file_ids`. + be specified for each file. The maximum batch size is 2000 files. Mutually + exclusive with `file_ids`. extra_headers: Send extra headers @@ -438,12 +440,14 @@ async def create( file_ids: A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied - to all files in the batch. Mutually exclusive with `files`. + to all files in the batch. The maximum batch size is 2000 files. Mutually + exclusive with `files`. files: A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must - be specified for each file. Mutually exclusive with `file_ids`. + be specified for each file. The maximum batch size is 2000 files. Mutually + exclusive with `file_ids`. extra_headers: Send extra headers diff --git a/src/openai/resources/videos.py b/src/openai/resources/videos.py index 9f74c942bc..85ea79f8bc 100644 --- a/src/openai/resources/videos.py +++ b/src/openai/resources/videos.py @@ -76,7 +76,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Create a video + Create a new video generation job from a prompt and optional reference assets. Args: prompt: Text prompt that describes the video to generate. @@ -209,7 +209,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Retrieve a video + Fetch the latest metadata for a generated video. Args: extra_headers: Send extra headers @@ -244,7 +244,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncConversationCursorPage[Video]: """ - List videos + List recently generated videos for the current project. Args: after: Identifier for the last item from the previous pagination request @@ -294,7 +294,7 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoDeleteResponse: """ - Delete a video + Permanently delete a completed or failed video and its stored assets. Args: extra_headers: Send extra headers @@ -327,12 +327,13 @@ def download_content( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: - """Download video content + """ + Download the generated video bytes or a derived preview asset. - Args: - variant: Which downloadable asset to return. + Streams the rendered video content for the specified video job. - Defaults to the MP4 video. + Args: + variant: Which downloadable asset to return. Defaults to the MP4 video. extra_headers: Send extra headers @@ -370,7 +371,7 @@ def remix( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Create a video remix + Create a remix of a completed video using a refreshed prompt. Args: prompt: Updated text prompt that directs the remix generation. @@ -431,7 +432,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Create a video + Create a new video generation job from a prompt and optional reference assets. Args: prompt: Text prompt that describes the video to generate. @@ -564,7 +565,7 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Retrieve a video + Fetch the latest metadata for a generated video. Args: extra_headers: Send extra headers @@ -599,7 +600,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[Video, AsyncConversationCursorPage[Video]]: """ - List videos + List recently generated videos for the current project. Args: after: Identifier for the last item from the previous pagination request @@ -649,7 +650,7 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> VideoDeleteResponse: """ - Delete a video + Permanently delete a completed or failed video and its stored assets. Args: extra_headers: Send extra headers @@ -682,12 +683,13 @@ async def download_content( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> _legacy_response.HttpxBinaryResponseContent: - """Download video content + """ + Download the generated video bytes or a derived preview asset. - Args: - variant: Which downloadable asset to return. + Streams the rendered video content for the specified video job. - Defaults to the MP4 video. + Args: + variant: Which downloadable asset to return. Defaults to the MP4 video. extra_headers: Send extra headers @@ -727,7 +729,7 @@ async def remix( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Video: """ - Create a video remix + Create a remix of a completed video using a refreshed prompt. Args: prompt: Updated text prompt that directs the remix generation. diff --git a/src/openai/types/chat/completion_create_params.py b/src/openai/types/chat/completion_create_params.py index 49cefb95fc..8e71ccbe41 100644 --- a/src/openai/types/chat/completion_create_params.py +++ b/src/openai/types/chat/completion_create_params.py @@ -227,8 +227,9 @@ class CompletionCreateParamsBase(TypedDict, total=False): """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ diff --git a/src/openai/types/responses/__init__.py b/src/openai/types/responses/__init__.py index cbb8deae95..de6f68989b 100644 --- a/src/openai/types/responses/__init__.py +++ b/src/openai/types/responses/__init__.py @@ -13,6 +13,7 @@ from .response_item import ResponseItem as ResponseItem from .container_auto import ContainerAuto as ContainerAuto from .response_error import ResponseError as ResponseError +from .response_input import ResponseInput as ResponseInput from .response_usage import ResponseUsage as ResponseUsage from .parsed_response import ( ParsedContent as ParsedContent, @@ -72,6 +73,8 @@ from .response_create_params import ResponseCreateParams as ResponseCreateParams from .response_created_event import ResponseCreatedEvent as ResponseCreatedEvent from .response_input_content import ResponseInputContent as ResponseInputContent +from .responses_client_event import ResponsesClientEvent as ResponsesClientEvent +from .responses_server_event import ResponsesServerEvent as ResponsesServerEvent from .local_environment_param import LocalEnvironmentParam as LocalEnvironmentParam from .response_compact_params import ResponseCompactParams as ResponseCompactParams from .response_output_message import ResponseOutputMessage as ResponseOutputMessage @@ -121,6 +124,7 @@ from .response_input_content_param import ResponseInputContentParam as ResponseInputContentParam from .response_input_image_content import ResponseInputImageContent as ResponseInputImageContent from .response_refusal_delta_event import ResponseRefusalDeltaEvent as ResponseRefusalDeltaEvent +from .responses_client_event_param import ResponsesClientEventParam as ResponsesClientEventParam from .response_output_message_param import ResponseOutputMessageParam as ResponseOutputMessageParam from .response_output_refusal_param import ResponseOutputRefusalParam as ResponseOutputRefusalParam from .response_reasoning_item_param import ResponseReasoningItemParam as ResponseReasoningItemParam @@ -139,6 +143,7 @@ from .container_network_policy_disabled import ContainerNetworkPolicyDisabled as ContainerNetworkPolicyDisabled from .response_computer_tool_call_param import ResponseComputerToolCallParam as ResponseComputerToolCallParam from .response_content_part_added_event import ResponseContentPartAddedEvent as ResponseContentPartAddedEvent +from .response_conversation_param_param import ResponseConversationParamParam as ResponseConversationParamParam from .response_format_text_config_param import ResponseFormatTextConfigParam as ResponseFormatTextConfigParam from .response_function_shell_tool_call import ResponseFunctionShellToolCall as ResponseFunctionShellToolCall from .response_function_tool_call_param import ResponseFunctionToolCallParam as ResponseFunctionToolCallParam diff --git a/src/openai/types/responses/input_token_count_params.py b/src/openai/types/responses/input_token_count_params.py index 97ee4bf6ca..f8a2026537 100644 --- a/src/openai/types/responses/input_token_count_params.py +++ b/src/openai/types/responses/input_token_count_params.py @@ -15,8 +15,8 @@ from .response_input_item_param import ResponseInputItemParam from .tool_choice_allowed_param import ToolChoiceAllowedParam from .tool_choice_function_param import ToolChoiceFunctionParam -from .response_conversation_param import ResponseConversationParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam +from .response_conversation_param_param import ResponseConversationParamParam from .response_format_text_config_param import ResponseFormatTextConfigParam __all__ = ["InputTokenCountParams", "Conversation", "Text", "ToolChoice"] @@ -97,7 +97,7 @@ class InputTokenCountParams(TypedDict, total=False): """ -Conversation: TypeAlias = Union[str, ResponseConversationParam] +Conversation: TypeAlias = Union[str, ResponseConversationParamParam] class Text(TypedDict, total=False): diff --git a/src/openai/types/responses/response.py b/src/openai/types/responses/response.py index 6bac7d65de..ada0783bce 100644 --- a/src/openai/types/responses/response.py +++ b/src/openai/types/responses/response.py @@ -233,8 +233,9 @@ class Response(BaseModel): """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ diff --git a/src/openai/types/responses/response_conversation_param.py b/src/openai/types/responses/response_conversation_param.py index d1587fe68a..7db4129bf4 100644 --- a/src/openai/types/responses/response_conversation_param.py +++ b/src/openai/types/responses/response_conversation_param.py @@ -1,14 +1,12 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from __future__ import annotations - -from typing_extensions import Required, TypedDict +from ..._models import BaseModel __all__ = ["ResponseConversationParam"] -class ResponseConversationParam(TypedDict, total=False): +class ResponseConversationParam(BaseModel): """The conversation that this response belongs to.""" - id: Required[str] + id: str """The unique ID of the conversation.""" diff --git a/src/openai/types/responses/response_conversation_param_param.py b/src/openai/types/responses/response_conversation_param_param.py new file mode 100644 index 0000000000..dba3628d0b --- /dev/null +++ b/src/openai/types/responses/response_conversation_param_param.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["ResponseConversationParamParam"] + + +class ResponseConversationParamParam(TypedDict, total=False): + """The conversation that this response belongs to.""" + + id: Required[str] + """The unique ID of the conversation.""" diff --git a/src/openai/types/responses/response_create_params.py b/src/openai/types/responses/response_create_params.py index 97aaf9dc3a..bf7170da1f 100644 --- a/src/openai/types/responses/response_create_params.py +++ b/src/openai/types/responses/response_create_params.py @@ -19,9 +19,9 @@ from .tool_choice_allowed_param import ToolChoiceAllowedParam from .response_text_config_param import ResponseTextConfigParam from .tool_choice_function_param import ToolChoiceFunctionParam -from .response_conversation_param import ResponseConversationParam from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam from ..shared_params.responses_model import ResponsesModel +from .response_conversation_param_param import ResponseConversationParamParam __all__ = [ "ResponseCreateParamsBase", @@ -171,8 +171,9 @@ class ResponseCreateParamsBase(TypedDict, total=False): """ A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely - identifies each user. We recommend hashing their username or email address, in - order to avoid sending us any identifying information. + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). """ @@ -291,7 +292,7 @@ class ContextManagement(TypedDict, total=False): """Token threshold at which compaction should be triggered for this entry.""" -Conversation: TypeAlias = Union[str, ResponseConversationParam] +Conversation: TypeAlias = Union[str, ResponseConversationParamParam] class StreamOptions(TypedDict, total=False): diff --git a/src/openai/types/responses/response_input.py b/src/openai/types/responses/response_input.py new file mode 100644 index 0000000000..e2180dec05 --- /dev/null +++ b/src/openai/types/responses/response_input.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .response_input_item import ResponseInputItem + +__all__ = ["ResponseInput"] + +ResponseInput: TypeAlias = List[ResponseInputItem] diff --git a/src/openai/types/responses/responses_client_event.py b/src/openai/types/responses/responses_client_event.py new file mode 100644 index 0000000000..2bc6f899c5 --- /dev/null +++ b/src/openai/types/responses/responses_client_event.py @@ -0,0 +1,326 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from .tool import Tool +from ..._models import BaseModel +from .response_input import ResponseInput +from .response_prompt import ResponsePrompt +from .tool_choice_mcp import ToolChoiceMcp +from ..shared.metadata import Metadata +from ..shared.reasoning import Reasoning +from .tool_choice_shell import ToolChoiceShell +from .tool_choice_types import ToolChoiceTypes +from .tool_choice_custom import ToolChoiceCustom +from .response_includable import ResponseIncludable +from .tool_choice_allowed import ToolChoiceAllowed +from .tool_choice_options import ToolChoiceOptions +from .response_text_config import ResponseTextConfig +from .tool_choice_function import ToolChoiceFunction +from ..shared.responses_model import ResponsesModel +from .tool_choice_apply_patch import ToolChoiceApplyPatch +from .response_conversation_param import ResponseConversationParam + +__all__ = ["ResponsesClientEvent", "ContextManagement", "Conversation", "StreamOptions", "ToolChoice"] + + +class ContextManagement(BaseModel): + type: str + """The context management entry type. Currently only 'compaction' is supported.""" + + compact_threshold: Optional[int] = None + """Token threshold at which compaction should be triggered for this entry.""" + + +Conversation: TypeAlias = Union[str, ResponseConversationParam, None] + + +class StreamOptions(BaseModel): + """Options for streaming responses. Only set this when you set `stream: true`.""" + + include_obfuscation: Optional[bool] = None + """When true, stream obfuscation will be enabled. + + Stream obfuscation adds random characters to an `obfuscation` field on streaming + delta events to normalize payload sizes as a mitigation to certain side-channel + attacks. These obfuscation fields are included by default, but add a small + amount of overhead to the data stream. You can set `include_obfuscation` to + false to optimize for bandwidth if you trust the network links between your + application and the OpenAI API. + """ + + +ToolChoice: TypeAlias = Union[ + ToolChoiceOptions, + ToolChoiceAllowed, + ToolChoiceTypes, + ToolChoiceFunction, + ToolChoiceMcp, + ToolChoiceCustom, + ToolChoiceApplyPatch, + ToolChoiceShell, +] + + +class ResponsesClientEvent(BaseModel): + type: Literal["response.create"] + """The type of the client event. Always `response.create`.""" + + background: Optional[bool] = None + """ + Whether to run the model response in the background. + [Learn more](https://platform.openai.com/docs/guides/background). + """ + + context_management: Optional[List[ContextManagement]] = None + """Context management configuration for this request.""" + + conversation: Optional[Conversation] = None + """The conversation that this response belongs to. + + Items from this conversation are prepended to `input_items` for this response + request. Input items and output items from this response are automatically added + to this conversation after this response completes. + """ + + include: Optional[List[ResponseIncludable]] = None + """Specify additional output data to include in the model response. + + Currently supported values are: + + - `web_search_call.action.sources`: Include the sources of the web search tool + call. + - `code_interpreter_call.outputs`: Includes the outputs of python code execution + in code interpreter tool call items. + - `computer_call_output.output.image_url`: Include image urls from the computer + call output. + - `file_search_call.results`: Include the search results of the file search tool + call. + - `message.input_image.image_url`: Include image urls from the input message. + - `message.output_text.logprobs`: Include logprobs with assistant messages. + - `reasoning.encrypted_content`: Includes an encrypted version of reasoning + tokens in reasoning item outputs. This enables reasoning items to be used in + multi-turn conversations when using the Responses API statelessly (like when + the `store` parameter is set to `false`, or when an organization is enrolled + in the zero data retention program). + """ + + input: Union[str, ResponseInput, None] = None + """Text, image, or file inputs to the model, used to generate a response. + + Learn more: + + - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + - [Image inputs](https://platform.openai.com/docs/guides/images) + - [File inputs](https://platform.openai.com/docs/guides/pdf-files) + - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) + - [Function calling](https://platform.openai.com/docs/guides/function-calling) + """ + + instructions: Optional[str] = None + """A system (or developer) message inserted into the model's context. + + When using along with `previous_response_id`, the instructions from a previous + response will not be carried over to the next response. This makes it simple to + swap out system (or developer) messages in new responses. + """ + + max_output_tokens: Optional[int] = None + """ + An upper bound for the number of tokens that can be generated for a response, + including visible output tokens and + [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). + """ + + max_tool_calls: Optional[int] = None + """ + The maximum number of total calls to built-in tools that can be processed in a + response. This maximum number applies across all built-in tool calls, not per + individual tool. Any further attempts to call a tool by the model will be + ignored. + """ + + metadata: Optional[Metadata] = None + """Set of 16 key-value pairs that can be attached to an object. + + This can be useful for storing additional information about the object in a + structured format, and querying for objects via API or the dashboard. + + Keys are strings with a maximum length of 64 characters. Values are strings with + a maximum length of 512 characters. + """ + + model: Optional[ResponsesModel] = None + """Model ID used to generate the response, like `gpt-4o` or `o3`. + + OpenAI offers a wide range of models with different capabilities, performance + characteristics, and price points. Refer to the + [model guide](https://platform.openai.com/docs/models) to browse and compare + available models. + """ + + parallel_tool_calls: Optional[bool] = None + """Whether to allow the model to run tool calls in parallel.""" + + previous_response_id: Optional[str] = None + """The unique ID of the previous response to the model. + + Use this to create multi-turn conversations. Learn more about + [conversation state](https://platform.openai.com/docs/guides/conversation-state). + Cannot be used in conjunction with `conversation`. + """ + + prompt: Optional[ResponsePrompt] = None + """ + Reference to a prompt template and its variables. + [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). + """ + + prompt_cache_key: Optional[str] = None + """ + Used by OpenAI to cache responses for similar requests to optimize your cache + hit rates. Replaces the `user` field. + [Learn more](https://platform.openai.com/docs/guides/prompt-caching). + """ + + prompt_cache_retention: Optional[Literal["in-memory", "24h"]] = None + """The retention policy for the prompt cache. + + Set to `24h` to enable extended prompt caching, which keeps cached prefixes + active for longer, up to a maximum of 24 hours. + [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). + """ + + reasoning: Optional[Reasoning] = None + """**gpt-5 and o-series models only** + + Configuration options for + [reasoning models](https://platform.openai.com/docs/guides/reasoning). + """ + + safety_identifier: Optional[str] = None + """ + A stable identifier used to help detect users of your application that may be + violating OpenAI's usage policies. The IDs should be a string that uniquely + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. + [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + """ + + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] = None + """Specifies the processing type used for serving the request. + + - If set to 'auto', then the request will be processed with the service tier + configured in the Project settings. Unless otherwise configured, the Project + will use 'default'. + - If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. + - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or + '[priority](https://openai.com/api-priority-processing/)', then the request + will be processed with the corresponding service tier. + - When not set, the default behavior is 'auto'. + + When the `service_tier` parameter is set, the response body will include the + `service_tier` value based on the processing mode actually used to serve the + request. This response value may be different from the value set in the + parameter. + """ + + store: Optional[bool] = None + """Whether to store the generated model response for later retrieval via API.""" + + stream: Optional[bool] = None + """ + If set to true, the model response data will be streamed to the client as it is + generated using + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). + See the + [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) + for more information. + """ + + stream_options: Optional[StreamOptions] = None + """Options for streaming responses. Only set this when you set `stream: true`.""" + + temperature: Optional[float] = None + """What sampling temperature to use, between 0 and 2. + + Higher values like 0.8 will make the output more random, while lower values like + 0.2 will make it more focused and deterministic. We generally recommend altering + this or `top_p` but not both. + """ + + text: Optional[ResponseTextConfig] = None + """Configuration options for a text response from the model. + + Can be plain text or structured JSON data. Learn more: + + - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) + """ + + tool_choice: Optional[ToolChoice] = None + """ + How the model should select which tool (or tools) to use when generating a + response. See the `tools` parameter to see how to specify which tools the model + can call. + """ + + tools: Optional[List[Tool]] = None + """An array of tools the model may call while generating a response. + + You can specify which tool to use by setting the `tool_choice` parameter. + + We support the following categories of tools: + + - **Built-in tools**: Tools that are provided by OpenAI that extend the model's + capabilities, like + [web search](https://platform.openai.com/docs/guides/tools-web-search) or + [file search](https://platform.openai.com/docs/guides/tools-file-search). + Learn more about + [built-in tools](https://platform.openai.com/docs/guides/tools). + - **MCP Tools**: Integrations with third-party systems via custom MCP servers or + predefined connectors such as Google Drive and SharePoint. Learn more about + [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). + - **Function calls (custom tools)**: Functions that are defined by you, enabling + the model to call your own code with strongly typed arguments and outputs. + Learn more about + [function calling](https://platform.openai.com/docs/guides/function-calling). + You can also use custom tools to call your own code. + """ + + top_logprobs: Optional[int] = None + """ + An integer between 0 and 20 specifying the number of most likely tokens to + return at each token position, each with an associated log probability. + """ + + top_p: Optional[float] = None + """ + An alternative to sampling with temperature, called nucleus sampling, where the + model considers the results of the tokens with top_p probability mass. So 0.1 + means only the tokens comprising the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + """ + + truncation: Optional[Literal["auto", "disabled"]] = None + """The truncation strategy to use for the model response. + + - `auto`: If the input to this Response exceeds the model's context window size, + the model will truncate the response to fit the context window by dropping + items from the beginning of the conversation. + - `disabled` (default): If the input size will exceed the context window size + for a model, the request will fail with a 400 error. + """ + + user: Optional[str] = None + """This field is being replaced by `safety_identifier` and `prompt_cache_key`. + + Use `prompt_cache_key` instead to maintain caching optimizations. A stable + identifier for your end-users. Used to boost cache hit rates by better bucketing + similar requests and to help OpenAI detect and prevent abuse. + [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + """ diff --git a/src/openai/types/responses/responses_client_event_param.py b/src/openai/types/responses/responses_client_event_param.py new file mode 100644 index 0000000000..08596ef9ea --- /dev/null +++ b/src/openai/types/responses/responses_client_event_param.py @@ -0,0 +1,327 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Iterable, Optional +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +from .tool_param import ToolParam +from .response_includable import ResponseIncludable +from .tool_choice_options import ToolChoiceOptions +from .response_input_param import ResponseInputParam +from .response_prompt_param import ResponsePromptParam +from .tool_choice_mcp_param import ToolChoiceMcpParam +from ..shared_params.metadata import Metadata +from .tool_choice_shell_param import ToolChoiceShellParam +from .tool_choice_types_param import ToolChoiceTypesParam +from ..shared_params.reasoning import Reasoning +from .tool_choice_custom_param import ToolChoiceCustomParam +from .tool_choice_allowed_param import ToolChoiceAllowedParam +from .response_text_config_param import ResponseTextConfigParam +from .tool_choice_function_param import ToolChoiceFunctionParam +from .tool_choice_apply_patch_param import ToolChoiceApplyPatchParam +from ..shared_params.responses_model import ResponsesModel +from .response_conversation_param_param import ResponseConversationParamParam + +__all__ = ["ResponsesClientEventParam", "ContextManagement", "Conversation", "StreamOptions", "ToolChoice"] + + +class ContextManagement(TypedDict, total=False): + type: Required[str] + """The context management entry type. Currently only 'compaction' is supported.""" + + compact_threshold: Optional[int] + """Token threshold at which compaction should be triggered for this entry.""" + + +Conversation: TypeAlias = Union[str, ResponseConversationParamParam] + + +class StreamOptions(TypedDict, total=False): + """Options for streaming responses. Only set this when you set `stream: true`.""" + + include_obfuscation: bool + """When true, stream obfuscation will be enabled. + + Stream obfuscation adds random characters to an `obfuscation` field on streaming + delta events to normalize payload sizes as a mitigation to certain side-channel + attacks. These obfuscation fields are included by default, but add a small + amount of overhead to the data stream. You can set `include_obfuscation` to + false to optimize for bandwidth if you trust the network links between your + application and the OpenAI API. + """ + + +ToolChoice: TypeAlias = Union[ + ToolChoiceOptions, + ToolChoiceAllowedParam, + ToolChoiceTypesParam, + ToolChoiceFunctionParam, + ToolChoiceMcpParam, + ToolChoiceCustomParam, + ToolChoiceApplyPatchParam, + ToolChoiceShellParam, +] + + +class ResponsesClientEventParam(TypedDict, total=False): + type: Required[Literal["response.create"]] + """The type of the client event. Always `response.create`.""" + + background: Optional[bool] + """ + Whether to run the model response in the background. + [Learn more](https://platform.openai.com/docs/guides/background). + """ + + context_management: Optional[Iterable[ContextManagement]] + """Context management configuration for this request.""" + + conversation: Optional[Conversation] + """The conversation that this response belongs to. + + Items from this conversation are prepended to `input_items` for this response + request. Input items and output items from this response are automatically added + to this conversation after this response completes. + """ + + include: Optional[List[ResponseIncludable]] + """Specify additional output data to include in the model response. + + Currently supported values are: + + - `web_search_call.action.sources`: Include the sources of the web search tool + call. + - `code_interpreter_call.outputs`: Includes the outputs of python code execution + in code interpreter tool call items. + - `computer_call_output.output.image_url`: Include image urls from the computer + call output. + - `file_search_call.results`: Include the search results of the file search tool + call. + - `message.input_image.image_url`: Include image urls from the input message. + - `message.output_text.logprobs`: Include logprobs with assistant messages. + - `reasoning.encrypted_content`: Includes an encrypted version of reasoning + tokens in reasoning item outputs. This enables reasoning items to be used in + multi-turn conversations when using the Responses API statelessly (like when + the `store` parameter is set to `false`, or when an organization is enrolled + in the zero data retention program). + """ + + input: Union[str, ResponseInputParam] + """Text, image, or file inputs to the model, used to generate a response. + + Learn more: + + - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + - [Image inputs](https://platform.openai.com/docs/guides/images) + - [File inputs](https://platform.openai.com/docs/guides/pdf-files) + - [Conversation state](https://platform.openai.com/docs/guides/conversation-state) + - [Function calling](https://platform.openai.com/docs/guides/function-calling) + """ + + instructions: Optional[str] + """A system (or developer) message inserted into the model's context. + + When using along with `previous_response_id`, the instructions from a previous + response will not be carried over to the next response. This makes it simple to + swap out system (or developer) messages in new responses. + """ + + max_output_tokens: Optional[int] + """ + An upper bound for the number of tokens that can be generated for a response, + including visible output tokens and + [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). + """ + + max_tool_calls: Optional[int] + """ + The maximum number of total calls to built-in tools that can be processed in a + response. This maximum number applies across all built-in tool calls, not per + individual tool. Any further attempts to call a tool by the model will be + ignored. + """ + + metadata: Optional[Metadata] + """Set of 16 key-value pairs that can be attached to an object. + + This can be useful for storing additional information about the object in a + structured format, and querying for objects via API or the dashboard. + + Keys are strings with a maximum length of 64 characters. Values are strings with + a maximum length of 512 characters. + """ + + model: ResponsesModel + """Model ID used to generate the response, like `gpt-4o` or `o3`. + + OpenAI offers a wide range of models with different capabilities, performance + characteristics, and price points. Refer to the + [model guide](https://platform.openai.com/docs/models) to browse and compare + available models. + """ + + parallel_tool_calls: Optional[bool] + """Whether to allow the model to run tool calls in parallel.""" + + previous_response_id: Optional[str] + """The unique ID of the previous response to the model. + + Use this to create multi-turn conversations. Learn more about + [conversation state](https://platform.openai.com/docs/guides/conversation-state). + Cannot be used in conjunction with `conversation`. + """ + + prompt: Optional[ResponsePromptParam] + """ + Reference to a prompt template and its variables. + [Learn more](https://platform.openai.com/docs/guides/text?api-mode=responses#reusable-prompts). + """ + + prompt_cache_key: str + """ + Used by OpenAI to cache responses for similar requests to optimize your cache + hit rates. Replaces the `user` field. + [Learn more](https://platform.openai.com/docs/guides/prompt-caching). + """ + + prompt_cache_retention: Optional[Literal["in-memory", "24h"]] + """The retention policy for the prompt cache. + + Set to `24h` to enable extended prompt caching, which keeps cached prefixes + active for longer, up to a maximum of 24 hours. + [Learn more](https://platform.openai.com/docs/guides/prompt-caching#prompt-cache-retention). + """ + + reasoning: Optional[Reasoning] + """**gpt-5 and o-series models only** + + Configuration options for + [reasoning models](https://platform.openai.com/docs/guides/reasoning). + """ + + safety_identifier: str + """ + A stable identifier used to help detect users of your application that may be + violating OpenAI's usage policies. The IDs should be a string that uniquely + identifies each user, with a maximum length of 64 characters. We recommend + hashing their username or email address, in order to avoid sending us any + identifying information. + [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + """ + + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] + """Specifies the processing type used for serving the request. + + - If set to 'auto', then the request will be processed with the service tier + configured in the Project settings. Unless otherwise configured, the Project + will use 'default'. + - If set to 'default', then the request will be processed with the standard + pricing and performance for the selected model. + - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or + '[priority](https://openai.com/api-priority-processing/)', then the request + will be processed with the corresponding service tier. + - When not set, the default behavior is 'auto'. + + When the `service_tier` parameter is set, the response body will include the + `service_tier` value based on the processing mode actually used to serve the + request. This response value may be different from the value set in the + parameter. + """ + + store: Optional[bool] + """Whether to store the generated model response for later retrieval via API.""" + + stream: Optional[bool] + """ + If set to true, the model response data will be streamed to the client as it is + generated using + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). + See the + [Streaming section below](https://platform.openai.com/docs/api-reference/responses-streaming) + for more information. + """ + + stream_options: Optional[StreamOptions] + """Options for streaming responses. Only set this when you set `stream: true`.""" + + temperature: Optional[float] + """What sampling temperature to use, between 0 and 2. + + Higher values like 0.8 will make the output more random, while lower values like + 0.2 will make it more focused and deterministic. We generally recommend altering + this or `top_p` but not both. + """ + + text: ResponseTextConfigParam + """Configuration options for a text response from the model. + + Can be plain text or structured JSON data. Learn more: + + - [Text inputs and outputs](https://platform.openai.com/docs/guides/text) + - [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) + """ + + tool_choice: ToolChoice + """ + How the model should select which tool (or tools) to use when generating a + response. See the `tools` parameter to see how to specify which tools the model + can call. + """ + + tools: Iterable[ToolParam] + """An array of tools the model may call while generating a response. + + You can specify which tool to use by setting the `tool_choice` parameter. + + We support the following categories of tools: + + - **Built-in tools**: Tools that are provided by OpenAI that extend the model's + capabilities, like + [web search](https://platform.openai.com/docs/guides/tools-web-search) or + [file search](https://platform.openai.com/docs/guides/tools-file-search). + Learn more about + [built-in tools](https://platform.openai.com/docs/guides/tools). + - **MCP Tools**: Integrations with third-party systems via custom MCP servers or + predefined connectors such as Google Drive and SharePoint. Learn more about + [MCP Tools](https://platform.openai.com/docs/guides/tools-connectors-mcp). + - **Function calls (custom tools)**: Functions that are defined by you, enabling + the model to call your own code with strongly typed arguments and outputs. + Learn more about + [function calling](https://platform.openai.com/docs/guides/function-calling). + You can also use custom tools to call your own code. + """ + + top_logprobs: Optional[int] + """ + An integer between 0 and 20 specifying the number of most likely tokens to + return at each token position, each with an associated log probability. + """ + + top_p: Optional[float] + """ + An alternative to sampling with temperature, called nucleus sampling, where the + model considers the results of the tokens with top_p probability mass. So 0.1 + means only the tokens comprising the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + """ + + truncation: Optional[Literal["auto", "disabled"]] + """The truncation strategy to use for the model response. + + - `auto`: If the input to this Response exceeds the model's context window size, + the model will truncate the response to fit the context window by dropping + items from the beginning of the conversation. + - `disabled` (default): If the input size will exceed the context window size + for a model, the request will fail with a 400 error. + """ + + user: str + """This field is being replaced by `safety_identifier` and `prompt_cache_key`. + + Use `prompt_cache_key` instead to maintain caching optimizations. A stable + identifier for your end-users. Used to boost cache hit rates by better bucketing + similar requests and to help OpenAI detect and prevent abuse. + [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#safety-identifiers). + """ diff --git a/src/openai/types/responses/responses_server_event.py b/src/openai/types/responses/responses_server_event.py new file mode 100644 index 0000000000..c543587ad0 --- /dev/null +++ b/src/openai/types/responses/responses_server_event.py @@ -0,0 +1,120 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import Annotated, TypeAlias + +from ..._utils import PropertyInfo +from .response_error_event import ResponseErrorEvent +from .response_failed_event import ResponseFailedEvent +from .response_queued_event import ResponseQueuedEvent +from .response_created_event import ResponseCreatedEvent +from .response_completed_event import ResponseCompletedEvent +from .response_text_done_event import ResponseTextDoneEvent +from .response_audio_done_event import ResponseAudioDoneEvent +from .response_incomplete_event import ResponseIncompleteEvent +from .response_text_delta_event import ResponseTextDeltaEvent +from .response_audio_delta_event import ResponseAudioDeltaEvent +from .response_in_progress_event import ResponseInProgressEvent +from .response_refusal_done_event import ResponseRefusalDoneEvent +from .response_refusal_delta_event import ResponseRefusalDeltaEvent +from .response_mcp_call_failed_event import ResponseMcpCallFailedEvent +from .response_output_item_done_event import ResponseOutputItemDoneEvent +from .response_content_part_done_event import ResponseContentPartDoneEvent +from .response_output_item_added_event import ResponseOutputItemAddedEvent +from .response_content_part_added_event import ResponseContentPartAddedEvent +from .response_mcp_call_completed_event import ResponseMcpCallCompletedEvent +from .response_reasoning_text_done_event import ResponseReasoningTextDoneEvent +from .response_mcp_call_in_progress_event import ResponseMcpCallInProgressEvent +from .response_reasoning_text_delta_event import ResponseReasoningTextDeltaEvent +from .response_audio_transcript_done_event import ResponseAudioTranscriptDoneEvent +from .response_mcp_list_tools_failed_event import ResponseMcpListToolsFailedEvent +from .response_audio_transcript_delta_event import ResponseAudioTranscriptDeltaEvent +from .response_mcp_call_arguments_done_event import ResponseMcpCallArgumentsDoneEvent +from .response_image_gen_call_completed_event import ResponseImageGenCallCompletedEvent +from .response_mcp_call_arguments_delta_event import ResponseMcpCallArgumentsDeltaEvent +from .response_mcp_list_tools_completed_event import ResponseMcpListToolsCompletedEvent +from .response_image_gen_call_generating_event import ResponseImageGenCallGeneratingEvent +from .response_web_search_call_completed_event import ResponseWebSearchCallCompletedEvent +from .response_web_search_call_searching_event import ResponseWebSearchCallSearchingEvent +from .response_file_search_call_completed_event import ResponseFileSearchCallCompletedEvent +from .response_file_search_call_searching_event import ResponseFileSearchCallSearchingEvent +from .response_image_gen_call_in_progress_event import ResponseImageGenCallInProgressEvent +from .response_mcp_list_tools_in_progress_event import ResponseMcpListToolsInProgressEvent +from .response_custom_tool_call_input_done_event import ResponseCustomToolCallInputDoneEvent +from .response_reasoning_summary_part_done_event import ResponseReasoningSummaryPartDoneEvent +from .response_reasoning_summary_text_done_event import ResponseReasoningSummaryTextDoneEvent +from .response_web_search_call_in_progress_event import ResponseWebSearchCallInProgressEvent +from .response_custom_tool_call_input_delta_event import ResponseCustomToolCallInputDeltaEvent +from .response_file_search_call_in_progress_event import ResponseFileSearchCallInProgressEvent +from .response_function_call_arguments_done_event import ResponseFunctionCallArgumentsDoneEvent +from .response_image_gen_call_partial_image_event import ResponseImageGenCallPartialImageEvent +from .response_output_text_annotation_added_event import ResponseOutputTextAnnotationAddedEvent +from .response_reasoning_summary_part_added_event import ResponseReasoningSummaryPartAddedEvent +from .response_reasoning_summary_text_delta_event import ResponseReasoningSummaryTextDeltaEvent +from .response_function_call_arguments_delta_event import ResponseFunctionCallArgumentsDeltaEvent +from .response_code_interpreter_call_code_done_event import ResponseCodeInterpreterCallCodeDoneEvent +from .response_code_interpreter_call_completed_event import ResponseCodeInterpreterCallCompletedEvent +from .response_code_interpreter_call_code_delta_event import ResponseCodeInterpreterCallCodeDeltaEvent +from .response_code_interpreter_call_in_progress_event import ResponseCodeInterpreterCallInProgressEvent +from .response_code_interpreter_call_interpreting_event import ResponseCodeInterpreterCallInterpretingEvent + +__all__ = ["ResponsesServerEvent"] + +ResponsesServerEvent: TypeAlias = Annotated[ + Union[ + ResponseAudioDeltaEvent, + ResponseAudioDoneEvent, + ResponseAudioTranscriptDeltaEvent, + ResponseAudioTranscriptDoneEvent, + ResponseCodeInterpreterCallCodeDeltaEvent, + ResponseCodeInterpreterCallCodeDoneEvent, + ResponseCodeInterpreterCallCompletedEvent, + ResponseCodeInterpreterCallInProgressEvent, + ResponseCodeInterpreterCallInterpretingEvent, + ResponseCompletedEvent, + ResponseContentPartAddedEvent, + ResponseContentPartDoneEvent, + ResponseCreatedEvent, + ResponseErrorEvent, + ResponseFileSearchCallCompletedEvent, + ResponseFileSearchCallInProgressEvent, + ResponseFileSearchCallSearchingEvent, + ResponseFunctionCallArgumentsDeltaEvent, + ResponseFunctionCallArgumentsDoneEvent, + ResponseInProgressEvent, + ResponseFailedEvent, + ResponseIncompleteEvent, + ResponseOutputItemAddedEvent, + ResponseOutputItemDoneEvent, + ResponseReasoningSummaryPartAddedEvent, + ResponseReasoningSummaryPartDoneEvent, + ResponseReasoningSummaryTextDeltaEvent, + ResponseReasoningSummaryTextDoneEvent, + ResponseReasoningTextDeltaEvent, + ResponseReasoningTextDoneEvent, + ResponseRefusalDeltaEvent, + ResponseRefusalDoneEvent, + ResponseTextDeltaEvent, + ResponseTextDoneEvent, + ResponseWebSearchCallCompletedEvent, + ResponseWebSearchCallInProgressEvent, + ResponseWebSearchCallSearchingEvent, + ResponseImageGenCallCompletedEvent, + ResponseImageGenCallGeneratingEvent, + ResponseImageGenCallInProgressEvent, + ResponseImageGenCallPartialImageEvent, + ResponseMcpCallArgumentsDeltaEvent, + ResponseMcpCallArgumentsDoneEvent, + ResponseMcpCallCompletedEvent, + ResponseMcpCallFailedEvent, + ResponseMcpCallInProgressEvent, + ResponseMcpListToolsCompletedEvent, + ResponseMcpListToolsFailedEvent, + ResponseMcpListToolsInProgressEvent, + ResponseOutputTextAnnotationAddedEvent, + ResponseQueuedEvent, + ResponseCustomToolCallInputDeltaEvent, + ResponseCustomToolCallInputDoneEvent, + ], + PropertyInfo(discriminator="type"), +] diff --git a/src/openai/types/vector_stores/file_batch_create_params.py b/src/openai/types/vector_stores/file_batch_create_params.py index 2ab98a83ab..7ca0de81da 100644 --- a/src/openai/types/vector_stores/file_batch_create_params.py +++ b/src/openai/types/vector_stores/file_batch_create_params.py @@ -33,7 +33,8 @@ class FileBatchCreateParams(TypedDict, total=False): A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied - to all files in the batch. Mutually exclusive with `files`. + to all files in the batch. The maximum batch size is 2000 files. Mutually + exclusive with `files`. """ files: Iterable[File] @@ -41,7 +42,8 @@ class FileBatchCreateParams(TypedDict, total=False): A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must - be specified for each file. Mutually exclusive with `file_ids`. + be specified for each file. The maximum batch size is 2000 files. Mutually + exclusive with `file_ids`. """