Skip to content

Commit 2c404fc

Browse files
feat(api): webhook and deep research support
1 parent f43c7b5 commit 2c404fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1222
-392
lines changed

.github/workflows/detect-breaking-changes.yml

Lines changed: 0 additions & 35 deletions
This file was deleted.

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 111
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-ef4ecb19eb61e24c49d77fef769ee243e5279bc0bdbaee8d0f8dba4da8722559.yml
3-
openapi_spec_hash: 1b8a9767c9f04e6865b06c41948cdc24
4-
config_hash: cae2d1f187b5b9f8dfa00daa807da42a
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-cca460eaf5cc13e9d6e5293eb97aac53d66dc1385c691f74b768c97d165b6e8b.yml
3+
openapi_spec_hash: 9ec43d443b3dd58ca5aa87eb0a7eb49f
4+
config_hash: e74d6791681e3af1b548748ff47a22c2

api.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,30 @@ Methods:
387387
- <code title="post /vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel">client.vector_stores.file_batches.<a href="./src/openai/resources/vector_stores/file_batches.py">cancel</a>(batch_id, \*, vector_store_id) -> <a href="./src/openai/types/vector_stores/vector_store_file_batch.py">VectorStoreFileBatch</a></code>
388388
- <code title="get /vector_stores/{vector_store_id}/file_batches/{batch_id}/files">client.vector_stores.file_batches.<a href="./src/openai/resources/vector_stores/file_batches.py">list_files</a>(batch_id, \*, vector_store_id, \*\*<a href="src/openai/types/vector_stores/file_batch_list_files_params.py">params</a>) -> <a href="./src/openai/types/vector_stores/vector_store_file.py">SyncCursorPage[VectorStoreFile]</a></code>
389389

390+
# Webhooks
391+
392+
Types:
393+
394+
```python
395+
from openai.types.webhooks import (
396+
BatchCancelledWebhookEvent,
397+
BatchCompletedWebhookEvent,
398+
BatchExpiredWebhookEvent,
399+
BatchFailedWebhookEvent,
400+
EvalRunCanceledWebhookEvent,
401+
EvalRunFailedWebhookEvent,
402+
EvalRunSucceededWebhookEvent,
403+
FineTuningJobCancelledWebhookEvent,
404+
FineTuningJobFailedWebhookEvent,
405+
FineTuningJobSucceededWebhookEvent,
406+
ResponseCancelledWebhookEvent,
407+
ResponseCompletedWebhookEvent,
408+
ResponseFailedWebhookEvent,
409+
ResponseIncompleteWebhookEvent,
410+
UnwrapWebhookEvent,
411+
)
412+
```
413+
390414
# Beta
391415

