Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.99.1"
".": "1.99.2"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 111
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-d6a16b25b969c3e5382e7d413de15bf83d5f7534d5c3ecce64d3a7e847418f9e.yml
openapi_spec_hash: 0c0bcf4aee9ca2a948dd14b890dfe728
config_hash: aeff9289bd7f8c8482e4d738c3c2fde1
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-f5c45f4ae5c2075cbc603d6910bba3da31c23714c209fbd3fd82a94f634a126b.yml
openapi_spec_hash: 3eb8d86c06f0bb5e1190983e5acfc9ba
config_hash: 9a64321968e21ed72f5c0e02164ea00d
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## 1.99.2 (2025-08-07)

Full Changelog: [v1.99.1...v1.99.2](https://github.com/openai/openai-python/compare/v1.99.1...v1.99.2)

### Features

* **api:** adds GPT-5 and new API features: platform.openai.com/docs/guides/gpt-5 ([ed370d8](https://github.com/openai/openai-python/commit/ed370d805e4d5d1ec14a136f5b2516751277059f))


### Bug Fixes

* **types:** correct tool types ([0c57bd7](https://github.com/openai/openai-python/commit/0c57bd7f2183a20b714d04edea380a4df0464a40))


### Chores

* **tests:** bump inline-snapshot dependency ([e236fde](https://github.com/openai/openai-python/commit/e236fde99a335fcaac9760f324e4807ce2cf7cba))

## 1.99.1 (2025-08-05)

Full Changelog: [v1.99.0...v1.99.1](https://github.com/openai/openai-python/compare/v1.99.0...v1.99.1)
Expand Down
17 changes: 17 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from openai.types import (
ChatModel,
ComparisonFilter,
CompoundFilter,
CustomToolInputFormat,
ErrorObject,
FunctionDefinition,
FunctionParameters,
Expand All @@ -15,6 +16,8 @@ from openai.types import (
ResponseFormatJSONObject,
ResponseFormatJSONSchema,
ResponseFormatText,
ResponseFormatTextGrammar,
ResponseFormatTextPython,
ResponsesModel,
)
```
Expand Down Expand Up @@ -46,6 +49,7 @@ Types:
```python
from openai.types.chat import (
ChatCompletion,
ChatCompletionAllowedToolChoice,
ChatCompletionAssistantMessageParam,
ChatCompletionAudio,
ChatCompletionAudioParam,
Expand All @@ -55,15 +59,20 @@ from openai.types.chat import (
ChatCompletionContentPartInputAudio,
ChatCompletionContentPartRefusal,
ChatCompletionContentPartText,
ChatCompletionCustomTool,
ChatCompletionDeleted,
ChatCompletionDeveloperMessageParam,
ChatCompletionFunctionCallOption,
ChatCompletionFunctionMessageParam,
ChatCompletionFunctionTool,
ChatCompletionMessage,
ChatCompletionMessageCustomToolCall,
ChatCompletionMessageFunctionToolCall,
ChatCompletionMessageParam,
ChatCompletionMessageToolCall,
ChatCompletionModality,
ChatCompletionNamedToolChoice,
ChatCompletionNamedToolChoiceCustom,
ChatCompletionPredictionContent,
ChatCompletionRole,
ChatCompletionStoreMessage,
Expand All @@ -74,6 +83,7 @@ from openai.types.chat import (
ChatCompletionToolChoiceOption,
ChatCompletionToolMessageParam,
ChatCompletionUserMessageParam,
ChatCompletionAllowedTools,
ChatCompletionReasoningEffort,
)
```
Expand Down Expand Up @@ -719,6 +729,7 @@ Types:
```python
from openai.types.responses import (
ComputerTool,
CustomTool,
EasyInputMessage,
FileSearchTool,
FunctionTool,
Expand All @@ -741,6 +752,10 @@ from openai.types.responses import (
ResponseContentPartAddedEvent,
ResponseContentPartDoneEvent,
ResponseCreatedEvent,
ResponseCustomToolCall,
ResponseCustomToolCallInputDeltaEvent,
ResponseCustomToolCallInputDoneEvent,
ResponseCustomToolCallOutput,
ResponseError,
ResponseErrorEvent,
ResponseFailedEvent,
Expand Down Expand Up @@ -810,6 +825,8 @@ from openai.types.responses import (
ResponseWebSearchCallInProgressEvent,
ResponseWebSearchCallSearchingEvent,
Tool,
ToolChoiceAllowed,
ToolChoiceCustom,
ToolChoiceFunction,
ToolChoiceMcp,
ToolChoiceOptions,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "openai"
version = "1.99.1"
version = "1.99.2"
description = "The official Python library for the openai API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
25 changes: 6 additions & 19 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ attrs==24.2.0
azure-core==1.31.0
# via azure-identity
azure-identity==1.19.0
black==24.10.0
# via inline-snapshot
certifi==2023.7.22
# via httpcore
# via httpx
Expand All @@ -46,9 +44,6 @@ cffi==1.16.0
# via sounddevice
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via black
# via inline-snapshot
colorlog==6.7.0
# via nox
cryptography==42.0.7
Expand All @@ -66,7 +61,7 @@ exceptiongroup==1.2.2
# via trio
execnet==2.1.1
# via pytest-xdist
executing==2.1.0
executing==2.2.0
# via inline-snapshot
filelock==3.12.4
# via virtualenv
Expand All @@ -92,7 +87,7 @@ idna==3.4
importlib-metadata==7.0.0
iniconfig==2.0.0
# via pytest
inline-snapshot==0.10.2
inline-snapshot==0.27.0
jiter==0.5.0
# via openai
markdown-it-py==3.0.0
Expand All @@ -109,7 +104,6 @@ multidict==6.5.0
# via yarl
mypy==1.14.1
mypy-extensions==1.0.0
# via black
# via mypy
nest-asyncio==1.6.0
nodeenv==1.8.0
Expand All @@ -122,17 +116,13 @@ numpy==2.0.2
outcome==1.3.0.post0
# via trio
packaging==23.2
# via black
# via nox
# via pytest
pandas==2.2.3
# via openai
pandas-stubs==2.1.4.231227
# via openai
pathspec==0.12.1
# via black
platformdirs==3.11.0
# via black
# via virtualenv
pluggy==1.5.0
# via pytest
Expand All @@ -148,11 +138,13 @@ pydantic==2.10.3
pydantic-core==2.27.1
# via pydantic
pygments==2.18.0
# via pytest
# via rich
pyjwt==2.8.0
# via msal
pyright==1.1.399
pytest==8.3.3
pytest==8.4.1
# via inline-snapshot
# via pytest-asyncio
# via pytest-xdist
pytest-asyncio==0.24.0
Expand Down Expand Up @@ -185,10 +177,8 @@ sortedcontainers==2.4.0
sounddevice==0.5.1
# via openai
time-machine==2.9.0
toml==0.10.2
# via inline-snapshot
tomli==2.0.2
# via black
# via inline-snapshot
# via mypy
# via pytest
tqdm==4.66.5
Expand All @@ -197,13 +187,10 @@ trio==0.27.0
types-pyaudio==0.2.16.20240516
types-pytz==2024.2.0.20241003
# via pandas-stubs
types-toml==0.10.8.20240310
# via inline-snapshot
types-tqdm==4.66.0.20240417
typing-extensions==4.12.2
# via azure-core
# via azure-identity
# via black
# via multidict
# via mypy
# via openai
Expand Down
2 changes: 1 addition & 1 deletion src/openai/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "openai"
__version__ = "1.99.1" # x-release-please-version
__version__ = "1.99.2" # x-release-please-version
57 changes: 49 additions & 8 deletions src/openai/lib/_parsing/_completions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import json
import logging
from typing import TYPE_CHECKING, Any, Iterable, cast
from typing_extensions import TypeVar, TypeGuard, assert_never

Expand All @@ -19,14 +20,15 @@
ParsedChatCompletion,
ChatCompletionMessage,
ParsedFunctionToolCall,
ChatCompletionToolParam,
ParsedChatCompletionMessage,
ChatCompletionFunctionToolParam,
completion_create_params,
)
from ..._exceptions import LengthFinishReasonError, ContentFilterFinishReasonError
from ...types.shared_params import FunctionDefinition
from ...types.chat.completion_create_params import ResponseFormat as ResponseFormatParam
from ...types.chat.chat_completion_message_tool_call import Function
from ...types.chat.chat_completion_tool_param import ChatCompletionToolParam
from ...types.chat.chat_completion_message_function_tool_call import Function

ResponseFormatT = TypeVar(
"ResponseFormatT",
Expand All @@ -35,12 +37,36 @@
)
_default_response_format: None = None

log: logging.Logger = logging.getLogger("openai.lib.parsing")


def is_strict_chat_completion_tool_param(
tool: ChatCompletionToolParam,
) -> TypeGuard[ChatCompletionFunctionToolParam]:
"""Check if the given tool is a strict ChatCompletionFunctionToolParam."""
if not tool["type"] == "function":
return False
if tool["function"].get("strict") is not True:
return False

return True


def select_strict_chat_completion_tools(
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
) -> Iterable[ChatCompletionFunctionToolParam] | NotGiven:
"""Select only the strict ChatCompletionFunctionToolParams from the given tools."""
if not is_given(tools):
return NOT_GIVEN

return [t for t in tools if is_strict_chat_completion_tool_param(t)]


def validate_input_tools(
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
) -> None:
) -> Iterable[ChatCompletionFunctionToolParam] | NotGiven:
if not is_given(tools):
return
return NOT_GIVEN

for tool in tools:
if tool["type"] != "function":
Expand All @@ -54,6 +80,8 @@ def validate_input_tools(
f"`{tool['function']['name']}` is not strict. Only `strict` function tools can be auto-parsed"
)

return cast(Iterable[ChatCompletionFunctionToolParam], tools)


def parse_chat_completion(
*,
Expand Down Expand Up @@ -95,6 +123,14 @@ def parse_chat_completion(
type_=ParsedFunctionToolCall,
)
)
elif tool_call.type == "custom":
# warn user that custom tool calls are not callable here
log.warning(
"Custom tool calls are not callable. Ignoring tool call: %s - %s",
tool_call.id,
tool_call.custom.name,
stacklevel=2,
)
elif TYPE_CHECKING: # type: ignore[unreachable]
assert_never(tool_call)
else:
Expand Down Expand Up @@ -129,13 +165,15 @@ def parse_chat_completion(
)


def get_input_tool_by_name(*, input_tools: list[ChatCompletionToolParam], name: str) -> ChatCompletionToolParam | None:
return next((t for t in input_tools if t.get("function", {}).get("name") == name), None)
def get_input_tool_by_name(
*, input_tools: list[ChatCompletionToolParam], name: str
) -> ChatCompletionFunctionToolParam | None:
return next((t for t in input_tools if t["type"] == "function" and t.get("function", {}).get("name") == name), None)


def parse_function_tool_arguments(
*, input_tools: list[ChatCompletionToolParam], function: Function | ParsedFunction
) -> object:
) -> object | None:
input_tool = get_input_tool_by_name(input_tools=input_tools, name=function.name)
if not input_tool:
return None
Expand All @@ -149,7 +187,7 @@ def parse_function_tool_arguments(
if not input_fn.get("strict"):
return None

return json.loads(function.arguments)
return json.loads(function.arguments) # type: ignore[no-any-return]


def maybe_parse_content(
Expand Down Expand Up @@ -209,6 +247,9 @@ def is_response_format_param(response_format: object) -> TypeGuard[ResponseForma


def is_parseable_tool(input_tool: ChatCompletionToolParam) -> bool:
if input_tool["type"] != "function":
return False

input_fn = cast(object, input_tool.get("function"))
if isinstance(input_fn, PydanticFunctionTool):
return True
Expand Down
1 change: 1 addition & 0 deletions src/openai/lib/_parsing/_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def parse_response(
or output.type == "local_shell_call"
or output.type == "mcp_list_tools"
or output.type == "exec"
or output.type == "custom_tool_call"
):
output_list.append(output)
elif TYPE_CHECKING: # type: ignore
Expand Down
4 changes: 2 additions & 2 deletions src/openai/lib/_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pydantic

from ._pydantic import to_strict_json_schema
from ..types.chat import ChatCompletionToolParam
from ..types.chat import ChatCompletionFunctionToolParam
from ..types.shared_params import FunctionDefinition
from ..types.responses.function_tool_param import FunctionToolParam as ResponsesFunctionToolParam

Expand Down Expand Up @@ -42,7 +42,7 @@ def pydantic_function_tool(
*,
name: str | None = None, # inferred from class name by default
description: str | None = None, # inferred from class docstring by default
) -> ChatCompletionToolParam:
) -> ChatCompletionFunctionToolParam:
if description is None:
# note: we intentionally don't use `.getdoc()` to avoid
# including pydantic's docstrings
Expand Down
Loading