diff --git a/schemas/cache/media-buy/create-media-buy-async-response-submitted.json b/schemas/cache/media-buy/create-media-buy-async-response-submitted.json index 4531f8776..ccbbf3347 100644 --- a/schemas/cache/media-buy/create-media-buy-async-response-submitted.json +++ b/schemas/cache/media-buy/create-media-buy-async-response-submitted.json @@ -1,9 +1,19 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Create Media Buy - Submitted", - "description": "Payload acknowledging the task is queued. Usually empty or just context.", + "description": "Payload acknowledging the task is queued for async processing (e.g. human-review tenants). Consumers must use task_id to poll tasks/get for the final outcome.", "type": "object", + "required": ["status", "task_id"], "properties": { + "status": { + "type": "string", + "const": "submitted", + "description": "Discriminates this async envelope from the synchronous success shape." + }, + "task_id": { + "type": "string", + "description": "Task handle the buyer uses with tasks/get. The media_buy_id is issued on the completion artifact, not here." + }, "context": { "$ref": "../core/context.json" }, @@ -12,4 +22,4 @@ } }, "additionalProperties": true -} \ No newline at end of file +} diff --git a/src/adcp/__init__.py b/src/adcp/__init__.py index 2445170d2..3470f9729 100644 --- a/src/adcp/__init__.py +++ b/src/adcp/__init__.py @@ -294,6 +294,7 @@ CreateContentStandardsErrorResponse, CreateContentStandardsSuccessResponse, CreateMediaBuyErrorResponse, + CreateMediaBuySubmittedResponse, CreateMediaBuySuccessResponse, Deployment, Destination, @@ -888,6 +889,7 @@ def get_adcp_version() -> str: "CalibrateContentErrorResponse", "CreateContentStandardsSuccessResponse", "CreateContentStandardsErrorResponse", + "CreateMediaBuySubmittedResponse", "CreateMediaBuySuccessResponse", "CreateMediaBuyErrorResponse", "Deployment", diff --git a/src/adcp/decisioning/handler.py b/src/adcp/decisioning/handler.py index 045a9fcb6..1847bebce 100644 --- a/src/adcp/decisioning/handler.py +++ b/src/adcp/decisioning/handler.py @@ -98,7 +98,7 @@ CreateContentStandardsRequest, CreateContentStandardsResponse, CreateMediaBuyRequest, - CreateMediaBuySuccessResponse, + CreateMediaBuyResponse, CreatePropertyListRequest, CreatePropertyListResponse, DeleteCollectionListRequest, @@ -1305,7 +1305,7 @@ async def create_media_buy( # type: ignore[override] self, params: CreateMediaBuyRequest, context: ToolContext | None = None, - ) -> CreateMediaBuySuccessResponse: + ) -> CreateMediaBuyResponse: from adcp.decisioning.types import AdcpError tool_ctx = context or ToolContext() @@ -1404,7 +1404,7 @@ async def _release_reservation_hook(_exc: BaseException) -> None: on_failure=on_failure, ) self._maybe_auto_emit_sync_completion("create_media_buy", params, result) - return cast("CreateMediaBuySuccessResponse", result) + return cast("CreateMediaBuyResponse", result) async def update_media_buy( # type: ignore[override] self, diff --git a/src/adcp/types/__init__.py b/src/adcp/types/__init__.py index d10142120..14860bdcf 100644 --- a/src/adcp/types/__init__.py +++ b/src/adcp/types/__init__.py @@ -459,6 +459,7 @@ CreateContentStandardsErrorResponse, CreateContentStandardsSuccessResponse, CreateMediaBuyErrorResponse, + CreateMediaBuySubmittedResponse, CreateMediaBuySuccessResponse, CssFormatAsset, CssFormatGroupAsset, @@ -600,6 +601,7 @@ is_build_creative_success, is_calibrate_content_success, is_create_media_buy_error, + is_create_media_buy_submitted, is_create_media_buy_success, is_get_account_financials_error, is_get_account_financials_success, @@ -1119,6 +1121,7 @@ def __init__(self, *args: object, **kwargs: object) -> None: "CreateContentStandardsSuccessResponse", "CreateMediaBuyErrorResponse", "CreateMediaBuySuccessResponse", + "CreateMediaBuySubmittedResponse", "Deployment", "Destination", "GetContentStandardsErrorResponse", diff --git a/src/adcp/types/aliases.py b/src/adcp/types/aliases.py index 5a5949a19..ff325878a 100644 --- a/src/adcp/types/aliases.py +++ b/src/adcp/types/aliases.py @@ -78,6 +78,7 @@ # Create media buy responses CreateMediaBuyResponse1, CreateMediaBuyResponse2, + CreateMediaBuyResponse3, # DAAST assets DaastAsset1, DaastAsset2, @@ -291,6 +292,9 @@ CreateMediaBuyErrorResponse = CreateMediaBuyResponse2 """Error response - media buy creation failed, no media buy created.""" +CreateMediaBuySubmittedResponse = CreateMediaBuyResponse3 +"""Async-submitted response - media buy queued for human review; poll task_id for completion.""" + # Performance Feedback Response Variants ProvidePerformanceFeedbackSuccessResponse = ProvidePerformanceFeedbackResponse1 """Success response - performance feedback accepted.""" @@ -1489,6 +1493,7 @@ def get_pricing(options: list[PricingOption]) -> None: # Create media buy responses "CreateMediaBuySuccessResponse", "CreateMediaBuyErrorResponse", + "CreateMediaBuySubmittedResponse", # Creative delivery requests "GetCreativeDeliveryByMediaBuyRequest", "GetCreativeDeliveryByBuyerRefRequest", diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py index 298e9773b..cf1d781c0 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py @@ -4,8 +4,10 @@ from __future__ import annotations +from typing import Annotated, Literal + from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict +from pydantic import ConfigDict, Field from ..core import context as context_1 from ..core import ext as ext_1 @@ -15,5 +17,15 @@ class CreateMediaBuySubmitted(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) + status: Annotated[ + Literal['submitted'], + Field(description='Discriminates this async envelope from the synchronous success shape.'), + ] = 'submitted' + task_id: Annotated[ + str, + Field( + description='Task handle the buyer uses with tasks/get. The media_buy_id is issued on the completion artifact, not here.' + ), + ] context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/guards.py b/src/adcp/types/guards.py index 8a908ea10..e9510512e 100644 --- a/src/adcp/types/guards.py +++ b/src/adcp/types/guards.py @@ -79,6 +79,7 @@ def is_adcp_success(response: Any) -> bool: CalibrateContentErrorResponse, CalibrateContentSuccessResponse, CreateMediaBuyErrorResponse, + CreateMediaBuySubmittedResponse, CreateMediaBuySuccessResponse, GetAccountFinancialsErrorResponse, GetAccountFinancialsSuccessResponse, @@ -103,7 +104,9 @@ def is_adcp_success(response: Any) -> bool: ) # Type aliases for response unions -CreateMediaBuyResponse = CreateMediaBuySuccessResponse | CreateMediaBuyErrorResponse +CreateMediaBuyResponse = ( + CreateMediaBuySuccessResponse | CreateMediaBuyErrorResponse | CreateMediaBuySubmittedResponse +) UpdateMediaBuyResponse = UpdateMediaBuySuccessResponse | UpdateMediaBuyErrorResponse ActivateSignalResponse = ActivateSignalSuccessResponse | ActivateSignalErrorResponse BuildCreativeResponse = BuildCreativeSuccessResponse | BuildCreativeErrorResponse @@ -116,11 +119,18 @@ def is_adcp_success(response: Any) -> bool: # --- Create Media Buy --- +def is_create_media_buy_submitted( + response: CreateMediaBuyResponse, +) -> TypeGuard[CreateMediaBuySubmittedResponse]: + """Check if a CreateMediaBuyResponse is an async-submitted envelope.""" + return getattr(response, "status", None) == "submitted" + + def is_create_media_buy_success( response: CreateMediaBuyResponse, ) -> TypeGuard[CreateMediaBuySuccessResponse]: - """Check if a CreateMediaBuyResponse is a success.""" - return not is_adcp_error(response) + """Check if a CreateMediaBuyResponse is a synchronous success.""" + return not is_adcp_error(response) and not is_create_media_buy_submitted(response) def is_create_media_buy_error( @@ -308,6 +318,7 @@ def is_get_creative_features_success( "is_adcp_error", "is_adcp_success", # Media buy guards + "is_create_media_buy_submitted", "is_create_media_buy_success", "is_create_media_buy_error", "is_update_media_buy_success", diff --git a/tests/fixtures/public_api_snapshot.json b/tests/fixtures/public_api_snapshot.json index bfeede817..dbacfcd50 100644 --- a/tests/fixtures/public_api_snapshot.json +++ b/tests/fixtures/public_api_snapshot.json @@ -94,6 +94,7 @@ "CreateMediaBuyErrorResponse", "CreateMediaBuyRequest", "CreateMediaBuyResponse", + "CreateMediaBuySubmittedResponse", "CreateMediaBuySuccessResponse", "Creative", "CreativeApproval", @@ -492,6 +493,7 @@ "CreateMediaBuyErrorResponse", "CreateMediaBuyRequest", "CreateMediaBuyResponse", + "CreateMediaBuySubmittedResponse", "CreateMediaBuySuccessResponse", "CreatePropertyListRequest", "CreatePropertyListResponse",