392416
## Realtime
@@ -758,6 +782,7 @@ from openai.types.responses import (
758782
ResponseWebSearchCallSearchingEvent,
759783
Tool,
760784
ToolChoiceFunction,
785+
ToolChoiceMcp,
761786
ToolChoiceOptions,
762787
ToolChoiceTypes,
763788
WebSearchTool,

scripts/detect-breaking-changes

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/openai/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105

106106
project: str | None = None
107107

108+
webhook_secret: str | None = None
109+
108110
base_url: str | _httpx.URL | None = None
109111

110112
timeout: float | Timeout | None = DEFAULT_TIMEOUT
@@ -155,6 +157,17 @@ def project(self, value: str | None) -> None: # type: ignore
155157

156158
project = value
157159

160+
@property # type: ignore
161+
@override
162+
def webhook_secret(self) -> str | None:
163+
return webhook_secret
164+
165+
@webhook_secret.setter # type: ignore
166+
def webhook_secret(self, value: str | None) -> None: # type: ignore
167+
global webhook_secret
168+
169+
webhook_secret = value
170+
158171
@property
159172
@override
160173
def base_url(self) -> _httpx.URL:
@@ -234,6 +247,7 @@ def _load_client() -> OpenAI: # type: ignore[reportUnusedFunction]
234247
api_key=api_key,
235248
organization=organization,
236249
project=project,
250+
webhook_secret=webhook_secret,
237251
base_url=base_url,
238252
timeout=timeout,
239253
max_retries=max_retries,
@@ -262,6 +276,7 @@ def _reset_client() -> None: # type: ignore[reportUnusedFunction]
262276
models as models,
263277
batches as batches,
264278
uploads as uploads,
279+
webhooks as webhooks,
265280
responses as responses,
266281
containers as containers,
267282
embeddings as embeddings,

src/openai/_client.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
from .resources.images import Images, AsyncImages
5858
from .resources.models import Models, AsyncModels
5959
from .resources.batches import Batches, AsyncBatches
60+
from .resources.webhooks import Webhooks, AsyncWebhooks
6061
from .resources.beta.beta import Beta, AsyncBeta
6162
from .resources.chat.chat import Chat, AsyncChat
6263
from .resources.embeddings import Embeddings, AsyncEmbeddings
@@ -78,6 +79,7 @@ class OpenAI(SyncAPIClient):
7879
api_key: str
7980
organization: str | None
8081
project: str | None
82+
webhook_secret: str | None
8183

8284
websocket_base_url: str | httpx.URL | None
8385
"""Base URL for WebSocket connections.
@@ -93,6 +95,7 @@ def __init__(
9395
api_key: str | None = None,
9496
organization: str | None = None,
9597
project: str | None = None,
98+
webhook_secret: str | None = None,
9699
base_url: str | httpx.URL | None = None,
97100
websocket_base_url: str | httpx.URL | None = None,
98101
timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN,
@@ -119,6 +122,7 @@ def __init__(
119122
- `api_key` from `OPENAI_API_KEY`
120123
- `organization` from `OPENAI_ORG_ID`
121124
- `project` from `OPENAI_PROJECT_ID`
125+
- `webhook_secret` from `OPENAI_WEBHOOK_SECRET`
122126
"""
123127
if api_key is None:
124128
api_key = os.environ.get("OPENAI_API_KEY")
@@ -136,6 +140,10 @@ def __init__(
136140
project = os.environ.get("OPENAI_PROJECT_ID")
137141
self.project = project
138142

143+
if webhook_secret is None:
144+
webhook_secret = os.environ.get("OPENAI_WEBHOOK_SECRET")
145+
self.webhook_secret = webhook_secret
146+
139147
self.websocket_base_url = websocket_base_url
140148

141149
if base_url is None:
@@ -216,6 +224,12 @@ def vector_stores(self) -> VectorStores:
216224

217225
return VectorStores(self)
218226

227+
@cached_property
228+
def webhooks(self) -> Webhooks:
229+
from .resources.webhooks import Webhooks
230+
231+
return Webhooks(self)
232+
219233
@cached_property
220234
def beta(self) -> Beta:
221235
from .resources.beta import Beta
@@ -288,6 +302,7 @@ def copy(
288302
api_key: str | None = None,
289303
organization: str | None = None,
290304
project: str | None = None,
305+
webhook_secret: str | None = None,
291306
websocket_base_url: str | httpx.URL | None = None,
292307
base_url: str | httpx.URL | None = None,
293308
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
@@ -325,6 +340,7 @@ def copy(
325340
api_key=api_key or self.api_key,
326341
organization=organization or self.organization,
327342
project=project or self.project,
343+
webhook_secret=webhook_secret or self.webhook_secret,
328344
websocket_base_url=websocket_base_url or self.websocket_base_url,
329345
base_url=base_url or self.base_url,
330346
timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
@@ -379,6 +395,7 @@ class AsyncOpenAI(AsyncAPIClient):
379395
api_key: str
380396
organization: str | None
381397
project: str | None
398+
webhook_secret: str | None
382399

383400
websocket_base_url: str | httpx.URL | None
384401
"""Base URL for WebSocket connections.
@@ -394,6 +411,7 @@ def __init__(
394411
api_key: str | None = None,
395412
organization: str | None = None,
396413
project: str | None = None,
414+
webhook_secret: str | None = None,
397415
base_url: str | httpx.URL | None = None,
398416
websocket_base_url: str | httpx.URL | None = None,
399417
timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN,
@@ -420,6 +438,7 @@ def __init__(
420438
- `api_key` from `OPENAI_API_KEY`
421439
- `organization` from `OPENAI_ORG_ID`
422440
- `project` from `OPENAI_PROJECT_ID`
441+
- `webhook_secret` from `OPENAI_WEBHOOK_SECRET`
423442
"""
424443
if api_key is None:
425444
api_key = os.environ.get("OPENAI_API_KEY")
@@ -437,6 +456,10 @@ def __init__(
437456
project = os.environ.get("OPENAI_PROJECT_ID")
438457
self.project = project
439458

459+
if webhook_secret is None:
460+
webhook_secret = os.environ.get("OPENAI_WEBHOOK_SECRET")
461+
self.webhook_secret = webhook_secret
462+
440463
self.websocket_base_url = websocket_base_url
441464

442465
if base_url is None:
@@ -517,6 +540,12 @@ def vector_stores(self) -> AsyncVectorStores:
517540

518541
return AsyncVectorStores(self)
519542

543+
@cached_property
544+
def webhooks(self) -> AsyncWebhooks:
545+
from .resources.webhooks import AsyncWebhooks
546+
547+
return AsyncWebhooks(self)
548+
520549
@cached_property
521550
def beta(self) -> AsyncBeta:
522551
from .resources.beta import AsyncBeta
@@ -589,6 +618,7 @@ def copy(
589618
api_key: str | None = None,
590619
organization: str | None = None,
591620
project: str | None = None,
621+
webhook_secret: str | None = None,
592622
websocket_base_url: str | httpx.URL | None = None,
593623
base_url: str | httpx.URL | None = None,
594624
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
@@ -626,6 +656,7 @@ def copy(
626656
api_key=api_key or self.api_key,
627657
organization=organization or self.organization,
628658
project=project or self.project,
659+
webhook_secret=webhook_secret or self.webhook_secret,
629660
websocket_base_url=websocket_base_url or self.websocket_base_url,
630661
base_url=base_url or self.base_url,
631662
timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,

src/openai/_module_client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .resources.images import Images
1111
from .resources.models import Models
1212
from .resources.batches import Batches
13+
from .resources.webhooks import Webhooks
1314
from .resources.beta.beta import Beta
1415
from .resources.chat.chat import Chat
1516
from .resources.embeddings import Embeddings
@@ -81,6 +82,12 @@ def __load__(self) -> Uploads:
8182
return _load_client().uploads
8283

8384

85+
class WebhooksProxy(LazyProxy["Webhooks"]):
86+
@override
87+
def __load__(self) -> Webhooks:
88+
return _load_client().webhooks
89+
90+
8491
class ResponsesProxy(LazyProxy["Responses"]):
8592
@override
8693
def __load__(self) -> Responses:
@@ -132,6 +139,7 @@ def __load__(self) -> VectorStores:
132139
models: Models = ModelsProxy().__as_proxied__()
133140
batches: Batches = BatchesProxy().__as_proxied__()
134141
uploads: Uploads = UploadsProxy().__as_proxied__()
142+
webhooks: Webhooks = WebhooksProxy().__as_proxied__()
135143
responses: Responses = ResponsesProxy().__as_proxied__()
136144
embeddings: Embeddings = EmbeddingsProxy().__as_proxied__()
137145
containers: Containers = ContainersProxy().__as_proxied__()

0 commit comments

Comments
 (0)