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
16 changes: 8 additions & 8 deletions src/core/schema_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from src.core.schemas_generated._schemas_v1_media_buy_get_products_request_json import (
BrandManifest,
BrandManifest8,
BrandManifest10,
Filters,
GetProductsRequest,
)
Expand All @@ -29,7 +29,7 @@
def create_get_products_request(
brief: str = "",
promoted_offering: str | None = None,
brand_manifest: BrandManifest | BrandManifest8 | str | dict[str, Any] | None = None,
brand_manifest: BrandManifest | BrandManifest10 | str | dict[str, Any] | None = None,
filters: Filters | dict[str, Any] | None = None,
) -> GetProductsRequest:
"""Create GetProductsRequest.
Expand Down Expand Up @@ -65,15 +65,15 @@ def create_get_products_request(
filters_obj = filters

# Convert brand_manifest to proper type
brand_manifest_obj: BrandManifest | BrandManifest8 | AnyUrl | None = None
brand_manifest_obj: BrandManifest | BrandManifest10 | AnyUrl | None = None
if isinstance(brand_manifest, dict):
# Choose BrandManifest or BrandManifest8 based on what's provided
# Choose BrandManifest or BrandManifest10 based on what's provided
if "url" in brand_manifest and brand_manifest["url"] is not None:
# Has url - use BrandManifest (url-required variant)
brand_manifest_obj = BrandManifest(**brand_manifest)
elif "name" in brand_manifest:
# Only name - use BrandManifest8 (both optional)
brand_manifest_obj = BrandManifest8(**brand_manifest)
# Only name - use BrandManifest10 (both optional)
brand_manifest_obj = BrandManifest10(**brand_manifest)
elif isinstance(brand_manifest, str):
# URL string
brand_manifest_obj = AnyUrl(brand_manifest) # type: ignore[assignment]
Expand All @@ -83,7 +83,7 @@ def create_get_products_request(
# Handle promoted_offering → brand_manifest conversion (backward compat)
if promoted_offering and not brand_manifest_obj:
# Convert promoted_offering to brand_manifest for AdCP spec compliance
brand_manifest_obj = BrandManifest8(name=promoted_offering)
brand_manifest_obj = BrandManifest10(name=promoted_offering)

# Create single flat GetProductsRequest (AdCP spec fields only)
return GetProductsRequest(
Expand Down Expand Up @@ -126,7 +126,7 @@ def create_get_products_response(
"GetProductsRequest",
"GetProductsResponse",
"BrandManifest",
"BrandManifest8",
"BrandManifest10",
"Filters",
"Product",
]
6 changes: 3 additions & 3 deletions src/core/schemas_generated/_schemas_v1_adagents_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Optional
from typing import Annotated

from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field

Expand All @@ -30,13 +30,13 @@ class AuthorizedSalesAgents(BaseModel):
extra="forbid",
)
field_schema: Annotated[
Optional[str], Field(alias="$schema", description="JSON Schema identifier for this adagents.json file")
str | None, Field(alias="$schema", description="JSON Schema identifier for this adagents.json file")
] = "https://adcontextprotocol.org/schemas/v1/adagents.json"
authorized_agents: Annotated[
list[AuthorizedAgent],
Field(description="Array of sales agents authorized to sell this publisher's inventory", min_length=1),
]
last_updated: Annotated[
Optional[AwareDatetime],
AwareDatetime | None,
Field(description="ISO 8601 timestamp indicating when this file was last updated (optional but recommended)"),
] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field

Expand All @@ -16,6 +16,6 @@ class AudioAsset(BaseModel):
)
asset_type: Literal["audio"]
url: Annotated[AnyUrl, Field(description="URL to the audio asset")]
duration_ms: Annotated[Optional[int], Field(description="Audio duration in milliseconds", ge=0)] = None
format: Annotated[Optional[str], Field(description="Audio file format (mp3, wav, aac, etc.)")] = None
bitrate_kbps: Annotated[Optional[int], Field(description="Audio bitrate in kilobits per second", ge=1)] = None
duration_ms: Annotated[int | None, Field(description="Audio duration in milliseconds", ge=0)] = None
format: Annotated[str | None, Field(description="Audio file format (mp3, wav, aac, etc.)")] = None
bitrate_kbps: Annotated[int | None, Field(description="Audio bitrate in kilobits per second", ge=1)] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import BaseModel, ConfigDict, Field

Expand All @@ -16,4 +16,4 @@ class CssAsset(BaseModel):
)
asset_type: Literal["css"]
content: Annotated[str, Field(description="CSS content")]
media: Annotated[Optional[str], Field(description="CSS media query context (e.g., 'screen', 'print')")] = None
media: Annotated[str | None, Field(description="CSS media query context (e.g., 'screen', 'print')")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

from enum import Enum
from typing import Annotated, Literal, Optional, Union
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel

Expand Down Expand Up @@ -36,37 +36,37 @@ class DaastAsset1(BaseModel):
)
asset_type: Literal["daast"]
url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")]
content: Annotated[Optional[str], Field(description="Inline DAAST XML content")] = None
daast_version: Annotated[Optional[DaastVersion], Field(description="DAAST specification version")] = None
content: Annotated[str | None, Field(description="Inline DAAST XML content")] = None
daast_version: Annotated[DaastVersion | None, Field(description="DAAST specification version")] = None
duration_ms: Annotated[
Optional[int], Field(description="Expected audio duration in milliseconds (if known)", ge=0)
int | None, Field(description="Expected audio duration in milliseconds (if known)", ge=0)
] = None
tracking_events: Annotated[
Optional[list[TrackingEvent]], Field(description="Tracking events supported by this DAAST tag")
list[TrackingEvent] | None, Field(description="Tracking events supported by this DAAST tag")
] = None
companion_ads: Annotated[Optional[bool], Field(description="Whether companion display ads are included")] = None
companion_ads: Annotated[bool | None, Field(description="Whether companion display ads are included")] = None


class DaastAsset2(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
asset_type: Literal["daast"]
url: Annotated[Optional[AnyUrl], Field(description="URL endpoint that returns DAAST XML")] = None
url: Annotated[AnyUrl | None, Field(description="URL endpoint that returns DAAST XML")] = None
content: Annotated[str, Field(description="Inline DAAST XML content")]
daast_version: Annotated[Optional[DaastVersion], Field(description="DAAST specification version")] = None
daast_version: Annotated[DaastVersion | None, Field(description="DAAST specification version")] = None
duration_ms: Annotated[
Optional[int], Field(description="Expected audio duration in milliseconds (if known)", ge=0)
int | None, Field(description="Expected audio duration in milliseconds (if known)", ge=0)
] = None
tracking_events: Annotated[
Optional[list[TrackingEvent]], Field(description="Tracking events supported by this DAAST tag")
list[TrackingEvent] | None, Field(description="Tracking events supported by this DAAST tag")
] = None
companion_ads: Annotated[Optional[bool], Field(description="Whether companion display ads are included")] = None
companion_ads: Annotated[bool | None, Field(description="Whether companion display ads are included")] = None


class DaastAsset(RootModel[Union[DaastAsset1, DaastAsset2]]):
class DaastAsset(RootModel[DaastAsset1 | DaastAsset2]):
root: Annotated[
Union[DaastAsset1, DaastAsset2],
DaastAsset1 | DaastAsset2,
Field(
description="DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving",
title="DAAST Asset",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import BaseModel, ConfigDict, Field

Expand All @@ -16,4 +16,4 @@ class HtmlAsset(BaseModel):
)
asset_type: Literal["html"]
content: Annotated[str, Field(description="HTML content")]
version: Annotated[Optional[str], Field(description="HTML version (e.g., 'HTML5')")] = None
version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field

Expand All @@ -16,7 +16,7 @@ class ImageAsset(BaseModel):
)
asset_type: Literal["image"]
url: Annotated[AnyUrl, Field(description="URL to the image asset")]
width: Annotated[Optional[int], Field(description="Image width in pixels", ge=1)] = None
height: Annotated[Optional[int], Field(description="Image height in pixels", ge=1)] = None
format: Annotated[Optional[str], Field(description="Image file format (jpg, png, gif, webp, etc.)")] = None
alt_text: Annotated[Optional[str], Field(description="Alternative text for accessibility")] = None
width: Annotated[int | None, Field(description="Image width in pixels", ge=1)] = None
height: Annotated[int | None, Field(description="Image height in pixels", ge=1)] = None
format: Annotated[str | None, Field(description="Image file format (jpg, png, gif, webp, etc.)")] = None
alt_text: Annotated[str | None, Field(description="Alternative text for accessibility")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

from enum import Enum
from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import BaseModel, ConfigDict, Field

Expand All @@ -23,4 +23,4 @@ class JavascriptAsset(BaseModel):
)
asset_type: Literal["javascript"]
content: Annotated[str, Field(description="JavaScript content")]
module_type: Annotated[Optional[ModuleType], Field(description="JavaScript module type")] = None
module_type: Annotated[ModuleType | None, Field(description="JavaScript module type")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field


class Colors(BaseModel):
primary: Optional[str] = None
secondary: Optional[str] = None
accent: Optional[str] = None
primary: str | None = None
secondary: str | None = None
accent: str | None = None


class PromotedOfferingsAsset(BaseModel):
Expand All @@ -22,8 +22,8 @@ class PromotedOfferingsAsset(BaseModel):
)
asset_type: Literal["promoted_offerings"]
url: Annotated[
Optional[AnyUrl], Field(description="URL of the advertiser's brand or offering (e.g., https://retailer.com)")
AnyUrl | None, Field(description="URL of the advertiser's brand or offering (e.g., https://retailer.com)")
] = None
colors: Annotated[Optional[Colors], Field(description="Brand colors")] = None
fonts: Annotated[Optional[list[str]], Field(description="Brand fonts")] = None
tone: Annotated[Optional[str], Field(description="Brand tone/voice")] = None
colors: Annotated[Colors | None, Field(description="Brand colors")] = None
fonts: Annotated[list[str] | None, Field(description="Brand fonts")] = None
tone: Annotated[str | None, Field(description="Brand tone/voice")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import BaseModel, ConfigDict, Field

Expand All @@ -16,5 +16,5 @@ class TextAsset(BaseModel):
)
asset_type: Literal["text"]
content: Annotated[str, Field(description="Text content")]
max_length: Annotated[Optional[int], Field(description="Maximum character length constraint", ge=1)] = None
language: Annotated[Optional[str], Field(description="Language code (e.g., 'en', 'es', 'fr')")] = None
max_length: Annotated[int | None, Field(description="Maximum character length constraint", ge=1)] = None
language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field

Expand All @@ -16,4 +16,4 @@ class UrlAsset(BaseModel):
)
asset_type: Literal["url"]
url: Annotated[AnyUrl, Field(description="URL reference")]
description: Annotated[Optional[str], Field(description="Description of what this URL points to")] = None
description: Annotated[str | None, Field(description="Description of what this URL points to")] = None
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

from enum import Enum
from typing import Annotated, Literal, Optional, Union
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel

Expand Down Expand Up @@ -44,19 +44,19 @@ class VastAsset1(BaseModel):
)
asset_type: Literal["vast"]
url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")]
content: Annotated[Optional[str], Field(description="Inline VAST XML content")] = None
vast_version: Annotated[Optional[VastVersion], Field(description="VAST specification version")] = None
content: Annotated[str | None, Field(description="Inline VAST XML content")] = None
vast_version: Annotated[VastVersion | None, Field(description="VAST specification version")] = None
vpaid_enabled: Annotated[
Optional[bool], Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
bool | None, Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
] = None
max_wrapper_depth: Annotated[
Optional[int], Field(description="Maximum allowed wrapper/redirect depth", ge=0, le=10)
int | None, Field(description="Maximum allowed wrapper/redirect depth", ge=0, le=10)
] = None
duration_ms: Annotated[
Optional[int], Field(description="Expected video duration in milliseconds (if known)", ge=0)
int | None, Field(description="Expected video duration in milliseconds (if known)", ge=0)
] = None
tracking_events: Annotated[
Optional[list[TrackingEvent]], Field(description="Tracking events supported by this VAST tag")
list[TrackingEvent] | None, Field(description="Tracking events supported by this VAST tag")
] = None


Expand All @@ -65,25 +65,25 @@ class VastAsset2(BaseModel):
extra="forbid",
)
asset_type: Literal["vast"]
url: Annotated[Optional[AnyUrl], Field(description="URL endpoint that returns VAST XML")] = None
url: Annotated[AnyUrl | None, Field(description="URL endpoint that returns VAST XML")] = None
content: Annotated[str, Field(description="Inline VAST XML content")]
vast_version: Annotated[Optional[VastVersion], Field(description="VAST specification version")] = None
vast_version: Annotated[VastVersion | None, Field(description="VAST specification version")] = None
vpaid_enabled: Annotated[
Optional[bool], Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
bool | None, Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
] = None
max_wrapper_depth: Annotated[
Optional[int], Field(description="Maximum allowed wrapper/redirect depth", ge=0, le=10)
int | None, Field(description="Maximum allowed wrapper/redirect depth", ge=0, le=10)
] = None
duration_ms: Annotated[
Optional[int], Field(description="Expected video duration in milliseconds (if known)", ge=0)
int | None, Field(description="Expected video duration in milliseconds (if known)", ge=0)
] = None
tracking_events: Annotated[
Optional[list[TrackingEvent]], Field(description="Tracking events supported by this VAST tag")
list[TrackingEvent] | None, Field(description="Tracking events supported by this VAST tag")
] = None


class VastAsset(RootModel[Union[VastAsset1, VastAsset2]]):
class VastAsset(RootModel[VastAsset1 | VastAsset2]):
root: Annotated[
Union[VastAsset1, VastAsset2],
VastAsset1 | VastAsset2,
Field(description="VAST (Video Ad Serving Template) tag for third-party video ad serving", title="VAST Asset"),
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Literal, Optional
from typing import Annotated, Literal

from pydantic import AnyUrl, BaseModel, ConfigDict, Field

Expand All @@ -16,8 +16,8 @@ class VideoAsset(BaseModel):
)
asset_type: Literal["video"]
url: Annotated[AnyUrl, Field(description="URL to the video asset")]
width: Annotated[Optional[int], Field(description="Video width in pixels", ge=1)] = None
height: Annotated[Optional[int], Field(description="Video height in pixels", ge=1)] = None
duration_ms: Annotated[Optional[int], Field(description="Video duration in milliseconds", ge=0)] = None
format: Annotated[Optional[str], Field(description="Video file format (mp4, webm, mov, etc.)")] = None
bitrate_kbps: Annotated[Optional[int], Field(description="Video bitrate in kilobits per second", ge=1)] = None
width: Annotated[int | None, Field(description="Video width in pixels", ge=1)] = None
height: Annotated[int | None, Field(description="Video height in pixels", ge=1)] = None
duration_ms: Annotated[int | None, Field(description="Video duration in milliseconds", ge=0)] = None
format: Annotated[str | None, Field(description="Video file format (mp4, webm, mov, etc.)")] = None
bitrate_kbps: Annotated[int | None, Field(description="Video bitrate in kilobits per second", ge=1)] = None
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import Annotated, Optional
from typing import Annotated

from pydantic import BaseModel, ConfigDict, Field

Expand All @@ -15,4 +15,4 @@ class CreativeAssignment(BaseModel):
extra="forbid",
)
creative_id: Annotated[str, Field(description="Unique identifier for the creative")]
weight: Annotated[Optional[float], Field(description="Delivery weight for this creative", ge=0.0, le=100.0)] = None
weight: Annotated[float | None, Field(description="Delivery weight for this creative", ge=0.0, le=100.0)] = None
Loading