From 73ea15b97562cd2b46f19e3d9e23b4e4f211355d Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 14:26:31 -0500 Subject: [PATCH 1/8] chore: upgrade to AdCP protocol 2.6.0 - Update ADCP_VERSION to 2.6.0 - Sync schemas from upstream adcontextprotocol.org - Regenerate Python types from new schemas - Fix sync_schemas.py to look for ADCP_VERSION in correct location (src/adcp/) - Fix Makefile to use generate_types.py instead of missing generate_models_simple.py --- Makefile | 4 +- schemas/cache/.hashes.json | 306 +++++++++--------- schemas/cache/adagents.json | 26 +- schemas/cache/core/activation-key.json | 4 +- schemas/cache/core/assets/audio-asset.json | 2 +- schemas/cache/core/assets/css-asset.json | 2 +- schemas/cache/core/assets/daast-asset.json | 4 +- schemas/cache/core/assets/html-asset.json | 2 +- schemas/cache/core/assets/image-asset.json | 2 +- .../cache/core/assets/javascript-asset.json | 2 +- schemas/cache/core/assets/text-asset.json | 2 +- schemas/cache/core/assets/url-asset.json | 2 +- schemas/cache/core/assets/vast-asset.json | 4 +- schemas/cache/core/assets/video-asset.json | 2 +- schemas/cache/core/assets/webhook-asset.json | 2 +- schemas/cache/core/brand-manifest.json | 6 +- schemas/cache/core/creative-asset.json | 6 +- schemas/cache/core/creative-assignment.json | 2 +- schemas/cache/core/creative-filters.json | 2 +- schemas/cache/core/creative-manifest.json | 4 +- schemas/cache/core/creative-policy.json | 2 +- schemas/cache/core/delivery-metrics.json | 4 +- schemas/cache/core/deployment.json | 4 +- schemas/cache/core/destination.json | 4 +- schemas/cache/core/error.json | 6 +- schemas/cache/core/format-id.json | 2 +- schemas/cache/core/format.json | 128 +++++++- schemas/cache/core/frequency-cap.json | 2 +- schemas/cache/core/measurement.json | 2 +- schemas/cache/core/media-buy.json | 2 +- schemas/cache/core/package.json | 2 +- schemas/cache/core/performance-feedback.json | 4 +- schemas/cache/core/placement.json | 2 +- schemas/cache/core/product-filters.json | 4 +- schemas/cache/core/product.json | 6 +- schemas/cache/core/promoted-offerings.json | 6 +- schemas/cache/core/promoted-products.json | 2 +- schemas/cache/core/property.json | 4 +- schemas/cache/core/protocol-envelope.json | 2 +- .../core/publisher-property-selector.json | 6 +- .../cache/core/reporting-capabilities.json | 2 +- schemas/cache/core/response.json | 2 +- schemas/cache/core/signal-filters.json | 2 +- schemas/cache/core/sub-asset.json | 4 +- schemas/cache/core/targeting.json | 2 +- schemas/cache/creative/asset-types/index.json | 8 +- .../list-creative-formats-request.json | 2 +- .../list-creative-formats-response.json | 2 +- .../creative/preview-creative-request.json | 12 +- .../creative/preview-creative-response.json | 4 +- schemas/cache/creative/preview-render.json | 6 +- .../media-buy/build-creative-request.json | 2 +- .../media-buy/build-creative-response.json | 4 +- ...dia-buy-async-response-input-required.json | 2 +- ...te-media-buy-async-response-submitted.json | 2 +- ...eate-media-buy-async-response-working.json | 2 +- .../media-buy/create-media-buy-request.json | 96 ++++-- .../media-buy/create-media-buy-response.json | 4 +- .../get-media-buy-delivery-request.json | 2 +- .../get-media-buy-delivery-response.json | 10 +- ...roducts-async-response-input-required.json | 2 +- ...get-products-async-response-submitted.json | 2 +- .../get-products-async-response-working.json | 2 +- .../cache/media-buy/get-products-request.json | 2 +- .../media-buy/get-products-response.json | 2 +- .../list-authorized-properties-request.json | 2 +- .../list-authorized-properties-response.json | 2 +- .../list-creative-formats-request.json | 2 +- .../list-creative-formats-response.json | 2 +- .../media-buy/list-creatives-request.json | 6 +- .../media-buy/list-creatives-response.json | 18 +- schemas/cache/media-buy/package-request.json | 2 +- .../provide-performance-feedback-request.json | 4 +- ...provide-performance-feedback-response.json | 4 +- ...eatives-async-response-input-required.json | 2 +- ...nc-creatives-async-response-submitted.json | 2 +- ...sync-creatives-async-response-working.json | 2 +- .../media-buy/sync-creatives-request.json | 4 +- .../media-buy/sync-creatives-response.json | 8 +- ...dia-buy-async-response-input-required.json | 2 +- ...te-media-buy-async-response-submitted.json | 2 +- ...date-media-buy-async-response-working.json | 2 +- .../media-buy/update-media-buy-request.json | 4 +- .../media-buy/update-media-buy-response.json | 4 +- schemas/cache/pricing-options/cpc-option.json | 2 +- .../cache/pricing-options/cpcv-option.json | 2 +- .../pricing-options/cpm-auction-option.json | 2 +- .../pricing-options/cpm-fixed-option.json | 2 +- schemas/cache/pricing-options/cpp-option.json | 4 +- schemas/cache/pricing-options/cpv-option.json | 6 +- .../pricing-options/flat-rate-option.json | 4 +- .../pricing-options/vcpm-auction-option.json | 2 +- .../pricing-options/vcpm-fixed-option.json | 2 +- schemas/cache/protocols/adcp-extension.json | 2 +- .../signals/activate-signal-request.json | 2 +- .../signals/activate-signal-response.json | 4 +- .../cache/signals/get-signals-request.json | 4 +- .../cache/signals/get-signals-response.json | 6 +- scripts/sync_schemas.py | 2 +- src/adcp/ADCP_VERSION | 2 +- src/adcp/types/_ergonomic.py | 29 +- src/adcp/types/_generated.py | 8 +- src/adcp/types/generated_poc/adagents.py | 28 +- .../generated_poc/core/activation_key.py | 6 +- .../generated_poc/core/assets/audio_asset.py | 4 +- .../generated_poc/core/assets/css_asset.py | 4 +- .../generated_poc/core/assets/daast_asset.py | 6 +- .../generated_poc/core/assets/html_asset.py | 4 +- .../generated_poc/core/assets/image_asset.py | 4 +- .../core/assets/javascript_asset.py | 4 +- .../generated_poc/core/assets/text_asset.py | 4 +- .../generated_poc/core/assets/url_asset.py | 4 +- .../generated_poc/core/assets/vast_asset.py | 6 +- .../generated_poc/core/assets/video_asset.py | 4 +- .../core/assets/webhook_asset.py | 4 +- .../generated_poc/core/brand_manifest.py | 8 +- src/adcp/types/generated_poc/core/context.py | 3 +- .../generated_poc/core/creative_asset.py | 6 +- .../generated_poc/core/creative_assignment.py | 4 +- .../generated_poc/core/creative_filters.py | 4 +- .../generated_poc/core/creative_manifest.py | 4 +- .../generated_poc/core/creative_policy.py | 4 +- .../generated_poc/core/delivery_metrics.py | 6 +- .../types/generated_poc/core/deployment.py | 6 +- .../types/generated_poc/core/destination.py | 6 +- src/adcp/types/generated_poc/core/error.py | 10 +- src/adcp/types/generated_poc/core/ext.py | 3 +- src/adcp/types/generated_poc/core/format.py | 100 +++++- .../types/generated_poc/core/format_id.py | 4 +- .../types/generated_poc/core/frequency_cap.py | 4 +- .../types/generated_poc/core/measurement.py | 4 +- .../types/generated_poc/core/media_buy.py | 4 +- src/adcp/types/generated_poc/core/package.py | 4 +- .../core/performance_feedback.py | 6 +- .../types/generated_poc/core/placement.py | 4 +- src/adcp/types/generated_poc/core/product.py | 8 +- .../generated_poc/core/product_filters.py | 8 +- .../generated_poc/core/promoted_offerings.py | 8 +- .../generated_poc/core/promoted_products.py | 4 +- src/adcp/types/generated_poc/core/property.py | 6 +- .../generated_poc/core/protocol_envelope.py | 4 +- .../core/publisher_property_selector.py | 8 +- .../core/reporting_capabilities.py | 4 +- src/adcp/types/generated_poc/core/response.py | 4 +- .../generated_poc/core/signal_filters.py | 4 +- .../types/generated_poc/core/sub_asset.py | 6 +- .../types/generated_poc/core/targeting.py | 4 +- .../creative/list_creative_formats_request.py | 4 +- .../list_creative_formats_response.py | 4 +- .../creative/preview_creative_request.py | 14 +- .../creative/preview_creative_response.py | 6 +- .../generated_poc/creative/preview_render.py | 8 +- .../media_buy/build_creative_request.py | 4 +- .../media_buy/build_creative_response.py | 6 +- ...media_buy_async_response_input_required.py | 4 +- ...eate_media_buy_async_response_submitted.py | 4 +- ...create_media_buy_async_response_working.py | 4 +- .../media_buy/create_media_buy_request.py | 53 ++- .../media_buy/create_media_buy_response.py | 6 +- .../get_media_buy_delivery_request.py | 4 +- .../get_media_buy_delivery_response.py | 12 +- ..._products_async_response_input_required.py | 4 +- .../get_products_async_response_submitted.py | 4 +- .../get_products_async_response_working.py | 4 +- .../media_buy/get_products_request.py | 4 +- .../media_buy/get_products_response.py | 4 +- .../list_authorized_properties_request.py | 4 +- .../list_authorized_properties_response.py | 4 +- .../list_creative_formats_request.py | 4 +- .../list_creative_formats_response.py | 4 +- .../media_buy/list_creatives_request.py | 10 +- .../media_buy/list_creatives_response.py | 18 +- .../media_buy/package_request.py | 4 +- .../provide_performance_feedback_request.py | 8 +- .../provide_performance_feedback_response.py | 6 +- ...creatives_async_response_input_required.py | 4 +- ...sync_creatives_async_response_submitted.py | 4 +- .../sync_creatives_async_response_working.py | 4 +- .../media_buy/sync_creatives_request.py | 4 +- .../media_buy/sync_creatives_response.py | 8 +- ...media_buy_async_response_input_required.py | 4 +- ...date_media_buy_async_response_submitted.py | 4 +- ...update_media_buy_async_response_working.py | 4 +- .../media_buy/update_media_buy_request.py | 10 +- .../media_buy/update_media_buy_response.py | 6 +- .../pricing_options/cpc_option.py | 4 +- .../pricing_options/cpcv_option.py | 4 +- .../pricing_options/cpm_auction_option.py | 4 +- .../pricing_options/cpm_fixed_option.py | 4 +- .../pricing_options/cpp_option.py | 6 +- .../pricing_options/cpv_option.py | 8 +- .../pricing_options/flat_rate_option.py | 6 +- .../pricing_options/vcpm_auction_option.py | 4 +- .../pricing_options/vcpm_fixed_option.py | 4 +- .../generated_poc/protocols/adcp_extension.py | 4 +- .../signals/activate_signal_request.py | 4 +- .../signals/activate_signal_response.py | 6 +- .../signals/get_signals_request.py | 6 +- .../signals/get_signals_response.py | 8 +- 199 files changed, 943 insertions(+), 659 deletions(-) diff --git a/Makefile b/Makefile index fb772eec9..2ce963f74 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ regenerate-schemas: ## Download latest schemas and regenerate models @echo "Fixing schema references..." $(PYTHON) scripts/fix_schema_refs.py @echo "Generating Pydantic models..." - $(PYTHON) scripts/generate_models_simple.py + $(PYTHON) scripts/generate_types.py @echo "✓ Schemas regenerated successfully" validate-generated: ## Validate generated code (syntax and imports) @@ -99,7 +99,7 @@ check-schema-drift: ## Check if schemas are out of sync with upstream @echo "Checking for schema drift..." @$(PYTHON) scripts/sync_schemas.py @$(PYTHON) scripts/fix_schema_refs.py - @$(PYTHON) scripts/generate_models_simple.py + @$(PYTHON) scripts/generate_types.py @if git diff --exit-code src/adcp/types/generated.py schemas/cache/; then \ echo "✓ Schemas are up-to-date"; \ else \ diff --git a/schemas/cache/.hashes.json b/schemas/cache/.hashes.json index 819cf0e7d..1b43218ad 100644 --- a/schemas/cache/.hashes.json +++ b/schemas/cache/.hashes.json @@ -1,155 +1,155 @@ { - "https://adcontextprotocol.org/schemas/v1/index.json": "66f2aee679deca39a3568e306d2ee5fffd6787f2481c5091a939477350d94500", - "https://adcontextprotocol.org/schemas/latest/adagents.json": "ca971f574560e40457d05d6356adee231479592bce51dd07cd28b21d78d31dda", - "https://adcontextprotocol.org/schemas/latest/core/activation-key.json": "d4429a894016a2598f8ff48e330a438196bc4b42dad024f7aec55432e8970692", - "https://adcontextprotocol.org/schemas/latest/core/assets/audio-asset.json": "7ab9e762afe3486c9059a529736b37ef11cd905c60c8aaf8f19fb2812844ba85", - "https://adcontextprotocol.org/schemas/latest/core/assets/css-asset.json": "088774919bff4dd4319de55e663b828208596da92de15a50ab3f1479c102b8df", - "https://adcontextprotocol.org/schemas/latest/core/assets/daast-asset.json": "7dd9f5fb417926f6b214a8c9b29da3d89296ea7135112ab400239a7f8631d972", - "https://adcontextprotocol.org/schemas/latest/core/assets/html-asset.json": "532eebc05ad8534d8e23eb3cbce88e8171fcefc7821957530b4014d7d713228b", - "https://adcontextprotocol.org/schemas/latest/core/assets/image-asset.json": "342deb6c4918344842479dd53be9f8128401bcdea33512c6bd28edb4fdc89092", - "https://adcontextprotocol.org/schemas/latest/core/assets/javascript-asset.json": "72967e4e679a225e8bc8d1db325db0ee751edd97118ca7b36e1cb1f8a8b86644", - "https://adcontextprotocol.org/schemas/latest/core/assets/text-asset.json": "f5fff3619e3f12ce29c87c8c5b351853e8504e25454f3dcbcd905476551da819", - "https://adcontextprotocol.org/schemas/latest/core/assets/url-asset.json": "b7590bf3a3e48c95ebb08014a8cfb7fb1deea536b1e65bec7f7c329abeb4589f", - "https://adcontextprotocol.org/schemas/latest/core/assets/vast-asset.json": "a7914f85a3737c8e0aec858b8f6fc894eee5c877a653a1737ae4674b5533795c", - "https://adcontextprotocol.org/schemas/latest/core/assets/video-asset.json": "83937d482ef0e4c01f4f833711d47a67fdcfba42544043b21ab3bb9a5bda247e", - "https://adcontextprotocol.org/schemas/latest/core/assets/webhook-asset.json": "e1b9b45c3305349d571003371502693828b57eedc9fe9f12b7fb071a7f5ea3f2", - "https://adcontextprotocol.org/schemas/latest/core/async-response-data.json": "b3e3e57e1a121067cdd6392265223a14b89ebb27220a18d822ffdeb09e7b7523", - "https://adcontextprotocol.org/schemas/latest/core/brand-manifest-ref.json": "10bd77dc7e07fb8e8a0665272c18cdcb7f05afc72856ffd66e6f2505431d7612", - "https://adcontextprotocol.org/schemas/latest/core/brand-manifest.json": "127183790905f2ad1b52f2097e89f714f071543654d12ea3900f8b41acdeb99a", - "https://adcontextprotocol.org/schemas/latest/core/context.json": "b5b5de9482d662c1eacfcfdfa53de672a047664e295940cb204f2d822d5eeb31", - "https://adcontextprotocol.org/schemas/latest/core/creative-asset.json": "a971362eaef05186b663cf22db6d03bab876fba63547c836db14fea86c5f2ce1", - "https://adcontextprotocol.org/schemas/latest/core/creative-assignment.json": "36cabb2da7e19b7e99f7e91ba2d5ac62ba881f336f7735213484a9c5c9882f8b", - "https://adcontextprotocol.org/schemas/latest/core/creative-filters.json": "5da9f8ee13b3ea261b887acf39241893c022491f95e48f1ffbaf1bccedc1d331", - "https://adcontextprotocol.org/schemas/latest/core/creative-manifest.json": "0e5f29f44b35509f7d8709604a82dfdfb32401672ec22c4924fc78e3877c0914", - "https://adcontextprotocol.org/schemas/latest/core/creative-policy.json": "adfba827378e11aace7ded9c173d55043d5f6d4e6a61321b1e0640cd2e447545", - "https://adcontextprotocol.org/schemas/latest/core/delivery-metrics.json": "c04cc7a46cf2d8d11134ae0a9e5662d050991521781d4d2521c3d72ad0717508", - "https://adcontextprotocol.org/schemas/latest/core/deployment.json": "d72caa8138af5bca256cb1c5502b3313a249ff7484c611fc813ccbc59d77222b", - "https://adcontextprotocol.org/schemas/latest/core/destination.json": "0ce81da756e6e8d57747f106a1b3d6bfdae3756f835bbc6bcc8baff2896f5819", - "https://adcontextprotocol.org/schemas/latest/core/error.json": "db54eb32908dcfa23b77e28ef1d317bdb26c4715d2bcee48f5619429f21e9f11", - "https://adcontextprotocol.org/schemas/latest/core/ext.json": "0dc59d0cf5bcf97f9ce9ba635f977ec65b982e853cc0b05decb034cfb642f4b5", - "https://adcontextprotocol.org/schemas/latest/core/format-id.json": "1ae1959498a13f4d944196dc5967f098855d27a87e3eb4ea5d3e4e3d587f52cf", - "https://adcontextprotocol.org/schemas/latest/core/format.json": "db547a8703d297173c56a789aee7430328941d77881227deefb89beaf4a4373a", - "https://adcontextprotocol.org/schemas/latest/core/frequency-cap.json": "6b43e269f021f6230001ab7923761cafa6402468379d595c4e89a3afa1f17919", - "https://adcontextprotocol.org/schemas/latest/core/mcp-webhook-payload.json": "1dae520cb0c0564f4c647a5fba4cb8383897f28dcf72a2d046986684255f099e", - "https://adcontextprotocol.org/schemas/latest/core/measurement.json": "596c14a1c135928937a1a238a8a0aaa0d9bc43e6f7a497b553746afa8e9f4161", - "https://adcontextprotocol.org/schemas/latest/core/media-buy.json": "0bd1dd219544a254ad5ab38ca6f5fa7e7b14e3e1185d865035e23130a6037dd2", - "https://adcontextprotocol.org/schemas/latest/core/package.json": "892d138037b86077e2effee0f9eabdb4c0d2d87c52ae0c99c746affc4f90a791", - "https://adcontextprotocol.org/schemas/latest/core/performance-feedback.json": "69eb64438779c5732b6da6d9bcaeb2576bc1b7681722e6db8cd148e2caa255b9", - "https://adcontextprotocol.org/schemas/latest/core/placement.json": "15bf0a30a29406964e9e00f5f20431bf1a8ff157f071315892ea170ec283f08c", - "https://adcontextprotocol.org/schemas/latest/core/pricing-option.json": "f4f99dac2a28722dd3ce0ded62e8b93a295ba5fff43de6c3d1419e0cfccf4e12", - "https://adcontextprotocol.org/schemas/latest/core/product-filters.json": "1fef7a57e485d064b1b9c171980c861ddaddd901587b1c83731dbbdaa70e60ee", - "https://adcontextprotocol.org/schemas/latest/core/product.json": "d08b988eb16a84f9a9710cdec64c72427512e4c396590189db89ffdcdcf78a59", - "https://adcontextprotocol.org/schemas/latest/core/promoted-offerings.json": "0e5bc0d269ba9909863560890fd97d64545716a0b15ef2afbf49828c4f4b6b11", - "https://adcontextprotocol.org/schemas/latest/core/promoted-products.json": "cf9497d2751b9bcd34abf34199f9965828fd3f2e457076e69e5c8b729b53f1b2", - "https://adcontextprotocol.org/schemas/latest/core/property-id.json": "16ff353402c03691a7290a0f7578a901b63a0f7e83567b8903c5c6f89e1fb6f0", - "https://adcontextprotocol.org/schemas/latest/core/property-tag.json": "6f2c35324ca6c5533a2c3d1a5837360c813a0905be68b11da7a46965ec37d59c", - "https://adcontextprotocol.org/schemas/latest/core/property.json": "785bd5615917aa73e4e10f4925f35c0fc739b5c60f4351b53a005d131bb74657", - "https://adcontextprotocol.org/schemas/latest/core/protocol-envelope.json": "5e59b7890e40beffb4ab56b723eaefd57a6917ee561ab71e41e26491c45d50de", - "https://adcontextprotocol.org/schemas/latest/core/publisher-property-selector.json": "53f58431de12001c89af98dde18769cb1b021a6b88d3503111d8a2ac5e418eda", - "https://adcontextprotocol.org/schemas/latest/core/push-notification-config.json": "64ed4db710d5a5346d6935e238d28ffaa4374dcff9d08e5d4283d4786dfe6de5", - "https://adcontextprotocol.org/schemas/latest/core/reporting-capabilities.json": "5b49fa96cce7bda72e758ac1ffb2ad39166798bf3133d89fda3e143584140c64", - "https://adcontextprotocol.org/schemas/latest/core/response.json": "cd52aeaf429ed7ccd5e45f88cef9520d734874cbd7ea53831dac99691de2835b", - "https://adcontextprotocol.org/schemas/latest/core/signal-filters.json": "dc368066ffd83612767e6cd60698eb41b91704e9771abeb91a83b655f86ae757", - "https://adcontextprotocol.org/schemas/latest/core/start-timing.json": "8e07e0469f434f3d3ba998e2b1fe58fc3dd097915e2d5e0c547cadfd5a469158", - "https://adcontextprotocol.org/schemas/latest/core/sub-asset.json": "ae9a93b482eb023971c6b85296fe7cd64cbd47422e43e0ae7758eaa734b10d83", - "https://adcontextprotocol.org/schemas/latest/core/targeting.json": "a576185d458a258f0652d3d1c9056d7da7e5acd46e7b615b392c1ddd52fcf02a", - "https://adcontextprotocol.org/schemas/latest/creative/asset-types/index.json": "e191c0e50f800351f07e754bb70042c7f960bf75f9bb36ff8f73ff5b9b104cfd", - "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-request.json": "4b0ccb85bb35fafabdf5ff38d29ebb9fe8c2d49c81e32488371da2e9a0444d5d", - "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-response.json": "2c24b242e05fa2629599c2dffc6f2bd54d86d6917481066f9874652d8c00a788", - "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-request.json": "aea9784b4f44c9648dd35748cf23a6b516a0fe16013e348c45122526a94fdbb9", - "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-response.json": "f8d6b69641994c44bca3f89761b20eb95d74ed1be4f9474e108f035a6af6b3d5", - "https://adcontextprotocol.org/schemas/latest/creative/preview-render.json": "609f89f622792258069e7d6e6b0fc5bc4de7d5bf6e90630389d8fc02412f6be4", - "https://adcontextprotocol.org/schemas/latest/enums/adcp-domain.json": "f6c850ee4652848a0a4825c5911c4c53e4793324a4596973540b2eacb501c69d", - "https://adcontextprotocol.org/schemas/latest/enums/asset-content-type.json": "74414bc886efb8a52794da63cfbb873befd9d24c87d9293ac88008bd496dfafc", - "https://adcontextprotocol.org/schemas/latest/enums/auth-scheme.json": "492732201479760e022e7e20461874312403dab836af0f45c1382fd7b59c8b17", - "https://adcontextprotocol.org/schemas/latest/enums/available-metric.json": "30577d384f8ffa1f6b9285c59878dbe0d55b090ea9e9ae765efa9fe4aabd3825", - "https://adcontextprotocol.org/schemas/latest/enums/channels.json": "18344bb746790dd1a2d6874c604fa3735e4b6ea8cd903d71fad25f6de71ced3e", - "https://adcontextprotocol.org/schemas/latest/enums/co-branding-requirement.json": "7d533d01abfc5b134985e4a4611547a8d88601f2ad3dae166d30483433a5af8e", - "https://adcontextprotocol.org/schemas/latest/enums/creative-action.json": "c8f56831b63d868ecdadb81787fbd9bda85f791387cc04d10a4f3f4774edf591", - "https://adcontextprotocol.org/schemas/latest/enums/creative-agent-capability.json": "1393bde9696600816f802091fe73cd8553c305e039b8f0e39493b5112e4f9d27", - "https://adcontextprotocol.org/schemas/latest/enums/creative-sort-field.json": "adc83644f01b9948aa436c79dc0701d878a876e185adf7808485772fbad5eb28", - "https://adcontextprotocol.org/schemas/latest/enums/creative-status.json": "ac51ce7d2803901f5c2c9115becf16965c4c205a186c7d5bbc3079ac83ccca85", - "https://adcontextprotocol.org/schemas/latest/enums/daast-tracking-event.json": "caec0a9b0852c26a43a41c52312a36007656f7104c5af276d1111dddca9e2041", - "https://adcontextprotocol.org/schemas/latest/enums/daast-version.json": "95b06e213a2279ad3db0cca8912324a7773bc90a28bd0a39c676f73dcc4c70e2", - "https://adcontextprotocol.org/schemas/latest/enums/delivery-type.json": "3934bfba9af3ef9469f73b85b15c61c058b79771e74ae7bc387afc95905feacc", - "https://adcontextprotocol.org/schemas/latest/enums/dimension-unit.json": "405de49a9144c527466677ef3d3e5010b3cecea289f74b837958496da78045fb", - "https://adcontextprotocol.org/schemas/latest/enums/feed-format.json": "2147a55d3ab95d8108f6258d31c2ea3e37f32eef065af05236135600f4eb9c99", - "https://adcontextprotocol.org/schemas/latest/enums/feedback-source.json": "56283eec28ab10c8a11f09959c0f3dbef2b5bf02b7df84599343cb9fb0e69f78", - "https://adcontextprotocol.org/schemas/latest/enums/format-category.json": "12e5642d281d4657de9039e7a41af4ba72cc8cd3b0b72fc395f42d760a62789d", - "https://adcontextprotocol.org/schemas/latest/enums/format-id-parameter.json": "0783749a5ac1e2eff4cc523eec16e3a723e107b3718bd55e1bc671cf230b0a1f", - "https://adcontextprotocol.org/schemas/latest/enums/frequency-cap-scope.json": "3275a767cbde71235e7a23d0d775b5d58afb1859936393b04eb2c7c976ef2493", - "https://adcontextprotocol.org/schemas/latest/enums/history-entry-type.json": "e77c87be1493e84d83ffb567113303e2b50baa1dbd8c1ea791e2e8822f2bbf64", - "https://adcontextprotocol.org/schemas/latest/enums/http-method.json": "75c12b6e8868b0248841bbf8e666fd097308276f59a2c8f809fa279a88c06188", - "https://adcontextprotocol.org/schemas/latest/enums/identifier-types.json": "73190ea41c388af5b6b9c56358c4bce893b0f7cf61bc5062647f9987755451ed", - "https://adcontextprotocol.org/schemas/latest/enums/javascript-module-type.json": "da4746acdce608ce9497f59e7fdbc97a649367e55aebe4b9675feb3176e8525e", - "https://adcontextprotocol.org/schemas/latest/enums/landing-page-requirement.json": "5a09b76855c541b23ccf1aaa8ea87e77203d358b5c01c1b255722f21ac6327a4", - "https://adcontextprotocol.org/schemas/latest/enums/markdown-flavor.json": "df8836754968fb1c02fc7725aa1bce56e315c4cec11515a19058b5d6a0cf782b", - "https://adcontextprotocol.org/schemas/latest/enums/media-buy-status.json": "70bd2fca8832137c3b504c4b80934fdf8a57bcb45c4e1bf821fc49096aae53f9", - "https://adcontextprotocol.org/schemas/latest/enums/metric-type.json": "41eafcfaf6206670aabecd65abd5c1f2d0c4af019a3e4055d26aecfdccfd0a75", - "https://adcontextprotocol.org/schemas/latest/enums/notification-type.json": "be6d4177c9350e8fdced52773b483acf464beecd567934cf020e53c43e61afac", - "https://adcontextprotocol.org/schemas/latest/enums/pacing.json": "6fb8e62bfdc40bb48e0620ed71310f21a821fdfbe644c625d01b6a68ba4e40bb", - "https://adcontextprotocol.org/schemas/latest/enums/preview-output-format.json": "b14841f4e6689b3a3d2afa5740b4787ba49961d39ede2f9b92b709ad7970b32e", - "https://adcontextprotocol.org/schemas/latest/enums/pricing-model.json": "eb2aee267593d91e7f02ee0143fd8c2226021560fbee6b7ad983188f216f5f5a", - "https://adcontextprotocol.org/schemas/latest/enums/property-type.json": "aa431658c44beda5ead5e52977eeb4a2a0640a5e0be51027a769b39957910d53", - "https://adcontextprotocol.org/schemas/latest/enums/publisher-identifier-types.json": "3d4f8baf9ea57f525d1f126d58190588c17b05c7493ea2c9ff5737922cc96c4d", - "https://adcontextprotocol.org/schemas/latest/enums/reporting-frequency.json": "b480016e39a0b8a4493e55f5bda13b153e8df7c4c07ee49586cd77bdfdab0af5", - "https://adcontextprotocol.org/schemas/latest/enums/signal-catalog-type.json": "f899ae2550950b3e2269f42c20c50bfd09c1f2870fc656e334b73758bfbf2245", - "https://adcontextprotocol.org/schemas/latest/enums/sort-direction.json": "85a2cf23403297069995f14498a495c566a5a8bce4409d468d9071e18338ce6e", - "https://adcontextprotocol.org/schemas/latest/enums/standard-format-ids.json": "898565127bec42be24b65bff5ad0c650cd337601bc6b546bc7ee55d39e6f01e1", - "https://adcontextprotocol.org/schemas/latest/enums/task-status.json": "b45adb6b28b0b35ea5cf5564ec22d7b692e66c40d10d891d6dfe6661035c82b0", - "https://adcontextprotocol.org/schemas/latest/enums/task-type.json": "54a0ba43415b7948f3e0b1a61e06388b6eb239ce3a6073a9032c363d158c7905", - "https://adcontextprotocol.org/schemas/latest/enums/update-frequency.json": "657d0460d5675ddcd7edb4cf92655b56a93cd724ab3c0b4094241ef91ca644c8", - "https://adcontextprotocol.org/schemas/latest/enums/url-asset-type.json": "8cb3c557a43a0d5f85cd9c7b83366910c570349c6ab8625583ca66454fc88c03", - "https://adcontextprotocol.org/schemas/latest/enums/validation-mode.json": "0df6bb0c18921714d48d26c2813d6fa312c5a671e1a421f9c9f9ca0c0cfa6811", - "https://adcontextprotocol.org/schemas/latest/enums/vast-tracking-event.json": "c13b3a90cfa3f13f9446185a366095576b1b92574fc468c7de432c8c141167a8", - "https://adcontextprotocol.org/schemas/latest/enums/vast-version.json": "cf0f0e11eba22c9679b96f13608540016dfa3423101b8e22238ebb56abd224dd", - "https://adcontextprotocol.org/schemas/latest/enums/webhook-response-type.json": "72ba18db0a6fabd814195e895841e4cd6af5b54c4d6a954552c36284da5c4075", - "https://adcontextprotocol.org/schemas/latest/enums/webhook-security-method.json": "80c1a7622b750af3bcfd2695569a3b348e42d5c8614378c27a65f8c7374e9165", - "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-request.json": "12a7352bd4b0eb2ca856f9dd84dd611583a6f2bc5344890eb03c3496809dd439", - "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-response.json": "d07d4ef0e583b4bc20399bcaf204f28c16c0b30c701c13b9251c983312ecc858", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-input-required.json": "d0d53decd0e006bb66088898714692754eead832012f34e1e2d50b7b26d90d32", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-submitted.json": "8d9178048ee7f5adc46f9d27b9adb536dcd225f8ce17eea9e1f80edf3b815519", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-working.json": "e0f44bd7d3a9c3ef54ef672edf3a5806472498d2d89013ebe3ff731c25feba99", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-request.json": "af613bab7f81731e4bc3aefb7323fde499d1630453f79dc5a875e71ce11ed61a", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-response.json": "61565bb1c2edf344338a1e56d8a998c086f852a1973290674e9fee9ac3b967ff", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-request.json": "ef9de9c9f24de440c139a1205559ad1646aa38ea2665734502a979b09eab1af3", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-response.json": "f0ba34dd2b4086bcd7545bca0dcac05a465daccd0df6c8938b3a20331573167f", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-input-required.json": "fa6f558932da62a48d53103044c23806cf6d3a8402aced8017791992a46f7e25", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-submitted.json": "d96c9c3fd171ea9cb3bd3efdee11326862d90c114d73f373e68367d04a2c2f9a", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-working.json": "bf028b7f3313f43c6f9d0ad4abfecf1dd7d8ddc581e797a1ee5ca8db84383f53", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-request.json": "f2f28d9cdcce3d71919af01f998cdbf1680595e4afc7007d362647fdefc01004", - "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-response.json": "6c236524c11b7b24b75c61b4a28507c2f863f6211dd6a8c68b141b0e145ec9fb", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-authorized-properties-request.json": "be7ab0ee04f87158254e9eefb1ad26f35b97b09d590e29633269a24d62a28524", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-authorized-properties-response.json": "628539fde80b56d671947d6ccf1a75c6bc8776be77948776bbf85fbedadfa6c9", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-creative-formats-request.json": "69662d9fc33882ed6ee29d3639aa83c8c74cebcf5e445a21dd9ffb30ab479681", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-creative-formats-response.json": "c296a680eaac7d9b74cb91bc3e7af0e26eb73cc2cc2228aed7d5ff3fb7d2c300", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-request.json": "7ec7b0639acbf9488c4efddd36680674c0b05b7bf63e8b95ccd0e5476f849bbb", - "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-response.json": "e50d9af1d6ddbfad7caeb022bdaa087db73e327155d9b5aa65e63ff8c6a1d67a", - "https://adcontextprotocol.org/schemas/latest/media-buy/package-request.json": "da9a6574d35c873cd3305e2b9d58d89f7aa0cc8f9eff0791dd13aa82e975c38d", - "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-request.json": "b418295130bbe51d7c75e06e4279d2391b645fb5a6edb75edb3a9c15196c5db9", - "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-response.json": "011bd01bef32f55a17d645636f0a29316fb55ab185714660456e5a61a926d575", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-input-required.json": "cee56e6ea91d5718cd300ab69c56002c782bd6b1bb1cbacdcfa112c43c6097f7", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-submitted.json": "3a4ce2ea5bdbfa0e81136b03977c19a5b5d2efda9b29bd68a6ca7b6dc944a9ae", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-working.json": "ee9c1215472361664f4b44149c524672c191bfd45474f437d63ef145891a053b", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-request.json": "ff8c89191ea0fa2d1469adbd97647cb098f68b646a7090e96815004082d73d1e", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-response.json": "9227bda293c14a4734290727a2a5cd13af690c8b9a0f107ffc3b664390b10b58", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-input-required.json": "3856eabfb464b5c9141fc80504810d10438b2883ed184908b6be6b0f3da2be50", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-submitted.json": "b843ded24cb2fb16c89050a534e075f52ba6ae2e11f726597b681fbdb2469bef", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-working.json": "dcf9cc0bbd5d23360b19a2da6da7b9650d7e2892a2e835339e421cbb8c12a328", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-request.json": "6810c163394eeb17f39be725aea20d5b1fdc1a363f2233055f92fd775ba96ae2", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-response.json": "2584822ce5f97f5ee2d19d61785906565d67d35631bebb13f7417fb7e3db8c03", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpc-option.json": "be10d3c12cd0d426496edf51b0769845f92000aa408db5bf049e89ce256dd19a", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpcv-option.json": "b0778b4dd666776d74565b29036bc4526395242ad4a08fbcab61794af2c68d9f", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-auction-option.json": "9c5db0364f491ca2ea90f9e6ecbfcef4765751c68084e94d043d63a52bd0be84", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-fixed-option.json": "2cc4697cc15db1f397d3b60c7115841592d730601e90ce5e2790e6e6866e270b", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpp-option.json": "a53067bf702a5c91423206ab6dee778696ce83efdcec7fd0b8bfe0e3b5f1263f", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpv-option.json": "dc391dba257bade8a3ed3271b51156e6b90830affa23aad94887c2fb35475b15", - "https://adcontextprotocol.org/schemas/latest/pricing-options/flat-rate-option.json": "ad3d86d9c8487a536738d0569498a1cfaa266b5f7ba2961a31c5da7819ae892e", - "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-auction-option.json": "7908d73566f4fe54e0ad939cb2384b6ee07572183a9c9707a99f69f923e80a3b", - "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-fixed-option.json": "7669e82e83d98650c154d5624378cfe600dd77eac5a1811014275bf168732666", - "https://adcontextprotocol.org/schemas/latest/protocols/adcp-extension.json": "67b25add68afab242ffa1e8477d030e3c805cc7e0bbf7162bb8f871d3e0b854d", - "https://adcontextprotocol.org/schemas/latest/signals/activate-signal-request.json": "5cd48cc897a5cae9cc7616d88596f578fc73cd184538206ce765c9daff2894e8", - "https://adcontextprotocol.org/schemas/latest/signals/activate-signal-response.json": "a4abaedbc47651c2bdbbde8bc2bedb3dcde2eaf1ca2dc9a369fa04a0a02dd56b", - "https://adcontextprotocol.org/schemas/latest/signals/get-signals-request.json": "8fa9b0270ae644a664ccf494696b6f1d4ca6afccbb11ffa2ceb89b42a2073016", - "https://adcontextprotocol.org/schemas/latest/signals/get-signals-response.json": "e8398ddb7b03e2b4e323c9e5e0f98c18173bc9ca56c3f4874e0bfe29122a4b3a" + "https://adcontextprotocol.org/schemas/2.6.0/index.json": "730a1d6e729660a6c107842356f1fca6721d69027df7fb00d018a12a59515426", + "https://adcontextprotocol.org/schemas/2.6.0/adagents.json": "040822ddc5e53c07ddc6a144a6c4ca935048170d388981645c2a842bff5cba01", + "https://adcontextprotocol.org/schemas/2.6.0/core/activation-key.json": "bd518951d02618c71fbb7b986612e8eb407ff1e42e56e6425ff72fe62de6e398", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/audio-asset.json": "8f58b0eaab323f37148586ca6c6053c3837beb1f4e11bd90643d65493906fd9b", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/css-asset.json": "58b4d0e37c5c50de3aa0634e68782cb980243972effdbbbb031c9fed7909fcd6", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/daast-asset.json": "18f64de4f4364f2b088553022dde888e1bc6ae901c2aba7a1b92a5077a9953e5", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/html-asset.json": "b37af64a11db31323ae31507eb777db79faf3d1c3b66cefb8dbf464f6b95baf3", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/image-asset.json": "9c47dc5885925dada5edfe8fffa14b70f95d97f642d0273b6905cb3e080db96e", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/javascript-asset.json": "3ad5e2a3c9819e6e555a2963aa5bf3e027fc72510638e6d2d541142b6682fd75", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/text-asset.json": "c8fd0ccf60e36f96051ed39d29df5ad740af8bce2cf78b15586d2f1e9802d628", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/url-asset.json": "2ea5873ce10b2fa3c9974b336567ddf3f1d268845964dcbd1cb0491360ec41f8", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/vast-asset.json": "6afb68b10d96efea99e5df28636f26c12189660c73e3afd03b4b2434d87192b5", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/video-asset.json": "335d3757fd7e754915b36cb663ea512c253cd91f2300a31cc0f165147c5c482b", + "https://adcontextprotocol.org/schemas/2.6.0/core/assets/webhook-asset.json": "c2b54eaad6c73c993056f98640b1fefa10600e25d33db47b4c6950ea855f7bec", + "https://adcontextprotocol.org/schemas/2.6.0/core/async-response-data.json": "0504ab3c32e4c595fc8c08f6959ab7888d0418e0a3c529c6db54bfc3ec725958", + "https://adcontextprotocol.org/schemas/2.6.0/core/brand-manifest-ref.json": "b42d89abb6bbc3d94f778e4ca50db2afbc44abdc323ff6d023b0991bcf5c636d", + "https://adcontextprotocol.org/schemas/2.6.0/core/brand-manifest.json": "84d9894ee5ffa030faae0f1ef8ded063672646b9d2d93a3f95274e9b4d0d7e8f", + "https://adcontextprotocol.org/schemas/2.6.0/core/context.json": "c667cb6656a09b519e0149894c71892dc0b41058286330a7abec1c6be06d1dd5", + "https://adcontextprotocol.org/schemas/2.6.0/core/creative-asset.json": "54796fa16fdab4e27292a3046927f3fa4e3c0a31100d0193e5a9037ba325d7b8", + "https://adcontextprotocol.org/schemas/2.6.0/core/creative-assignment.json": "c974290891741554ed6cf52e90f8cd849ca42dc93945f93a0e1131db184f1dd3", + "https://adcontextprotocol.org/schemas/2.6.0/core/creative-filters.json": "2561da12331c8fe8fbc5b51a0548c63bea0dcbf8e6a4ef33e750177588f7bfd0", + "https://adcontextprotocol.org/schemas/2.6.0/core/creative-manifest.json": "5b1741e6c1f28afdc7809ab4e0b46e7e0f60c8c6fb60f4180c0137f62f424da5", + "https://adcontextprotocol.org/schemas/2.6.0/core/creative-policy.json": "3d21944d2d8cb3d8547ab1ab4e8039126ed59c927769390b6e88a37741a95c3c", + "https://adcontextprotocol.org/schemas/2.6.0/core/delivery-metrics.json": "d1f66f1e536857c3636ac1bc0f5d3cf4566a3d291489e2e957e857379dff5f20", + "https://adcontextprotocol.org/schemas/2.6.0/core/deployment.json": "abd117816662f22d2ca04e9d59e3ecf3a4d89e67cf00c42eb208d3e00b85da99", + "https://adcontextprotocol.org/schemas/2.6.0/core/destination.json": "9561298e4b57b864e3db61466d7779dfd504c5f0e4c7a57184b4dc4de802e08b", + "https://adcontextprotocol.org/schemas/2.6.0/core/error.json": "9ce9217be88ac6f84b26b93438ea5e79c5e57b3cf9ad3f7008977d751aa12111", + "https://adcontextprotocol.org/schemas/2.6.0/core/ext.json": "5f7140fa267fd56e02547bf89e13cbb7c9ba54d2cd763de4f29f09e50896f952", + "https://adcontextprotocol.org/schemas/2.6.0/core/format-id.json": "d9a14c1a435444d54c9f9367ae9c8c4e6587cb05f1548e98df3a003bc3aaf8bc", + "https://adcontextprotocol.org/schemas/2.6.0/core/format.json": "9031bcb6669c5bb78692f50fa16641ccd99fd314e566275ef012468b2daca587", + "https://adcontextprotocol.org/schemas/2.6.0/core/frequency-cap.json": "6a089fbfdbcdeb15f0f51341ddee9eb75e451ac03324b75bf3d6eb769f5964a1", + "https://adcontextprotocol.org/schemas/2.6.0/core/mcp-webhook-payload.json": "b70c73f858af7128459f5cec9ae6eca8cca7201c0b0c5390622de9626abf243e", + "https://adcontextprotocol.org/schemas/2.6.0/core/measurement.json": "e69b4089087d788015d031db446ac96f338e1c1d404d26efc5e3d2333252552c", + "https://adcontextprotocol.org/schemas/2.6.0/core/media-buy.json": "d63e59bb894cfc0229118b1c20165b10755016ac24042d3d3d0ef268947ce482", + "https://adcontextprotocol.org/schemas/2.6.0/core/package.json": "3e95d5fc435f2a4ed9a68a9e4c8f2c02449669b0a770d41ffea91a6f91e4adb5", + "https://adcontextprotocol.org/schemas/2.6.0/core/performance-feedback.json": "499617d218e4ef538db7fabdc274f27bee659acc8f40c942d1decd093f78c6c9", + "https://adcontextprotocol.org/schemas/2.6.0/core/placement.json": "223fc39b7f5c4c39c79b871322130deb71e66675329d099769302b699a84dde4", + "https://adcontextprotocol.org/schemas/2.6.0/core/pricing-option.json": "971e4143584c5dc230d01931965f0560c4622c30af0ac596b13c00c7b3a947f8", + "https://adcontextprotocol.org/schemas/2.6.0/core/product-filters.json": "e7ed65699713c48a9a08edc3a183582365217cd7bcac3019795e81d432dcf22b", + "https://adcontextprotocol.org/schemas/2.6.0/core/product.json": "3366b26bdd6af8f6029a736c90097b0326d6cd92b3dc4b34fc0645a1364c6231", + "https://adcontextprotocol.org/schemas/2.6.0/core/promoted-offerings.json": "89904b5f4ac756cbb1344024a9962ef0e7dbfa32c6fac59379cd2e5876ae96a1", + "https://adcontextprotocol.org/schemas/2.6.0/core/promoted-products.json": "2e709fc90b776ece5907503ae83ca79af14dc0cc240a41782ddd9421aa13426f", + "https://adcontextprotocol.org/schemas/2.6.0/core/property-id.json": "875cc214bd58ddd8d480a7a5c76776f07e7e834daed4dc2a099fbceb973bdb97", + "https://adcontextprotocol.org/schemas/2.6.0/core/property-tag.json": "1a8a753226b02dbd359fb33abefb97dbdc13fd88b8eecf7321d5dd6d2942e6fe", + "https://adcontextprotocol.org/schemas/2.6.0/core/property.json": "a7d1be9f0813386f0061174810170bcc64731c06e9e8e436fd888f880c8edd3f", + "https://adcontextprotocol.org/schemas/2.6.0/core/protocol-envelope.json": "9a70425bdb28bbd69cf103f0826be514ba418f8186e244c22f6e0b5c2f966383", + "https://adcontextprotocol.org/schemas/2.6.0/core/publisher-property-selector.json": "a68ee6ebd20dc2f2195bce885d33785f91d325de48aee3316ead326b6cfc1289", + "https://adcontextprotocol.org/schemas/2.6.0/core/push-notification-config.json": "f43cac5b538808162bf51a49853a288f3d877dc29aba8cba71579a2d681d1d89", + "https://adcontextprotocol.org/schemas/2.6.0/core/reporting-capabilities.json": "e54e47a846197790b4d79e1d9ef978b13f4743f370d7562425e3b192b510b47f", + "https://adcontextprotocol.org/schemas/2.6.0/core/response.json": "91ea9185f3b317a5b1db21335e3662b98fd4266336ec2eba3dcdff7928881c48", + "https://adcontextprotocol.org/schemas/2.6.0/core/signal-filters.json": "2955477372ae338762a0f0af9f8af0f5e4deb183cdb4c486292d879e36f243bd", + "https://adcontextprotocol.org/schemas/2.6.0/core/start-timing.json": "64ff8e6fae2b1cf490c2d274f13f66813b0c1b8e6ce051bd4c6adbfdf45c5488", + "https://adcontextprotocol.org/schemas/2.6.0/core/sub-asset.json": "62cd6b334bb246504c927d7ef3e60b5d5624ae8d810fedb6301be87f710d3573", + "https://adcontextprotocol.org/schemas/2.6.0/core/targeting.json": "af891f2c882f3975e4a4c2fd3d2e04796fa7a401f19dbc6e39f6a00308a6dd01", + "https://adcontextprotocol.org/schemas/2.6.0/creative/asset-types/index.json": "6cf91c2c2ffbccc2bb78a94c38a3cdb44624c4dda1b5e018efeddc3011dc3c83", + "https://adcontextprotocol.org/schemas/2.6.0/creative/list-creative-formats-request.json": "f45d84c60e795a69cd51bccea0c8f4a8aa265ae219d7207f411bf1a0342ace7f", + "https://adcontextprotocol.org/schemas/2.6.0/creative/list-creative-formats-response.json": "a10637f93ab28ac03b78b8e5b5b8e129554ad907331695a766670b1d854d5fc2", + "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-creative-request.json": "4d1cda6561ce2ff645724076f10b70ff7b1e3b17655e660b12efdbffa6852584", + "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-creative-response.json": "1e7175be27ad98eb685e53ab6595796bad0950ea5425c4b8da45bfe20a9986b8", + "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-render.json": "b40d4e01eeb98942db2b9bf4802b78f6596295f8c7dbf0c3bac90b3e8bd4ec23", + "https://adcontextprotocol.org/schemas/2.6.0/enums/adcp-domain.json": "fb86b783d932ed188339b81c6e56782e930394b990508200d34d6b587e922903", + "https://adcontextprotocol.org/schemas/2.6.0/enums/asset-content-type.json": "a62ab210987be79ca430e0b40ddf91ae65db2bf83465470515d5c263f1dac2bb", + "https://adcontextprotocol.org/schemas/2.6.0/enums/auth-scheme.json": "1a8e9be46cce2432d7f58be1888d140f9783f73bb97a20c10dfcf9070161d2f4", + "https://adcontextprotocol.org/schemas/2.6.0/enums/available-metric.json": "b9beb1e79930ddd6d0f32ce41feee89ca10615fc61291d1f2227142fbfd47ddf", + "https://adcontextprotocol.org/schemas/2.6.0/enums/channels.json": "a77c405af340905ff47aaafdb766f38c0f041ed2e2e01970954edbe7282a0fa3", + "https://adcontextprotocol.org/schemas/2.6.0/enums/co-branding-requirement.json": "9340337b34e18abc0c2a73eed9ca1932deab734c055730e332c491daf8957f11", + "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-action.json": "fc5c1ebbffd46c7a408aaa59e89c63c81bb61b5ecbbc032a60d93246403d4346", + "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-agent-capability.json": "9b40c5c8d696a0b53ea22fade765e1d1aaf8ce161d575cf84b5bdf1b1448cb6d", + "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-sort-field.json": "95cbb824bc189f9d5b4e6082d7f6ca003a43ca2da643725e60a173ea4f4c6081", + "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-status.json": "b14c4aa8cfa3ea2fc9fb62763ae5dc482db9fb167eb33808438b0bfe8345cd3d", + "https://adcontextprotocol.org/schemas/2.6.0/enums/daast-tracking-event.json": "de04a339007b22b71b0d775df05aeaab052dc7fffbcab1655d8598e293035d70", + "https://adcontextprotocol.org/schemas/2.6.0/enums/daast-version.json": "32f5fcf31e87627d7f3f96e50232ff62557263534a3a476e298cf4c7c3695f73", + "https://adcontextprotocol.org/schemas/2.6.0/enums/delivery-type.json": "f7e6f2f9d63dba975614d37be5dc45cb6829ed77ad9732b7b95dc845e735cb66", + "https://adcontextprotocol.org/schemas/2.6.0/enums/dimension-unit.json": "db0027875a27109507d4a7ed9dc6e050c9a2a6d96433fa98ccce8ff1f37b1d20", + "https://adcontextprotocol.org/schemas/2.6.0/enums/feed-format.json": "67298ba035f9b095c6b4ae94fd318238a4d4f6edab175947f96f989b0db65ffd", + "https://adcontextprotocol.org/schemas/2.6.0/enums/feedback-source.json": "1f1059f2f2a64a6bcfedc8fc653f2def8b1b6cd544923ddd2ca697dc7f89526c", + "https://adcontextprotocol.org/schemas/2.6.0/enums/format-category.json": "587516d32b0455e0b44c86dbb01a3724033393899947b024302193ba0e4974ad", + "https://adcontextprotocol.org/schemas/2.6.0/enums/format-id-parameter.json": "ded3a4d0231e30709548086156867a3f27752d793fd1f504c62e15e193a9ba96", + "https://adcontextprotocol.org/schemas/2.6.0/enums/frequency-cap-scope.json": "4518e7b779353f0403a6e8ab7b8da5d1c775c745a8399d1e118fb0ac15893b9f", + "https://adcontextprotocol.org/schemas/2.6.0/enums/history-entry-type.json": "b46fee7bcd5f978347a5458b0209c176aa81a8be5bd06a23c4e6ac8574fc2c59", + "https://adcontextprotocol.org/schemas/2.6.0/enums/http-method.json": "b2f7e41876231efdc447ea58fa57a8e45933f6334aa2fcc17984f8007c6ba04f", + "https://adcontextprotocol.org/schemas/2.6.0/enums/identifier-types.json": "ce71e52ed324f17d51c57e8cae4976777a4a24f2701329e7808857676ca0e360", + "https://adcontextprotocol.org/schemas/2.6.0/enums/javascript-module-type.json": "227746528d3c02aeb31435b2dc7acc0502506313802ecec3a5022f4cd3cbf226", + "https://adcontextprotocol.org/schemas/2.6.0/enums/landing-page-requirement.json": "1cd39e922ce52a8710e0ba2db1430736c37ced565eca69e7a949f25b1a98f47a", + "https://adcontextprotocol.org/schemas/2.6.0/enums/markdown-flavor.json": "872bc5111d2397fc18c897b7f81c339be6604dbb3f88137ff278489d8ca89d60", + "https://adcontextprotocol.org/schemas/2.6.0/enums/media-buy-status.json": "7add3ed9ada1f4e867f1fab201d9be2f9a99eac110777f5a1932e16082f8358b", + "https://adcontextprotocol.org/schemas/2.6.0/enums/metric-type.json": "cab969ccc0fc057922cd89152977bbc9880370cf8a07aa4c7f7bee7a24ecb381", + "https://adcontextprotocol.org/schemas/2.6.0/enums/notification-type.json": "6dd5e835219c69ae289bb0261370a36b54e0b616cf9a7e2dfa88bd85e4761bd1", + "https://adcontextprotocol.org/schemas/2.6.0/enums/pacing.json": "730b6ff468ac9ec536b41fc93c6abc60d87acbbdc8cb67db9b8bc866acf89507", + "https://adcontextprotocol.org/schemas/2.6.0/enums/preview-output-format.json": "dcf5cad1d6b0878f92c981719786816ee9ce9c94d0ff28946920b9db3c168d94", + "https://adcontextprotocol.org/schemas/2.6.0/enums/pricing-model.json": "4db3c61a96392a200aef52fc6b0c87095c18855e150695b66a45d92e33c2de73", + "https://adcontextprotocol.org/schemas/2.6.0/enums/property-type.json": "4fafa162288a4ebf2dfcfe15d6d51c7c2886fa61873d0723525ea9d9aafa4911", + "https://adcontextprotocol.org/schemas/2.6.0/enums/publisher-identifier-types.json": "31d5d719846f3c697bef9581e849627099e13b6fe71663debcea04012b784b00", + "https://adcontextprotocol.org/schemas/2.6.0/enums/reporting-frequency.json": "7b8ec2d2f6e6bb68fccc782b1d05de274cf90c5f1873fc5982d39b3427817626", + "https://adcontextprotocol.org/schemas/2.6.0/enums/signal-catalog-type.json": "40692e383cb134b5e5d0159255ebc4ec426a65beeea55ebec1ab462525e6b314", + "https://adcontextprotocol.org/schemas/2.6.0/enums/sort-direction.json": "f1d72dfbdcff421cb81349b1c5209b5f6747b0d3a124f93ead7a325ba758309b", + "https://adcontextprotocol.org/schemas/2.6.0/enums/standard-format-ids.json": "9fd7f60107a25be0a66bd57f8bb3aa82122f554ab185686a7eccbc753749c40d", + "https://adcontextprotocol.org/schemas/2.6.0/enums/task-status.json": "7baa27e10078fec73b64b223170c39f3db89d818a82ad41ca9f02b6fd5c4b77b", + "https://adcontextprotocol.org/schemas/2.6.0/enums/task-type.json": "62ada0b15aaa8841a307f56e67f56a4d60a76eec6b698b9e58ba1e323862bf55", + "https://adcontextprotocol.org/schemas/2.6.0/enums/update-frequency.json": "ada6745eb5c7edaebec2693478da6fd93fb807c48413332132b1d7df97e31688", + "https://adcontextprotocol.org/schemas/2.6.0/enums/url-asset-type.json": "39e064861db8b50e41bef2dfa373f8309a2a14b27e65a93a6c3bb369d6f795f4", + "https://adcontextprotocol.org/schemas/2.6.0/enums/validation-mode.json": "437dc25f290358d95ff5352fc26bdda5a992dfe8f04a191e16b2106e3d21071e", + "https://adcontextprotocol.org/schemas/2.6.0/enums/vast-tracking-event.json": "f275ebe947d5609175550935989891819cc19e6c3b64a631a8b0927a9144b715", + "https://adcontextprotocol.org/schemas/2.6.0/enums/vast-version.json": "5734bcc344af47e3ad4dcf68f155538614babaec7788326f5d82cec3129559ec", + "https://adcontextprotocol.org/schemas/2.6.0/enums/webhook-response-type.json": "d81db53c78b4ae5ff32287746903ab9bbaf848859ef222dd9ed8d7c0ed17ed60", + "https://adcontextprotocol.org/schemas/2.6.0/enums/webhook-security-method.json": "f74d763f720823948e5ade72a3a139e95675247e25a2671cfea6643d9a8f4872", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/build-creative-request.json": "2633ac57f3a70c5ff82c2c240ca8066191d1778164c1415c4411593c9a7d4086", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/build-creative-response.json": "1b57abef495014331fe2e50a337048034c3b95d4a4e57c862664e40ce8a198d0", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-input-required.json": "74c43004e366b5af309ebf2fcf2d757b181efe7124a09e36b09ea85a92fb3a86", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-submitted.json": "c61193abebcf766bf587ae01c46303a7387c8fcdf79c1b5efd246535662d96a3", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-working.json": "c61630024e3803e09840f059ff95c257b247e0fda5c1a33dca5bea5fd1bfc890", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-request.json": "01740da777f9468703c2856f8f76d3ed4beca21b2782a6e4109c73fe51d4bb4d", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-response.json": "f9778d117dcd2db8705b01c511ee612231006102e5c1d9379b229bddd9fd439c", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-media-buy-delivery-request.json": "0da39fd5d7220b501694ff8e8950e254479e336bbe6ad4c0fc6e78a82941f63d", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-media-buy-delivery-response.json": "7a135f8998c29800959a39b7b8e929a80e907654d08a34e22becd9d7dba5f2c8", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-input-required.json": "00630687e7f8876e0fa14c14ad7f4989ce244b147cafdffe3089c62a062927eb", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-submitted.json": "1a02a09edfb86e4cbd677d161b1ee208427593b4e85c68930e565cf2b849dd30", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-working.json": "eab7913469420a43c9461e20bfe6bd057a139d49cfae08b59b71d7445cf0dab8", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-request.json": "ae9d2eda5dae9d5dd90e7835de153c097341a26ddd9f4c625fadefe13568cab0", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-response.json": "abdd7fc706a017bf37e52f354c9d6140d33ea422c999766797c6a02c04cfd013", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-authorized-properties-request.json": "b13aa3eddcb4cb3e5efe64dca2dd520d5e83dfaa542587b5d88c360ddfa56178", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-authorized-properties-response.json": "11520ba350e4af718dbdb4f0122f3a4d9e278a460b4eeaffad265772446d43b3", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creative-formats-request.json": "91990929c6c46a1d232bfb96a06d9ea9984b30de66d73d67a57744b7c3e90ad1", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creative-formats-response.json": "9237034591d0c325367d9530ae843f809a7927424a9c3ffca42a96b3826e3803", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creatives-request.json": "0788f951ff430c8cea3a012bd7c4ad64568385fa8f3ebf31e5930bad55702e09", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creatives-response.json": "4ce8932d0a9d03a2d3268e486367f1b6e9bf8b8e4811fe54cb8b0cfd1ed9943a", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/package-request.json": "975a46e52e17f996bb2c07b8b65a8987e90b4c5bfa49300e8dca25e21edd1c8f", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/provide-performance-feedback-request.json": "a75a015151b0bb2dea2eb5a38b4277b5ce610c6f73a6e36985742d1ca155d905", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/provide-performance-feedback-response.json": "221b7abdf0ba2765e498cc26d3f0bd91457e38a0c721d845a07465f87340bbf1", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-input-required.json": "e47eb69105a4c390b37a15c5097343d8b8a7491342e721bc7ddcab780de241de", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-submitted.json": "6a715ca5966419ac98eb709a78a2f6790fe573ac487190316935a72c8c533576", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-working.json": "ae2d75d062fd633e0661ef6fa10f712b1a88ddea237f4df8178b18110eece5f6", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-request.json": "972112985ae62cfc4f15e7083ed0c1992afa4bc5c377abaa063e5e02f2a27de9", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-response.json": "fba9d521d1a57ee8839a80f5cf7ac38bc0c5b4b719aff50d6fbe9074a50c95a7", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-input-required.json": "ec4b8fedaeba9a5343a858b540a390703381f93f13ba6842cdf334f3d1ce300f", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-submitted.json": "61c4b236551201ce1f2af4be0f91b75dc3ab51731e282e3c9cd6cb74011b72de", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-working.json": "bda5f4df3faf1b0468ac2492b965bd20828a9fafa1c891b3673e68596c5d342e", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-request.json": "e53221c03588f26a8b2f7541564dc44c4e3b63813ae85964aac3b6ad8ab12b0b", + "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-response.json": "19c8537f9f734363820f52a96fc815344fb9cb70eb8e3e88c73296297ffa5a68", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpc-option.json": "34c1a9b76b94065d48c9a5d45534ce81f088c7c3b385f783a8afca8b73da24c9", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpcv-option.json": "ea756831fda6ab8dcad3a1e1d956fe96733e11005926e871c5272050fb0f11fb", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpm-auction-option.json": "fdc3f30491967fe78586cfd69a1042164b0abf6e87d9c606e2090c17b828e306", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpm-fixed-option.json": "0dad3b1aa255a79fba2256b40641420293865ccb93345841207a717e06f9accd", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpp-option.json": "9efebfce87458ae552ad5bc2a0923bfb10d1e55d6c1709312e009c2655209fce", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpv-option.json": "732165490aa7cba55c135fd2560dc02fac68a906b1e76369be7ecd894067ebb4", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/flat-rate-option.json": "2c100f26341acc170df6dd705754c45619be538cfdec790cf08dd8e8e6098d00", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/vcpm-auction-option.json": "6fe3ad592309cf85138b09c86703c212fe4d165fd60d0b6e52356eb17783d304", + "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/vcpm-fixed-option.json": "7b16a9382043bc7968d0c86db3ef513027bcc931f42550ca218b62e6e5c2e41a", + "https://adcontextprotocol.org/schemas/2.6.0/protocols/adcp-extension.json": "33836db34120b0b96c2b28a46b418b6ebb3f80a2fa80c5296f394c152f745147", + "https://adcontextprotocol.org/schemas/2.6.0/signals/activate-signal-request.json": "afa9b3023801fe0589e6bf54c26f9df0dda30362dcf5d59c90693db4f2b7c55a", + "https://adcontextprotocol.org/schemas/2.6.0/signals/activate-signal-response.json": "6710d1ee820f9f887ceaf34cbafffc5cc93441caeaaf9a3cc91742ad60c00d52", + "https://adcontextprotocol.org/schemas/2.6.0/signals/get-signals-request.json": "2df5b4b6e1eed5a5df373a255cda5549bd84eb1dca9a1bb4a5449656be2992ea", + "https://adcontextprotocol.org/schemas/2.6.0/signals/get-signals-response.json": "d6037997c5beae4a7043769f8b8c56530f27357d6fc3bd349a6377e6d886be43" } \ No newline at end of file diff --git a/schemas/cache/adagents.json b/schemas/cache/adagents.json index ae355994b..d1511248f 100644 --- a/schemas/cache/adagents.json +++ b/schemas/cache/adagents.json @@ -3,12 +3,12 @@ "description": "Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.", "examples": [ { - "$schema": "/schemas/latest/adagents.json", + "$schema": "/schemas/2.6.0/adagents.json", "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", "last_updated": "2025-01-15T10:00:00Z" }, { - "$schema": "/schemas/latest/adagents.json", + "$schema": "/schemas/2.6.0/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -41,7 +41,7 @@ } }, { - "$schema": "/schemas/latest/adagents.json", + "$schema": "/schemas/2.6.0/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -135,7 +135,7 @@ } }, { - "$schema": "/schemas/latest/adagents.json", + "$schema": "/schemas/2.6.0/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -174,7 +174,7 @@ } }, { - "$schema": "/schemas/latest/adagents.json", + "$schema": "/schemas/2.6.0/adagents.json", "authorized_agents": [ { "authorization_type": "publisher_properties", @@ -222,7 +222,7 @@ ], "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "URL reference variant - points to the authoritative location of the adagents.json file", "properties": { "$schema": { @@ -247,7 +247,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Inline structure variant - contains full agent authorization data", "properties": { "$schema": { @@ -259,7 +259,7 @@ "items": { "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "authorization_type": { "const": "property_ids", @@ -295,7 +295,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "authorization_type": { "const": "property_tags", @@ -331,7 +331,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "authorization_type": { "const": "inline_properties", @@ -367,7 +367,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "authorization_type": { "const": "publisher_properties", @@ -408,7 +408,7 @@ "type": "array" }, "contact": { - "additionalProperties": false, + "additionalProperties": true, "description": "Contact information for the entity managing this adagents.json file (may be publisher or third-party operator)", "properties": { "domain": { @@ -462,7 +462,7 @@ }, "tags": { "additionalProperties": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "description": { "description": "Description of what this tag represents", diff --git a/schemas/cache/core/activation-key.json b/schemas/cache/core/activation-key.json index ac2543315..6ad5331b5 100644 --- a/schemas/cache/core/activation-key.json +++ b/schemas/cache/core/activation-key.json @@ -3,7 +3,7 @@ "description": "Universal identifier for using a signal on a destination platform. Can be either a segment ID or a key-value pair depending on the platform's targeting mechanism.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "segment_id": { "description": "The platform-specific segment identifier to use in campaign targeting", @@ -21,7 +21,7 @@ ] }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "key": { "description": "The targeting parameter key", diff --git a/schemas/cache/core/assets/audio-asset.json b/schemas/cache/core/assets/audio-asset.json index 5b5206e85..4fd73b6f0 100644 --- a/schemas/cache/core/assets/audio-asset.json +++ b/schemas/cache/core/assets/audio-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Audio asset with URL and specifications", "properties": { "bitrate_kbps": { diff --git a/schemas/cache/core/assets/css-asset.json b/schemas/cache/core/assets/css-asset.json index aaaf521a3..2327c516a 100644 --- a/schemas/cache/core/assets/css-asset.json +++ b/schemas/cache/core/assets/css-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "CSS stylesheet asset", "properties": { "content": { diff --git a/schemas/cache/core/assets/daast-asset.json b/schemas/cache/core/assets/daast-asset.json index 07f17adb1..6e25a751e 100644 --- a/schemas/cache/core/assets/daast-asset.json +++ b/schemas/cache/core/assets/daast-asset.json @@ -3,7 +3,7 @@ "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "companion_ads": { "description": "Whether companion display ads are included", @@ -43,7 +43,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "companion_ads": { "description": "Whether companion display ads are included", diff --git a/schemas/cache/core/assets/html-asset.json b/schemas/cache/core/assets/html-asset.json index fbfa7b5fb..0442fa797 100644 --- a/schemas/cache/core/assets/html-asset.json +++ b/schemas/cache/core/assets/html-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "HTML content asset", "properties": { "content": { diff --git a/schemas/cache/core/assets/image-asset.json b/schemas/cache/core/assets/image-asset.json index e2aa48402..68aa14dfa 100644 --- a/schemas/cache/core/assets/image-asset.json +++ b/schemas/cache/core/assets/image-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Image asset with URL and dimensions", "properties": { "alt_text": { diff --git a/schemas/cache/core/assets/javascript-asset.json b/schemas/cache/core/assets/javascript-asset.json index 7c3d9bc80..a43cd8041 100644 --- a/schemas/cache/core/assets/javascript-asset.json +++ b/schemas/cache/core/assets/javascript-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "JavaScript code asset", "properties": { "content": { diff --git a/schemas/cache/core/assets/text-asset.json b/schemas/cache/core/assets/text-asset.json index 3d236289c..7f4b2d404 100644 --- a/schemas/cache/core/assets/text-asset.json +++ b/schemas/cache/core/assets/text-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Text content asset", "properties": { "content": { diff --git a/schemas/cache/core/assets/url-asset.json b/schemas/cache/core/assets/url-asset.json index 4b714de24..ac5ea5bb3 100644 --- a/schemas/cache/core/assets/url-asset.json +++ b/schemas/cache/core/assets/url-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "URL reference asset", "properties": { "description": { diff --git a/schemas/cache/core/assets/vast-asset.json b/schemas/cache/core/assets/vast-asset.json index 5042129c0..4dc467acb 100644 --- a/schemas/cache/core/assets/vast-asset.json +++ b/schemas/cache/core/assets/vast-asset.json @@ -3,7 +3,7 @@ "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "delivery_type": { "const": "url", @@ -43,7 +43,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "content": { "description": "Inline VAST XML content", diff --git a/schemas/cache/core/assets/video-asset.json b/schemas/cache/core/assets/video-asset.json index de1747adc..d73c6509d 100644 --- a/schemas/cache/core/assets/video-asset.json +++ b/schemas/cache/core/assets/video-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Video asset with URL and specifications", "properties": { "bitrate_kbps": { diff --git a/schemas/cache/core/assets/webhook-asset.json b/schemas/cache/core/assets/webhook-asset.json index 9db9a4012..5ad3f28b5 100644 --- a/schemas/cache/core/assets/webhook-asset.json +++ b/schemas/cache/core/assets/webhook-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Webhook for server-side dynamic content rendering (DCO)", "properties": { "method": { diff --git a/schemas/cache/core/brand-manifest.json b/schemas/cache/core/brand-manifest.json index bc7d63b78..28fa3c341 100644 --- a/schemas/cache/core/brand-manifest.json +++ b/schemas/cache/core/brand-manifest.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Standardized brand information manifest for creative generation and media buying. Enables low-friction creative workflows by providing brand context that can be easily cached and shared across requests.", "examples": [ { @@ -117,7 +117,7 @@ "assets": { "description": "Brand asset library with explicit assets and tags. Assets are referenced inline with URLs pointing to CDN-hosted files.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "asset_id": { "description": "Unique identifier for this asset", @@ -336,7 +336,7 @@ "type": "string" }, "product_catalog": { - "additionalProperties": false, + "additionalProperties": true, "description": "Product catalog information for e-commerce advertisers. Enables SKU-level creative generation and product selection.", "properties": { "categories": { diff --git a/schemas/cache/core/creative-asset.json b/schemas/cache/core/creative-asset.json index b23da7434..ae5dfc6d1 100644 --- a/schemas/cache/core/creative-asset.json +++ b/schemas/cache/core/creative-asset.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Creative asset for upload to library - supports static assets, generative formats, and third-party snippets", "properties": { "approved": { @@ -8,7 +8,7 @@ "type": "boolean" }, "assets": { - "additionalProperties": false, + "additionalProperties": true, "description": "Assets required by the format, keyed by asset_role", "patternProperties": { "^[a-zA-Z0-9_-]+$": { @@ -62,7 +62,7 @@ "inputs": { "description": "Preview contexts for generative formats - defines what scenarios to generate previews for", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "context_description": { "description": "Natural language description of the context for AI-generated content", diff --git a/schemas/cache/core/creative-assignment.json b/schemas/cache/core/creative-assignment.json index 50aa36c39..5ddea1890 100644 --- a/schemas/cache/core/creative-assignment.json +++ b/schemas/cache/core/creative-assignment.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Assignment of a creative asset to a package with optional placement targeting. Used in create_media_buy and update_media_buy requests. Note: sync_creatives does not support placement_ids - use create/update_media_buy for placement-level targeting.", "properties": { "creative_id": { diff --git a/schemas/cache/core/creative-filters.json b/schemas/cache/core/creative-filters.json index c36c04dd0..2dad375db 100644 --- a/schemas/cache/core/creative-filters.json +++ b/schemas/cache/core/creative-filters.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Filter criteria for querying creative assets from the centralized library", "properties": { "assigned_to_package": { diff --git a/schemas/cache/core/creative-manifest.json b/schemas/cache/core/creative-manifest.json index ac7cda7e6..aaf9042d8 100644 --- a/schemas/cache/core/creative-manifest.json +++ b/schemas/cache/core/creative-manifest.json @@ -1,10 +1,10 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Complete specification of a creative with all assets needed for rendering in a specific format. Each asset is typed according to its asset_role from the format specification and contains the actual content/URL that fulfills the format requirements.", "properties": { "assets": { - "additionalProperties": false, + "additionalProperties": true, "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets_required array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Creative manifest validation MUST be performed in the context of the format specification. The format defines what type each asset_id should be, which eliminates any validation ambiguity.", "patternProperties": { "^[a-z0-9_]+$": { diff --git a/schemas/cache/core/creative-policy.json b/schemas/cache/core/creative-policy.json index a6cdd8139..bf17bb57a 100644 --- a/schemas/cache/core/creative-policy.json +++ b/schemas/cache/core/creative-policy.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Creative requirements and restrictions for a product", "properties": { "co_branding": { diff --git a/schemas/cache/core/delivery-metrics.json b/schemas/cache/core/delivery-metrics.json index e1dc6dce5..f4d074f49 100644 --- a/schemas/cache/core/delivery-metrics.json +++ b/schemas/cache/core/delivery-metrics.json @@ -31,7 +31,7 @@ "type": "number" }, "dooh_metrics": { - "additionalProperties": false, + "additionalProperties": true, "description": "DOOH-specific metrics (only included for DOOH campaigns)", "properties": { "calculation_notes": { @@ -62,7 +62,7 @@ "venue_breakdown": { "description": "Per-venue performance breakdown", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "impressions": { "description": "Impressions delivered at this venue", diff --git a/schemas/cache/core/deployment.json b/schemas/cache/core/deployment.json index 047266b6d..b240bb96b 100644 --- a/schemas/cache/core/deployment.json +++ b/schemas/cache/core/deployment.json @@ -3,7 +3,7 @@ "description": "A signal deployment to a specific deployment target with activation status and key", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "account": { "description": "Account identifier if applicable", @@ -45,7 +45,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "account": { "description": "Account identifier if applicable", diff --git a/schemas/cache/core/destination.json b/schemas/cache/core/destination.json index 81f51cf56..323cd69a1 100644 --- a/schemas/cache/core/destination.json +++ b/schemas/cache/core/destination.json @@ -3,7 +3,7 @@ "description": "A deployment target where signals can be activated (DSP, sales agent, etc.)", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "account": { "description": "Optional account identifier on the platform", @@ -25,7 +25,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "account": { "description": "Optional account identifier on the agent", diff --git a/schemas/cache/core/error.json b/schemas/cache/core/error.json index c905c0b23..31adf984b 100644 --- a/schemas/cache/core/error.json +++ b/schemas/cache/core/error.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Standard error structure for task-specific errors and warnings", "properties": { "code": { @@ -8,7 +8,9 @@ "type": "string" }, "details": { - "description": "Additional task-specific error details" + "additionalProperties": true, + "description": "Additional task-specific error details", + "type": "object" }, "field": { "description": "Field path associated with the error (e.g., 'packages[0].targeting')", diff --git a/schemas/cache/core/format-id.json b/schemas/cache/core/format-id.json index 21a55ed44..a2153f0be 100644 --- a/schemas/cache/core/format-id.json +++ b/schemas/cache/core/format-id.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "dependencies": { "height": [ "width" diff --git a/schemas/cache/core/format.json b/schemas/cache/core/format.json index 7fb1bc138..e32840685 100644 --- a/schemas/cache/core/format.json +++ b/schemas/cache/core/format.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Represents a creative format with its requirements", "properties": { "accepts_parameters": { @@ -11,8 +11,128 @@ "type": "array", "uniqueItems": true }, + "assets": { + "description": "Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. This field replaces the deprecated 'assets_required' and enables full asset discovery for buyers and AI agents.", + "items": { + "oneOf": [ + { + "description": "Individual asset specification", + "properties": { + "asset_id": { + "description": "Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object.", + "type": "string" + }, + "asset_role": { + "description": "Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo', 'third_party_tracking'). Not used for referencing assets in manifests\u2014use asset_id instead. This field is for human-readable documentation and UI display only.", + "type": "string" + }, + "asset_type": { + "$ref": "../enums/asset-content-type.json", + "description": "Type of asset" + }, + "item_type": { + "const": "individual", + "description": "Discriminator indicating this is an individual asset", + "type": "string" + }, + "required": { + "description": "Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.", + "type": "boolean" + }, + "requirements": { + "additionalProperties": true, + "description": "Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).", + "type": "object" + } + }, + "required": [ + "item_type", + "asset_id", + "asset_type", + "required" + ], + "type": "object" + }, + { + "description": "Repeatable asset group (for carousels, slideshows, playlists, etc.)", + "properties": { + "asset_group_id": { + "description": "Identifier for this asset group (e.g., 'product', 'slide', 'card')", + "type": "string" + }, + "assets": { + "description": "Assets within each repetition of this group", + "items": { + "properties": { + "asset_id": { + "description": "Identifier for this asset within the group", + "type": "string" + }, + "asset_role": { + "description": "Optional descriptive label for this asset's purpose. Not used for referencing assets in manifests\u2014use asset_id instead. This field is for human-readable documentation and UI display only.", + "type": "string" + }, + "asset_type": { + "$ref": "../enums/asset-content-type.json", + "description": "Type of asset" + }, + "required": { + "default": false, + "description": "Whether this asset is required within each repetition of the group", + "type": "boolean" + }, + "requirements": { + "additionalProperties": true, + "description": "Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).", + "type": "object" + } + }, + "required": [ + "asset_id", + "asset_type", + "required" + ], + "type": "object" + }, + "type": "array" + }, + "item_type": { + "const": "repeatable_group", + "description": "Discriminator indicating this is a repeatable asset group", + "type": "string" + }, + "max_count": { + "description": "Maximum number of repetitions allowed", + "minimum": 1, + "type": "integer" + }, + "min_count": { + "description": "Minimum number of repetitions required (if group is required) or allowed (if optional)", + "minimum": 0, + "type": "integer" + }, + "required": { + "description": "Whether this asset group is required. If true, at least min_count repetitions must be provided.", + "type": "boolean" + } + }, + "required": [ + "item_type", + "asset_group_id", + "required", + "min_count", + "max_count", + "assets" + ], + "type": "object" + } + ] + }, + "type": "array" + }, "assets_required": { - "description": "Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames).", + "deprecated": true, + "description": "DEPRECATED: Use 'assets' instead. Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames). This field is maintained for backward compatibility; new implementations should use 'assets' with the 'required' boolean on each asset.", "items": { "oneOf": [ { @@ -137,7 +257,7 @@ "type": "string" }, "format_card": { - "additionalProperties": false, + "additionalProperties": true, "description": "Optional standard visual card (300x400px) for displaying this format in user interfaces. Can be rendered via preview_creative or pre-generated.", "properties": { "format_id": { @@ -157,7 +277,7 @@ "type": "object" }, "format_card_detailed": { - "additionalProperties": false, + "additionalProperties": true, "description": "Optional detailed card with carousel and full specifications. Provides rich format documentation similar to ad spec pages.", "properties": { "format_id": { diff --git a/schemas/cache/core/frequency-cap.json b/schemas/cache/core/frequency-cap.json index 2eb753af2..7a658fd16 100644 --- a/schemas/cache/core/frequency-cap.json +++ b/schemas/cache/core/frequency-cap.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Frequency capping settings for package-level application", "properties": { "suppress_minutes": { diff --git a/schemas/cache/core/measurement.json b/schemas/cache/core/measurement.json index 6ae8e3f31..b0ba1c51a 100644 --- a/schemas/cache/core/measurement.json +++ b/schemas/cache/core/measurement.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Measurement capabilities included with a product", "properties": { "attribution": { diff --git a/schemas/cache/core/media-buy.json b/schemas/cache/core/media-buy.json index a7e2c74c3..e738afb68 100644 --- a/schemas/cache/core/media-buy.json +++ b/schemas/cache/core/media-buy.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Represents a purchased advertising campaign", "properties": { "buyer_ref": { diff --git a/schemas/cache/core/package.json b/schemas/cache/core/package.json index 5e97f457e..868e443e4 100644 --- a/schemas/cache/core/package.json +++ b/schemas/cache/core/package.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "A specific product within a media buy (line item)", "properties": { "bid_price": { diff --git a/schemas/cache/core/performance-feedback.json b/schemas/cache/core/performance-feedback.json index 6d5a9c010..1e289867d 100644 --- a/schemas/cache/core/performance-feedback.json +++ b/schemas/cache/core/performance-feedback.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Represents performance feedback data for a media buy or package", "properties": { "applied_at": { @@ -21,7 +21,7 @@ "description": "Source of the performance data" }, "measurement_period": { - "additionalProperties": false, + "additionalProperties": true, "description": "Time period for performance measurement", "properties": { "end": { diff --git a/schemas/cache/core/placement.json b/schemas/cache/core/placement.json index 35fab2c80..3fd390379 100644 --- a/schemas/cache/core/placement.json +++ b/schemas/cache/core/placement.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Represents a specific ad placement within a product's inventory", "properties": { "description": { diff --git a/schemas/cache/core/product-filters.json b/schemas/cache/core/product-filters.json index 7fcdc81cd..2104a47c5 100644 --- a/schemas/cache/core/product-filters.json +++ b/schemas/cache/core/product-filters.json @@ -1,10 +1,10 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Structured filters for product discovery", "properties": { "budget_range": { - "additionalProperties": false, + "additionalProperties": true, "anyOf": [ { "required": [ diff --git a/schemas/cache/core/product.json b/schemas/cache/core/product.json index d8656b57e..094887db7 100644 --- a/schemas/cache/core/product.json +++ b/schemas/cache/core/product.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Represents available advertising inventory", "properties": { "brief_relevance": { @@ -82,7 +82,7 @@ "type": "array" }, "product_card": { - "additionalProperties": false, + "additionalProperties": true, "description": "Optional standard visual card (300x400px) for displaying this product in user interfaces. Can be rendered via preview_creative or pre-generated.", "properties": { "format_id": { @@ -102,7 +102,7 @@ "type": "object" }, "product_card_detailed": { - "additionalProperties": false, + "additionalProperties": true, "description": "Optional detailed card with carousel and full specifications. Provides rich product presentation similar to media kit pages.", "properties": { "format_id": { diff --git a/schemas/cache/core/promoted-offerings.json b/schemas/cache/core/promoted-offerings.json index d22d4b81a..d956dce4d 100644 --- a/schemas/cache/core/promoted-offerings.json +++ b/schemas/cache/core/promoted-offerings.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Complete offering specification combining brand manifest, product selectors, and asset filters. Provides all context needed for creative generation about what is being promoted.", "examples": [ { @@ -27,7 +27,7 @@ ], "properties": { "asset_selectors": { - "additionalProperties": false, + "additionalProperties": true, "description": "Selectors to choose specific assets from the brand manifest", "properties": { "asset_types": { @@ -74,7 +74,7 @@ "offerings": { "description": "Inline offerings for campaigns without a product catalog. Each offering has a name, description, and associated assets.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "assets": { "description": "Assets specific to this offering", diff --git a/schemas/cache/core/promoted-products.json b/schemas/cache/core/promoted-products.json index 3b65cb08c..65c7e0a78 100644 --- a/schemas/cache/core/promoted-products.json +++ b/schemas/cache/core/promoted-products.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Specification of products or offerings being promoted in a campaign. Supports multiple selection methods from the brand manifest that can be combined using UNION (OR) logic. When multiple selection methods are provided, products matching ANY of the criteria are selected (logical OR, not AND).", "examples": [ { diff --git a/schemas/cache/core/property.json b/schemas/cache/core/property.json index 1cad9cb68..7d6535063 100644 --- a/schemas/cache/core/property.json +++ b/schemas/cache/core/property.json @@ -1,12 +1,12 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "An advertising property that can be validated via adagents.json", "properties": { "identifiers": { "description": "Array of identifiers for this property", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "type": { "$ref": "../enums/identifier-types.json", diff --git a/schemas/cache/core/protocol-envelope.json b/schemas/cache/core/protocol-envelope.json index 6e7220de9..8ff95b501 100644 --- a/schemas/cache/core/protocol-envelope.json +++ b/schemas/cache/core/protocol-envelope.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Standard envelope structure for AdCP task responses. This envelope is added by the protocol layer (MCP, A2A, REST) and wraps the task-specific response payload. Task response schemas should NOT include these fields - they are protocol-level concerns.", "examples": [ { diff --git a/schemas/cache/core/publisher-property-selector.json b/schemas/cache/core/publisher-property-selector.json index 8429b23e0..f4df5fe6c 100644 --- a/schemas/cache/core/publisher-property-selector.json +++ b/schemas/cache/core/publisher-property-selector.json @@ -6,7 +6,7 @@ }, "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Select all properties from the publisher domain", "properties": { "publisher_domain": { @@ -27,7 +27,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Select specific properties by ID", "properties": { "property_ids": { @@ -57,7 +57,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Select properties by tag membership", "properties": { "property_tags": { diff --git a/schemas/cache/core/reporting-capabilities.json b/schemas/cache/core/reporting-capabilities.json index 7cec38438..3ce119a1c 100644 --- a/schemas/cache/core/reporting-capabilities.json +++ b/schemas/cache/core/reporting-capabilities.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Reporting capabilities available for a product", "properties": { "available_metrics": { diff --git a/schemas/cache/core/response.json b/schemas/cache/core/response.json index b23290ad5..1e33e1b7c 100644 --- a/schemas/cache/core/response.json +++ b/schemas/cache/core/response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Protocol-level response wrapper (MCP/A2A) - contains AdCP task data plus protocol fields", "properties": { "context_id": { diff --git a/schemas/cache/core/signal-filters.json b/schemas/cache/core/signal-filters.json index f3a1d5f7c..e65e896ad 100644 --- a/schemas/cache/core/signal-filters.json +++ b/schemas/cache/core/signal-filters.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Filters to refine signal discovery results", "properties": { "catalog_types": { diff --git a/schemas/cache/core/sub-asset.json b/schemas/cache/core/sub-asset.json index ab332500a..798057068 100644 --- a/schemas/cache/core/sub-asset.json +++ b/schemas/cache/core/sub-asset.json @@ -3,7 +3,7 @@ "description": "Sub-asset for multi-asset creative formats, including carousel images and native ad template variables", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "properties": { "asset_id": { "description": "Unique identifier for the asset within the creative", @@ -33,7 +33,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "properties": { "asset_id": { "description": "Unique identifier for the asset within the creative", diff --git a/schemas/cache/core/targeting.json b/schemas/cache/core/targeting.json index 2518463d1..318ee547f 100644 --- a/schemas/cache/core/targeting.json +++ b/schemas/cache/core/targeting.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Optional geographic refinements for media buys. Most targeting should be expressed in the brief and handled by the publisher. These fields are primarily for geographic restrictions (RCT testing, regulatory compliance).", "properties": { "axe_exclude_segment": { diff --git a/schemas/cache/creative/asset-types/index.json b/schemas/cache/creative/asset-types/index.json index aa6c6340e..e29da17b9 100644 --- a/schemas/cache/creative/asset-types/index.json +++ b/schemas/cache/creative/asset-types/index.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "adcp_version": "latest", + "adcp_version": "2.6.0", "architecture": { "format_aware_validation": { "description": "Creative manifests are validated in the context of their format specification", @@ -89,9 +89,9 @@ "typical_use": "DCO (Dynamic Creative Optimization), real-time personalization, server-side rendering" } }, - "baseUrl": "/schemas/latest", + "baseUrl": "/schemas/2.6.0", "description": "Registry of asset types used in AdCP creative manifests. Each asset type defines the structure of actual content payloads (what you send), not requirements or constraints (which belong in format specifications).", - "lastUpdated": "2025-12-18", + "lastUpdated": "2026-01-07", "title": "AdCP Asset Type Registry", "usage_notes": { "creative_manifests": "Creative manifests provide actual asset content, keyed by asset_id from the format. Asset type is determined by the format specification, not declared in the payload.", @@ -100,6 +100,6 @@ }, "version": "1.0.0", "versioning": { - "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP latest. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/vlatest/ \u2192 /schemas/latest/." + "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 2.6.0. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/v2/ \u2192 /schemas/2.6.0/." } } \ No newline at end of file diff --git a/schemas/cache/creative/list-creative-formats-request.json b/schemas/cache/creative/list-creative-formats-request.json index 17aae342e..948f72837 100644 --- a/schemas/cache/creative/list-creative-formats-request.json +++ b/schemas/cache/creative/list-creative-formats-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for discovering creative formats provided by this creative agent", "properties": { "asset_types": { diff --git a/schemas/cache/creative/list-creative-formats-response.json b/schemas/cache/creative/list-creative-formats-response.json index cc66572c6..f211c4caf 100644 --- a/schemas/cache/creative/list-creative-formats-response.json +++ b/schemas/cache/creative/list-creative-formats-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for list_creative_formats task from creative agent - returns full format definitions", "properties": { "context": { diff --git a/schemas/cache/creative/preview-creative-request.json b/schemas/cache/creative/preview-creative-request.json index fa175b7d1..0166a8d11 100644 --- a/schemas/cache/creative/preview-creative-request.json +++ b/schemas/cache/creative/preview-creative-request.json @@ -3,7 +3,7 @@ "description": "Request to generate previews of one or more creative manifests. Accepts either a single creative request or an array of requests for batch processing.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Single creative preview request", "properties": { "context": { @@ -23,7 +23,7 @@ "inputs": { "description": "Array of input sets for generating multiple preview variants. Each input set defines macros and context values for one preview rendering. If not provided, creative agent will generate default previews.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "context_description": { "description": "Natural language description of the context for AI-generated content (e.g., 'User just searched for running shoes', 'Podcast discussing weather patterns', 'Article about electric vehicles')", @@ -33,7 +33,7 @@ "additionalProperties": { "type": "string" }, - "description": "Macro values to use for this preview. Supports all universal macros from the format's supported_macros list. See docs/media-buy/creatives/universal-macros.md for available macros.", + "description": "Macro values to use for this preview. Supports all universal macros from the format's supported_macros list. See docs/creative/universal-macros.md for available macros.", "type": "object" }, "name": { @@ -71,7 +71,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Batch preview request for multiple creatives (5-10x faster than individual calls)", "properties": { "context": { @@ -93,7 +93,7 @@ "requests": { "description": "Array of preview requests (1-50 items). Each follows the single request structure.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "creative_manifest": { "$ref": "../core/creative-manifest.json", @@ -106,7 +106,7 @@ "inputs": { "description": "Array of input sets for generating multiple preview variants", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "context_description": { "description": "Natural language description of the context for AI-generated content", diff --git a/schemas/cache/creative/preview-creative-response.json b/schemas/cache/creative/preview-creative-response.json index 3290efd3b..e04712c9f 100644 --- a/schemas/cache/creative/preview-creative-response.json +++ b/schemas/cache/creative/preview-creative-response.json @@ -3,7 +3,7 @@ "description": "Response containing preview links for one or more creatives. Format matches the request: single preview response for single requests, batch results for batch requests.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Single preview response - each preview URL returns an HTML page that can be embedded in an iframe", "properties": { "context": { @@ -88,7 +88,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Batch preview response - contains results for multiple creative requests", "properties": { "context": { diff --git a/schemas/cache/creative/preview-render.json b/schemas/cache/creative/preview-render.json index 9d1a2c21f..509aaf913 100644 --- a/schemas/cache/creative/preview-render.json +++ b/schemas/cache/creative/preview-render.json @@ -3,7 +3,7 @@ "description": "A single rendered piece of a creative preview with discriminated output format", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "URL-only preview format", "properties": { "dimensions": { @@ -74,7 +74,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "HTML-only preview format", "properties": { "dimensions": { @@ -144,7 +144,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Both URL and HTML preview format", "properties": { "dimensions": { diff --git a/schemas/cache/media-buy/build-creative-request.json b/schemas/cache/media-buy/build-creative-request.json index a0aa5f2e9..ab5758377 100644 --- a/schemas/cache/media-buy/build-creative-request.json +++ b/schemas/cache/media-buy/build-creative-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request to transform or generate a creative manifest. Takes a source manifest (which may be minimal for pure generation) and produces a target manifest in the specified format. The source manifest should include all assets required by the target format (e.g., promoted_offerings for generative formats).", "properties": { "context": { diff --git a/schemas/cache/media-buy/build-creative-response.json b/schemas/cache/media-buy/build-creative-response.json index 5ee757c27..bf8c9256d 100644 --- a/schemas/cache/media-buy/build-creative-response.json +++ b/schemas/cache/media-buy/build-creative-response.json @@ -3,7 +3,7 @@ "description": "Response containing the transformed or generated creative manifest, ready for use with preview_creative or sync_creatives. Returns either the complete creative manifest OR error information, never both.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - creative manifest generated successfully", "not": { "required": [ @@ -29,7 +29,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - creative generation failed", "not": { "required": [ diff --git a/schemas/cache/media-buy/create-media-buy-async-response-input-required.json b/schemas/cache/media-buy/create-media-buy-async-response-input-required.json index 61dfab09d..2585b957e 100644 --- a/schemas/cache/media-buy/create-media-buy-async-response-input-required.json +++ b/schemas/cache/media-buy/create-media-buy-async-response-input-required.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload when task is paused waiting for user input or approval.", "properties": { "context": { 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 306f18898..e95a3d0b8 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,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload acknowledging the task is queued. Usually empty or just context.", "properties": { "context": { diff --git a/schemas/cache/media-buy/create-media-buy-async-response-working.json b/schemas/cache/media-buy/create-media-buy-async-response-working.json index aa8469c22..3db307649 100644 --- a/schemas/cache/media-buy/create-media-buy-async-response-working.json +++ b/schemas/cache/media-buy/create-media-buy-async-response-working.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Progress payload for active create_media_buy task.", "properties": { "context": { diff --git a/schemas/cache/media-buy/create-media-buy-request.json b/schemas/cache/media-buy/create-media-buy-request.json index 926c581e0..2d2686b03 100644 --- a/schemas/cache/media-buy/create-media-buy-request.json +++ b/schemas/cache/media-buy/create-media-buy-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for creating a media buy", "properties": { "brand_manifest": { @@ -34,48 +34,80 @@ "type": "string" }, "reporting_webhook": { - "allOf": [ - { - "$ref": "../core/push-notification-config.json" - }, - { - "description": "Optional webhook configuration for automated reporting delivery. Uses push_notification_config structure with additional reporting-specific fields.", + "$comment": "Fields url, token, and authentication mirror push-notification-config.json. Inlined here because allOf + additionalProperties:false doesn't work in JSON Schema (additionalProperties can't see $ref properties). See CLAUDE.md 'Avoiding allOf with additionalProperties'.", + "additionalProperties": true, + "description": "Optional webhook configuration for automated reporting delivery. Combines push_notification_config structure with reporting-specific fields.", + "properties": { + "authentication": { + "additionalProperties": false, + "description": "Authentication configuration for webhook delivery (A2A-compatible)", "properties": { - "reporting_frequency": { - "description": "Frequency for automated reporting delivery. Must be supported by all products in the media buy.", - "enum": [ - "hourly", - "daily", - "monthly" - ], + "credentials": { + "description": "Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + "minLength": 32, "type": "string" }, - "requested_metrics": { - "description": "Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics.", + "schemes": { + "description": "Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", "items": { - "enum": [ - "impressions", - "spend", - "clicks", - "ctr", - "video_completions", - "completion_rate", - "conversions", - "viewability", - "engagement_rate" - ], - "type": "string" + "$ref": "../enums/auth-scheme.json" }, - "type": "array", - "uniqueItems": true + "maxItems": 1, + "minItems": 1, + "type": "array" } }, "required": [ - "reporting_frequency" + "schemes", + "credentials" ], "type": "object" + }, + "reporting_frequency": { + "description": "Frequency for automated reporting delivery. Must be supported by all products in the media buy.", + "enum": [ + "hourly", + "daily", + "monthly" + ], + "type": "string" + }, + "requested_metrics": { + "description": "Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics.", + "items": { + "enum": [ + "impressions", + "spend", + "clicks", + "ctr", + "video_completions", + "completion_rate", + "conversions", + "viewability", + "engagement_rate" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "token": { + "description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.", + "minLength": 16, + "type": "string" + }, + "url": { + "description": "Webhook endpoint URL for reporting notifications", + "format": "uri", + "type": "string" } - ] + }, + "required": [ + "url", + "authentication", + "reporting_frequency" + ], + "type": "object" }, "start_time": { "$ref": "../core/start-timing.json" diff --git a/schemas/cache/media-buy/create-media-buy-response.json b/schemas/cache/media-buy/create-media-buy-response.json index 0e869af2e..b0673a3cb 100644 --- a/schemas/cache/media-buy/create-media-buy-response.json +++ b/schemas/cache/media-buy/create-media-buy-response.json @@ -3,7 +3,7 @@ "description": "Response payload for create_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the media buy is either fully created or not created at all.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - media buy created successfully", "not": { "required": [ @@ -47,7 +47,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - operation failed, no media buy created", "not": { "anyOf": [ diff --git a/schemas/cache/media-buy/get-media-buy-delivery-request.json b/schemas/cache/media-buy/get-media-buy-delivery-request.json index f99c9cde4..f1c7600a2 100644 --- a/schemas/cache/media-buy/get-media-buy-delivery-request.json +++ b/schemas/cache/media-buy/get-media-buy-delivery-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for retrieving comprehensive delivery metrics", "properties": { "buyer_refs": { diff --git a/schemas/cache/media-buy/get-media-buy-delivery-response.json b/schemas/cache/media-buy/get-media-buy-delivery-response.json index a73bda16c..5b8662a90 100644 --- a/schemas/cache/media-buy/get-media-buy-delivery-response.json +++ b/schemas/cache/media-buy/get-media-buy-delivery-response.json @@ -1,10 +1,10 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for get_media_buy_delivery task", "properties": { "aggregated_totals": { - "additionalProperties": false, + "additionalProperties": true, "description": "Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.", "properties": { "clicks": { @@ -61,7 +61,7 @@ "media_buy_deliveries": { "description": "Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "buyer_ref": { "description": "Buyer's reference identifier for this media buy", @@ -135,7 +135,7 @@ "daily_breakdown": { "description": "Day-by-day delivery", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "date": { "description": "Date (YYYY-MM-DD)", @@ -243,7 +243,7 @@ "type": "boolean" }, "reporting_period": { - "additionalProperties": false, + "additionalProperties": true, "description": "Date range for the report. All periods use UTC timezone.", "properties": { "end": { diff --git a/schemas/cache/media-buy/get-products-async-response-input-required.json b/schemas/cache/media-buy/get-products-async-response-input-required.json index 95343e44b..bc82fea0f 100644 --- a/schemas/cache/media-buy/get-products-async-response-input-required.json +++ b/schemas/cache/media-buy/get-products-async-response-input-required.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload when search is paused waiting for user clarification.", "properties": { "context": { diff --git a/schemas/cache/media-buy/get-products-async-response-submitted.json b/schemas/cache/media-buy/get-products-async-response-submitted.json index 57d8599ce..b91031a76 100644 --- a/schemas/cache/media-buy/get-products-async-response-submitted.json +++ b/schemas/cache/media-buy/get-products-async-response-submitted.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload acknowledging the search is queued. Usually for custom/bespoke product curation.", "properties": { "context": { diff --git a/schemas/cache/media-buy/get-products-async-response-working.json b/schemas/cache/media-buy/get-products-async-response-working.json index 67343fd58..e0dbc1813 100644 --- a/schemas/cache/media-buy/get-products-async-response-working.json +++ b/schemas/cache/media-buy/get-products-async-response-working.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Progress payload for active get_products task.", "properties": { "context": { diff --git a/schemas/cache/media-buy/get-products-request.json b/schemas/cache/media-buy/get-products-request.json index 338c7e247..1896428c0 100644 --- a/schemas/cache/media-buy/get-products-request.json +++ b/schemas/cache/media-buy/get-products-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for discovering available advertising products", "properties": { "brand_manifest": { diff --git a/schemas/cache/media-buy/get-products-response.json b/schemas/cache/media-buy/get-products-response.json index c78add6dd..ee961efa2 100644 --- a/schemas/cache/media-buy/get-products-response.json +++ b/schemas/cache/media-buy/get-products-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for get_products task", "properties": { "context": { diff --git a/schemas/cache/media-buy/list-authorized-properties-request.json b/schemas/cache/media-buy/list-authorized-properties-request.json index 93f6e4058..352f329f1 100644 --- a/schemas/cache/media-buy/list-authorized-properties-request.json +++ b/schemas/cache/media-buy/list-authorized-properties-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for discovering which publishers this agent is authorized to represent", "properties": { "context": { diff --git a/schemas/cache/media-buy/list-authorized-properties-response.json b/schemas/cache/media-buy/list-authorized-properties-response.json index ca0fbebeb..7fb862a1d 100644 --- a/schemas/cache/media-buy/list-authorized-properties-response.json +++ b/schemas/cache/media-buy/list-authorized-properties-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for list_authorized_properties task. Lists publisher domains and authorization scope (property_ids or property_tags). Buyers fetch actual property definitions from each publisher's canonical adagents.json file.", "properties": { "advertising_policies": { diff --git a/schemas/cache/media-buy/list-creative-formats-request.json b/schemas/cache/media-buy/list-creative-formats-request.json index 6ffe0fbfa..39bae2047 100644 --- a/schemas/cache/media-buy/list-creative-formats-request.json +++ b/schemas/cache/media-buy/list-creative-formats-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for discovering supported creative formats", "properties": { "asset_types": { diff --git a/schemas/cache/media-buy/list-creative-formats-response.json b/schemas/cache/media-buy/list-creative-formats-response.json index aca33f516..0c8f657f2 100644 --- a/schemas/cache/media-buy/list-creative-formats-response.json +++ b/schemas/cache/media-buy/list-creative-formats-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for list_creative_formats task", "properties": { "context": { diff --git a/schemas/cache/media-buy/list-creatives-request.json b/schemas/cache/media-buy/list-creatives-request.json index fd6965c4e..6ab366c60 100644 --- a/schemas/cache/media-buy/list-creatives-request.json +++ b/schemas/cache/media-buy/list-creatives-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for querying creative assets from the centralized library with filtering, sorting, and pagination", "examples": [ { @@ -94,7 +94,7 @@ "type": "boolean" }, "pagination": { - "additionalProperties": false, + "additionalProperties": true, "description": "Pagination parameters", "properties": { "limit": { @@ -114,7 +114,7 @@ "type": "object" }, "sort": { - "additionalProperties": false, + "additionalProperties": true, "description": "Sorting parameters", "properties": { "direction": { diff --git a/schemas/cache/media-buy/list-creatives-response.json b/schemas/cache/media-buy/list-creatives-response.json index 437e37bd3..96b857bbe 100644 --- a/schemas/cache/media-buy/list-creatives-response.json +++ b/schemas/cache/media-buy/list-creatives-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response from creative library query with filtered results, metadata, and optional enriched data", "examples": [ { @@ -114,7 +114,7 @@ "creatives": { "description": "Array of creative assets matching the query", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "assets": { "description": "Assets for this creative, keyed by asset_role", @@ -160,13 +160,13 @@ "type": "object" }, "assignments": { - "additionalProperties": false, + "additionalProperties": true, "description": "Current package assignments (included when include_assignments=true)", "properties": { "assigned_packages": { "description": "List of packages this creative is assigned to", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "assigned_date": { "description": "When this assignment was created", @@ -229,7 +229,7 @@ "type": "string" }, "performance": { - "additionalProperties": false, + "additionalProperties": true, "description": "Aggregated performance metrics (included when include_performance=true)", "properties": { "clicks": { @@ -311,7 +311,7 @@ "$ref": "../core/ext.json" }, "format_summary": { - "additionalProperties": false, + "additionalProperties": true, "description": "Breakdown of creatives by format type", "patternProperties": { "^[a-zA-Z0-9_-]+$": { @@ -323,7 +323,7 @@ "type": "object" }, "pagination": { - "additionalProperties": false, + "additionalProperties": true, "description": "Pagination information for navigating results", "properties": { "current_page": { @@ -359,7 +359,7 @@ "type": "object" }, "query_summary": { - "additionalProperties": false, + "additionalProperties": true, "description": "Summary of the query that was executed", "properties": { "filters_applied": { @@ -399,7 +399,7 @@ "type": "object" }, "status_summary": { - "additionalProperties": false, + "additionalProperties": true, "description": "Breakdown of creatives by status", "properties": { "approved": { diff --git a/schemas/cache/media-buy/package-request.json b/schemas/cache/media-buy/package-request.json index ad22e3232..09002e636 100644 --- a/schemas/cache/media-buy/package-request.json +++ b/schemas/cache/media-buy/package-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Package configuration for media buy creation", "properties": { "bid_price": { diff --git a/schemas/cache/media-buy/provide-performance-feedback-request.json b/schemas/cache/media-buy/provide-performance-feedback-request.json index 5d50d8329..43e3f098b 100644 --- a/schemas/cache/media-buy/provide-performance-feedback-request.json +++ b/schemas/cache/media-buy/provide-performance-feedback-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request payload for provide_performance_feedback task", "oneOf": [ { @@ -41,7 +41,7 @@ "description": "Source of the performance data" }, "measurement_period": { - "additionalProperties": false, + "additionalProperties": true, "description": "Time period for performance measurement", "properties": { "end": { diff --git a/schemas/cache/media-buy/provide-performance-feedback-response.json b/schemas/cache/media-buy/provide-performance-feedback-response.json index f32a3fd19..d109718fd 100644 --- a/schemas/cache/media-buy/provide-performance-feedback-response.json +++ b/schemas/cache/media-buy/provide-performance-feedback-response.json @@ -3,7 +3,7 @@ "description": "Response payload for provide_performance_feedback task. Returns either success confirmation OR error information, never both.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - feedback received and processed", "not": { "required": [ @@ -30,7 +30,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - feedback rejected or could not be processed", "not": { "required": [ diff --git a/schemas/cache/media-buy/sync-creatives-async-response-input-required.json b/schemas/cache/media-buy/sync-creatives-async-response-input-required.json index 4c803b365..7cd907538 100644 --- a/schemas/cache/media-buy/sync-creatives-async-response-input-required.json +++ b/schemas/cache/media-buy/sync-creatives-async-response-input-required.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload when sync_creatives task is paused waiting for buyer clarification or approval.", "properties": { "context": { diff --git a/schemas/cache/media-buy/sync-creatives-async-response-submitted.json b/schemas/cache/media-buy/sync-creatives-async-response-submitted.json index 364dfcb96..e0ba03113 100644 --- a/schemas/cache/media-buy/sync-creatives-async-response-submitted.json +++ b/schemas/cache/media-buy/sync-creatives-async-response-submitted.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload acknowledging sync_creatives task is queued for processing.", "properties": { "context": { diff --git a/schemas/cache/media-buy/sync-creatives-async-response-working.json b/schemas/cache/media-buy/sync-creatives-async-response-working.json index b92ba7e36..83f360b0f 100644 --- a/schemas/cache/media-buy/sync-creatives-async-response-working.json +++ b/schemas/cache/media-buy/sync-creatives-async-response-working.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Progress payload for active sync_creatives task.", "properties": { "context": { diff --git a/schemas/cache/media-buy/sync-creatives-request.json b/schemas/cache/media-buy/sync-creatives-request.json index 3261d4109..51961fc77 100644 --- a/schemas/cache/media-buy/sync-creatives-request.json +++ b/schemas/cache/media-buy/sync-creatives-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for syncing creative assets with upsert semantics - supports bulk operations, scoped updates, and assignment management", "examples": [ { @@ -114,7 +114,7 @@ ], "properties": { "assignments": { - "additionalProperties": false, + "additionalProperties": true, "description": "Optional bulk assignment of creatives to packages", "patternProperties": { "^[a-zA-Z0-9_-]+$": { diff --git a/schemas/cache/media-buy/sync-creatives-response.json b/schemas/cache/media-buy/sync-creatives-response.json index fc9ea41de..fb8b4c6cb 100644 --- a/schemas/cache/media-buy/sync-creatives-response.json +++ b/schemas/cache/media-buy/sync-creatives-response.json @@ -3,7 +3,7 @@ "description": "Response from creative sync operation. Returns either per-creative results (best-effort processing) OR operation-level errors (complete failure). This enforces atomic semantics at the operation level while allowing per-item failures within successful operations.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - sync operation processed creatives (may include per-item failures)", "not": { "required": [ @@ -17,7 +17,7 @@ "creatives": { "description": "Results for each creative processed. Items with action='failed' indicate per-item validation/processing failures, not operation-level failures.", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "action": { "$ref": "../enums/creative-action.json", @@ -31,7 +31,7 @@ "type": "array" }, "assignment_errors": { - "additionalProperties": false, + "additionalProperties": true, "description": "Assignment errors by package ID (only present when assignment failures occurred)", "patternProperties": { "^[a-zA-Z0-9_-]+$": { @@ -104,7 +104,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - operation failed completely, no creatives were processed", "not": { "anyOf": [ diff --git a/schemas/cache/media-buy/update-media-buy-async-response-input-required.json b/schemas/cache/media-buy/update-media-buy-async-response-input-required.json index 9547de764..8e20eb5ca 100644 --- a/schemas/cache/media-buy/update-media-buy-async-response-input-required.json +++ b/schemas/cache/media-buy/update-media-buy-async-response-input-required.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload when update_media_buy task is paused waiting for user input or approval.", "properties": { "context": { diff --git a/schemas/cache/media-buy/update-media-buy-async-response-submitted.json b/schemas/cache/media-buy/update-media-buy-async-response-submitted.json index f56be9f49..681a5da72 100644 --- a/schemas/cache/media-buy/update-media-buy-async-response-submitted.json +++ b/schemas/cache/media-buy/update-media-buy-async-response-submitted.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Payload acknowledging update_media_buy task is queued for processing.", "properties": { "context": { diff --git a/schemas/cache/media-buy/update-media-buy-async-response-working.json b/schemas/cache/media-buy/update-media-buy-async-response-working.json index c92509e7a..775c885a0 100644 --- a/schemas/cache/media-buy/update-media-buy-async-response-working.json +++ b/schemas/cache/media-buy/update-media-buy-async-response-working.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Progress payload for active update_media_buy task.", "properties": { "context": { diff --git a/schemas/cache/media-buy/update-media-buy-request.json b/schemas/cache/media-buy/update-media-buy-request.json index cf260f565..86d977171 100644 --- a/schemas/cache/media-buy/update-media-buy-request.json +++ b/schemas/cache/media-buy/update-media-buy-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for updating campaign and package settings", "oneOf": [ { @@ -37,7 +37,7 @@ "packages": { "description": "Package-specific updates", "items": { - "additionalProperties": false, + "additionalProperties": true, "oneOf": [ { "required": [ diff --git a/schemas/cache/media-buy/update-media-buy-response.json b/schemas/cache/media-buy/update-media-buy-response.json index 99b2eaccb..a05318bbf 100644 --- a/schemas/cache/media-buy/update-media-buy-response.json +++ b/schemas/cache/media-buy/update-media-buy-response.json @@ -3,7 +3,7 @@ "description": "Response payload for update_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - updates are either fully applied or not applied at all.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - media buy updated successfully", "not": { "required": [ @@ -49,7 +49,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - operation failed, no changes applied", "not": { "anyOf": [ diff --git a/schemas/cache/pricing-options/cpc-option.json b/schemas/cache/pricing-options/cpc-option.json index 7bf78358a..26ede76e1 100644 --- a/schemas/cache/pricing-options/cpc-option.json +++ b/schemas/cache/pricing-options/cpc-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per Click fixed-rate pricing for performance-driven advertising campaigns", "properties": { "currency": { diff --git a/schemas/cache/pricing-options/cpcv-option.json b/schemas/cache/pricing-options/cpcv-option.json index 1ec457141..064fa2efe 100644 --- a/schemas/cache/pricing-options/cpcv-option.json +++ b/schemas/cache/pricing-options/cpcv-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per Completed View (100% video/audio completion) fixed-rate pricing", "properties": { "currency": { diff --git a/schemas/cache/pricing-options/cpm-auction-option.json b/schemas/cache/pricing-options/cpm-auction-option.json index 213545513..8735617ec 100644 --- a/schemas/cache/pricing-options/cpm-auction-option.json +++ b/schemas/cache/pricing-options/cpm-auction-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per Mille (cost per 1,000 impressions) with auction-based pricing - common for programmatic/non-guaranteed inventory", "properties": { "currency": { diff --git a/schemas/cache/pricing-options/cpm-fixed-option.json b/schemas/cache/pricing-options/cpm-fixed-option.json index ef9656634..279b43612 100644 --- a/schemas/cache/pricing-options/cpm-fixed-option.json +++ b/schemas/cache/pricing-options/cpm-fixed-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per Mille (cost per 1,000 impressions) with guaranteed fixed rate - common for direct/guaranteed deals", "properties": { "currency": { diff --git a/schemas/cache/pricing-options/cpp-option.json b/schemas/cache/pricing-options/cpp-option.json index 20f5cb4c3..5be3c6a6a 100644 --- a/schemas/cache/pricing-options/cpp-option.json +++ b/schemas/cache/pricing-options/cpp-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per Point (Gross Rating Point) fixed-rate pricing for TV and audio campaigns requiring demographic measurement", "properties": { "currency": { @@ -25,7 +25,7 @@ "type": "number" }, "parameters": { - "additionalProperties": false, + "additionalProperties": true, "description": "CPP-specific parameters for demographic targeting and GRP requirements", "properties": { "demographic": { diff --git a/schemas/cache/pricing-options/cpv-option.json b/schemas/cache/pricing-options/cpv-option.json index 5d4535c38..e2fecdf95 100644 --- a/schemas/cache/pricing-options/cpv-option.json +++ b/schemas/cache/pricing-options/cpv-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Cost Per View (at publisher-defined threshold) fixed-rate pricing for video/audio", "properties": { "currency": { @@ -25,7 +25,7 @@ "type": "number" }, "parameters": { - "additionalProperties": false, + "additionalProperties": true, "description": "CPV-specific parameters defining the view threshold", "properties": { "view_threshold": { @@ -37,7 +37,7 @@ "type": "number" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Time-based view threshold for CPV pricing", "properties": { "duration_seconds": { diff --git a/schemas/cache/pricing-options/flat-rate-option.json b/schemas/cache/pricing-options/flat-rate-option.json index 66e88202c..a532550ce 100644 --- a/schemas/cache/pricing-options/flat-rate-option.json +++ b/schemas/cache/pricing-options/flat-rate-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Flat rate pricing for DOOH, sponsorships, and time-based campaigns - fixed cost regardless of delivery volume", "properties": { "currency": { @@ -25,7 +25,7 @@ "type": "number" }, "parameters": { - "additionalProperties": false, + "additionalProperties": true, "description": "Flat rate parameters for DOOH and time-based campaigns", "properties": { "daypart": { diff --git a/schemas/cache/pricing-options/vcpm-auction-option.json b/schemas/cache/pricing-options/vcpm-auction-option.json index 4243104c6..c2f03350f 100644 --- a/schemas/cache/pricing-options/vcpm-auction-option.json +++ b/schemas/cache/pricing-options/vcpm-auction-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) with auction-based pricing - impressions meeting MRC viewability standard (50% pixels in-view for 1 second for display, 2 seconds for video)", "properties": { "currency": { diff --git a/schemas/cache/pricing-options/vcpm-fixed-option.json b/schemas/cache/pricing-options/vcpm-fixed-option.json index c95bccca8..b811c9321 100644 --- a/schemas/cache/pricing-options/vcpm-fixed-option.json +++ b/schemas/cache/pricing-options/vcpm-fixed-option.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) with guaranteed fixed rate - impressions meeting MRC viewability standard (50% pixels in-view for 1 second for display, 2 seconds for video)", "properties": { "currency": { diff --git a/schemas/cache/protocols/adcp-extension.json b/schemas/cache/protocols/adcp-extension.json index 759bd1b18..a5dbab166 100644 --- a/schemas/cache/protocols/adcp-extension.json +++ b/schemas/cache/protocols/adcp-extension.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Extension metadata for agent cards (MCP and A2A) declaring AdCP version and supported protocol domains", "properties": { "adcp_version": { diff --git a/schemas/cache/signals/activate-signal-request.json b/schemas/cache/signals/activate-signal-request.json index 24f1da469..49d89f43a 100644 --- a/schemas/cache/signals/activate-signal-request.json +++ b/schemas/cache/signals/activate-signal-request.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for activating a signal on a specific deployment target", "properties": { "context": { diff --git a/schemas/cache/signals/activate-signal-response.json b/schemas/cache/signals/activate-signal-response.json index c76b35a95..4c09e523a 100644 --- a/schemas/cache/signals/activate-signal-response.json +++ b/schemas/cache/signals/activate-signal-response.json @@ -3,7 +3,7 @@ "description": "Response payload for activate_signal task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the signal is either fully activated or not activated at all.", "oneOf": [ { - "additionalProperties": false, + "additionalProperties": true, "description": "Success response - signal activated successfully to one or more deployment targets", "not": { "required": [ @@ -32,7 +32,7 @@ "type": "object" }, { - "additionalProperties": false, + "additionalProperties": true, "description": "Error response - operation failed, signal not activated", "not": { "required": [ diff --git a/schemas/cache/signals/get-signals-request.json b/schemas/cache/signals/get-signals-request.json index 6076a29ed..08a552112 100644 --- a/schemas/cache/signals/get-signals-request.json +++ b/schemas/cache/signals/get-signals-request.json @@ -1,13 +1,13 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Request parameters for discovering signals based on description", "properties": { "context": { "$ref": "../core/context.json" }, "deliver_to": { - "additionalProperties": false, + "additionalProperties": true, "description": "Deployment targets where signals need to be activated", "properties": { "countries": { diff --git a/schemas/cache/signals/get-signals-response.json b/schemas/cache/signals/get-signals-response.json index 61402235c..30089b52d 100644 --- a/schemas/cache/signals/get-signals-response.json +++ b/schemas/cache/signals/get-signals-response.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, + "additionalProperties": true, "description": "Response payload for get_signals task", "properties": { "context": { @@ -19,7 +19,7 @@ "signals": { "description": "Array of matching signals", "items": { - "additionalProperties": false, + "additionalProperties": true, "properties": { "coverage_percentage": { "description": "Percentage of audience coverage", @@ -47,7 +47,7 @@ "type": "string" }, "pricing": { - "additionalProperties": false, + "additionalProperties": true, "description": "Pricing information", "properties": { "cpm": { diff --git a/scripts/sync_schemas.py b/scripts/sync_schemas.py index 267e5e4ff..2f00284d5 100755 --- a/scripts/sync_schemas.py +++ b/scripts/sync_schemas.py @@ -34,7 +34,7 @@ def get_target_adcp_version() -> str: Returns: AdCP version string (e.g., "v1", "v2") """ - version_file = Path(__file__).parent.parent / "ADCP_VERSION" + version_file = Path(__file__).parent.parent / "src" / "adcp" / "ADCP_VERSION" if version_file.exists(): return version_file.read_text().strip() return "v1" # Fallback diff --git a/src/adcp/ADCP_VERSION b/src/adcp/ADCP_VERSION index 437459cd9..e70b4523a 100644 --- a/src/adcp/ADCP_VERSION +++ b/src/adcp/ADCP_VERSION @@ -1 +1 @@ -2.5.0 +2.6.0 diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index f828abab7..e49ff2ad9 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -57,7 +57,20 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) - +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.update_media_buy_request import ( + Packages, + Packages1, +) # Response types from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, @@ -67,29 +80,15 @@ MediaBuyDelivery, NotificationType, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.update_media_buy_request import ( - Packages, - Packages1, -) def _apply_coercion() -> None: diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index a555dc4c6..62b342023 100644 --- a/src/adcp/types/_generated.py +++ b/src/adcp/types/_generated.py @@ -10,7 +10,7 @@ DO NOT EDIT MANUALLY. Generated from: https://github.com/adcontextprotocol/adcp/tree/main/schemas -Generation date: 2025-12-18 20:00:25 UTC +Generation date: 2026-01-08 19:25:24 UTC """ # ruff: noqa: E501, I001 @@ -75,6 +75,9 @@ from adcp.types.generated_poc.core.error import Error from adcp.types.generated_poc.core.ext import ExtensionObject from adcp.types.generated_poc.core.format import ( + Asset2, + Assets, + Assets1, AssetsRequired, AssetsRequired1, Dimensions, @@ -399,9 +402,12 @@ "AdvertisingChannels", "AggregatedTotals", "Asset", + "Asset2", "AssetContentType", "AssetSelectors", "AssetType", + "Assets", + "Assets1", "AssetsRequired", "AssetsRequired1", "AssignedPackage", diff --git a/src/adcp/types/generated_poc/adagents.py b/src/adcp/types/generated_poc/adagents.py index 097019219..e5dfea042 100644 --- a/src/adcp/types/generated_poc/adagents.py +++ b/src/adcp/types/generated_poc/adagents.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: adagents.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class AuthorizedSalesAgents1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) field_schema: Annotated[ str | None, @@ -34,7 +34,7 @@ class AuthorizedSalesAgents1(AdCPBaseModel): class Contact(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) domain: Annotated[ str | None, @@ -79,7 +79,7 @@ class Contact(AdCPBaseModel): class Tags(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) description: Annotated[str, Field(description='Description of what this tag represents')] name: Annotated[str, Field(description='Human-readable name for this tag')] @@ -87,7 +87,7 @@ class Tags(AdCPBaseModel): class AuthorizedAgents(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) authorization_type: Annotated[ Literal['property_ids'], @@ -113,7 +113,7 @@ class AuthorizedAgents(AdCPBaseModel): class AuthorizedAgents1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) authorization_type: Annotated[ Literal['property_tags'], @@ -139,7 +139,7 @@ class AuthorizedAgents1(AdCPBaseModel): class AuthorizedAgents3(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) authorization_type: Annotated[ Literal['publisher_properties'], @@ -167,7 +167,7 @@ class AuthorizedAgents3(AdCPBaseModel): class AuthorizedAgents2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) authorization_type: Annotated[ Literal['inline_properties'], @@ -193,7 +193,7 @@ class AuthorizedAgents2(AdCPBaseModel): class AuthorizedSalesAgents2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) field_schema: Annotated[ str | None, @@ -238,12 +238,12 @@ class AuthorizedSalesAgents(RootModel[AuthorizedSalesAgents1 | AuthorizedSalesAg description='Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.', examples=[ { - '$schema': '/schemas/latest/adagents.json', + '$schema': '/schemas/2.6.0/adagents.json', 'authoritative_location': 'https://cdn.example.com/adagents/v2/adagents.json', 'last_updated': '2025-01-15T10:00:00Z', }, { - '$schema': '/schemas/latest/adagents.json', + '$schema': '/schemas/2.6.0/adagents.json', 'authorized_agents': [ { 'authorization_type': 'property_tags', @@ -269,7 +269,7 @@ class AuthorizedSalesAgents(RootModel[AuthorizedSalesAgents1 | AuthorizedSalesAg }, }, { - '$schema': '/schemas/latest/adagents.json', + '$schema': '/schemas/2.6.0/adagents.json', 'authorized_agents': [ { 'authorization_type': 'property_tags', @@ -334,7 +334,7 @@ class AuthorizedSalesAgents(RootModel[AuthorizedSalesAgents1 | AuthorizedSalesAg }, }, { - '$schema': '/schemas/latest/adagents.json', + '$schema': '/schemas/2.6.0/adagents.json', 'authorized_agents': [ { 'authorization_type': 'property_tags', @@ -362,7 +362,7 @@ class AuthorizedSalesAgents(RootModel[AuthorizedSalesAgents1 | AuthorizedSalesAg }, }, { - '$schema': '/schemas/latest/adagents.json', + '$schema': '/schemas/2.6.0/adagents.json', 'authorized_agents': [ { 'authorization_type': 'publisher_properties', diff --git a/src/adcp/types/generated_poc/core/activation_key.py b/src/adcp/types/generated_poc/core/activation_key.py index effa4ae03..b85093741 100644 --- a/src/adcp/types/generated_poc/core/activation_key.py +++ b/src/adcp/types/generated_poc/core/activation_key.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/activation_key.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class ActivationKey1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) segment_id: Annotated[ str, @@ -23,7 +23,7 @@ class ActivationKey1(AdCPBaseModel): class ActivationKey2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) key: Annotated[str, Field(description='The targeting parameter key')] type: Annotated[Literal['key_value'], Field(description='Key-value pair based targeting')] diff --git a/src/adcp/types/generated_poc/core/assets/audio_asset.py b/src/adcp/types/generated_poc/core/assets/audio_asset.py index d5bdb7709..33a0ca656 100644 --- a/src/adcp/types/generated_poc/core/assets/audio_asset.py +++ b/src/adcp/types/generated_poc/core/assets/audio_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/audio_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class AudioAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bitrate_kbps: Annotated[ int | None, Field(description='Audio bitrate in kilobits per second', ge=1) diff --git a/src/adcp/types/generated_poc/core/assets/css_asset.py b/src/adcp/types/generated_poc/core/assets/css_asset.py index 0b1d0a836..91e797ae6 100644 --- a/src/adcp/types/generated_poc/core/assets/css_asset.py +++ b/src/adcp/types/generated_poc/core/assets/css_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/css_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class CssAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) content: Annotated[str, Field(description='CSS content')] media: Annotated[ diff --git a/src/adcp/types/generated_poc/core/assets/daast_asset.py b/src/adcp/types/generated_poc/core/assets/daast_asset.py index c9c9a5be3..4b5960333 100644 --- a/src/adcp/types/generated_poc/core/assets/daast_asset.py +++ b/src/adcp/types/generated_poc/core/assets/daast_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/daast_asset.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class DaastAsset1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) companion_ads: Annotated[ bool | None, Field(description='Whether companion display ads are included') @@ -39,7 +39,7 @@ class DaastAsset1(AdCPBaseModel): class DaastAsset2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) companion_ads: Annotated[ bool | None, Field(description='Whether companion display ads are included') diff --git a/src/adcp/types/generated_poc/core/assets/html_asset.py b/src/adcp/types/generated_poc/core/assets/html_asset.py index aebc86fef..f953a6dbf 100644 --- a/src/adcp/types/generated_poc/core/assets/html_asset.py +++ b/src/adcp/types/generated_poc/core/assets/html_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/html_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class HtmlAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) content: Annotated[str, Field(description='HTML content')] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None diff --git a/src/adcp/types/generated_poc/core/assets/image_asset.py b/src/adcp/types/generated_poc/core/assets/image_asset.py index 7ce673795..1af037fc0 100644 --- a/src/adcp/types/generated_poc/core/assets/image_asset.py +++ b/src/adcp/types/generated_poc/core/assets/image_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/image_asset.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class ImageAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) alt_text: Annotated[str | None, Field(description='Alternative text for accessibility')] = None format: Annotated[ diff --git a/src/adcp/types/generated_poc/core/assets/javascript_asset.py b/src/adcp/types/generated_poc/core/assets/javascript_asset.py index c846dedb7..a382ad05b 100644 --- a/src/adcp/types/generated_poc/core/assets/javascript_asset.py +++ b/src/adcp/types/generated_poc/core/assets/javascript_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/javascript_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class JavascriptAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) content: Annotated[str, Field(description='JavaScript content')] module_type: Annotated[ diff --git a/src/adcp/types/generated_poc/core/assets/text_asset.py b/src/adcp/types/generated_poc/core/assets/text_asset.py index 5763b4748..f16ccfa36 100644 --- a/src/adcp/types/generated_poc/core/assets/text_asset.py +++ b/src/adcp/types/generated_poc/core/assets/text_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/text_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class TextAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) content: Annotated[str, Field(description='Text content')] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( diff --git a/src/adcp/types/generated_poc/core/assets/url_asset.py b/src/adcp/types/generated_poc/core/assets/url_asset.py index cb4c95d07..7969e41ff 100644 --- a/src/adcp/types/generated_poc/core/assets/url_asset.py +++ b/src/adcp/types/generated_poc/core/assets/url_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/url_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class UrlAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) description: Annotated[ str | None, Field(description='Description of what this URL points to') diff --git a/src/adcp/types/generated_poc/core/assets/vast_asset.py b/src/adcp/types/generated_poc/core/assets/vast_asset.py index 71fa502cf..dcb242201 100644 --- a/src/adcp/types/generated_poc/core/assets/vast_asset.py +++ b/src/adcp/types/generated_poc/core/assets/vast_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/vast_asset.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class VastAsset1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) delivery_type: Annotated[ Literal['url'], @@ -40,7 +40,7 @@ class VastAsset1(AdCPBaseModel): class VastAsset2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) content: Annotated[str, Field(description='Inline VAST XML content')] delivery_type: Annotated[ diff --git a/src/adcp/types/generated_poc/core/assets/video_asset.py b/src/adcp/types/generated_poc/core/assets/video_asset.py index 774c37ff0..47fbcc674 100644 --- a/src/adcp/types/generated_poc/core/assets/video_asset.py +++ b/src/adcp/types/generated_poc/core/assets/video_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/video_asset.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class VideoAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bitrate_kbps: Annotated[ int | None, Field(description='Video bitrate in kilobits per second', ge=1) diff --git a/src/adcp/types/generated_poc/core/assets/webhook_asset.py b/src/adcp/types/generated_poc/core/assets/webhook_asset.py index 3d218b83c..d68f20eab 100644 --- a/src/adcp/types/generated_poc/core/assets/webhook_asset.py +++ b/src/adcp/types/generated_poc/core/assets/webhook_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/webhook_asset.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -26,7 +26,7 @@ class Security(AdCPBaseModel): class WebhookAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) method: Annotated[http_method.HttpMethod | None, Field(description='HTTP method')] = ( http_method.HttpMethod.POST diff --git a/src/adcp/types/generated_poc/core/brand_manifest.py b/src/adcp/types/generated_poc/core/brand_manifest.py index 2a1f9e30c..d009a7780 100644 --- a/src/adcp/types/generated_poc/core/brand_manifest.py +++ b/src/adcp/types/generated_poc/core/brand_manifest.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/brand_manifest.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class Asset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_id: Annotated[str, Field(description='Unique identifier for this asset')] asset_type: Annotated[ @@ -130,7 +130,7 @@ class UpdateFrequency(Enum): class ProductCatalog(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) categories: Annotated[ list[str] | None, @@ -150,7 +150,7 @@ class ProductCatalog(AdCPBaseModel): class BrandManifest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assets: Annotated[ list[Asset] | None, diff --git a/src/adcp/types/generated_poc/core/context.py b/src/adcp/types/generated_poc/core/context.py index 6af67cbe7..5a98be669 100644 --- a/src/adcp/types/generated_poc/core/context.py +++ b/src/adcp/types/generated_poc/core/context.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/context.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -9,7 +9,6 @@ class ContextObject(AdCPBaseModel): - pass model_config = ConfigDict( extra='allow', ) diff --git a/src/adcp/types/generated_poc/core/creative_asset.py b/src/adcp/types/generated_poc/core/creative_asset.py index cc0bd3f96..fc1239112 100644 --- a/src/adcp/types/generated_poc/core/creative_asset.py +++ b/src/adcp/types/generated_poc/core/creative_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_asset.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -27,7 +27,7 @@ class Input(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context_description: Annotated[ str | None, @@ -41,7 +41,7 @@ class Input(AdCPBaseModel): class CreativeAsset(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) approved: Annotated[ bool | None, diff --git a/src/adcp/types/generated_poc/core/creative_assignment.py b/src/adcp/types/generated_poc/core/creative_assignment.py index fcfdef567..ed6aa184e 100644 --- a/src/adcp/types/generated_poc/core/creative_assignment.py +++ b/src/adcp/types/generated_poc/core/creative_assignment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_assignment.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class CreativeAssignment(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) creative_id: Annotated[str, Field(description='Unique identifier for the creative')] placement_ids: Annotated[ diff --git a/src/adcp/types/generated_poc/core/creative_filters.py b/src/adcp/types/generated_poc/core/creative_filters.py index 9bd6a5c81..030382bbf 100644 --- a/src/adcp/types/generated_poc/core/creative_filters.py +++ b/src/adcp/types/generated_poc/core/creative_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_filters.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class CreativeFilters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assigned_to_package: Annotated[ str | None, Field(description='Filter creatives assigned to this specific package') diff --git a/src/adcp/types/generated_poc/core/creative_manifest.py b/src/adcp/types/generated_poc/core/creative_manifest.py index 5f30d13b9..ef22303a3 100644 --- a/src/adcp/types/generated_poc/core/creative_manifest.py +++ b/src/adcp/types/generated_poc/core/creative_manifest.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_manifest.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -29,7 +29,7 @@ class CreativeManifest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assets: Annotated[ dict[ diff --git a/src/adcp/types/generated_poc/core/creative_policy.py b/src/adcp/types/generated_poc/core/creative_policy.py index 646852099..d3a38cb9a 100644 --- a/src/adcp/types/generated_poc/core/creative_policy.py +++ b/src/adcp/types/generated_poc/core/creative_policy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_policy.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class CreativePolicy(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) co_branding: Annotated[ co_branding_requirement.CoBrandingRequirement, Field(description='Co-branding requirement') diff --git a/src/adcp/types/generated_poc/core/delivery_metrics.py b/src/adcp/types/generated_poc/core/delivery_metrics.py index 2d3a6564c..33cdd8934 100644 --- a/src/adcp/types/generated_poc/core/delivery_metrics.py +++ b/src/adcp/types/generated_poc/core/delivery_metrics.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/delivery_metrics.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class VenueBreakdownItem(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) impressions: Annotated[int, Field(description='Impressions delivered at this venue', ge=0)] loop_plays: Annotated[int | None, Field(description='Loop plays at this venue', ge=0)] = None @@ -29,7 +29,7 @@ class VenueBreakdownItem(AdCPBaseModel): class DoohMetrics(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) calculation_notes: Annotated[ str | None, Field(description='Explanation of how DOOH impressions were calculated') diff --git a/src/adcp/types/generated_poc/core/deployment.py b/src/adcp/types/generated_poc/core/deployment.py index 3af77f897..b3c05447f 100644 --- a/src/adcp/types/generated_poc/core/deployment.py +++ b/src/adcp/types/generated_poc/core/deployment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/deployment.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class Deployment1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) account: Annotated[str | None, Field(description='Account identifier if applicable')] = None activation_key: Annotated[ @@ -46,7 +46,7 @@ class Deployment1(AdCPBaseModel): class Deployment2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) account: Annotated[str | None, Field(description='Account identifier if applicable')] = None activation_key: Annotated[ diff --git a/src/adcp/types/generated_poc/core/destination.py b/src/adcp/types/generated_poc/core/destination.py index ab1d1c5a6..2a811ba31 100644 --- a/src/adcp/types/generated_poc/core/destination.py +++ b/src/adcp/types/generated_poc/core/destination.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/destination.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class Destination1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) account: Annotated[ str | None, Field(description='Optional account identifier on the platform') @@ -29,7 +29,7 @@ class Destination1(AdCPBaseModel): class Destination2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) account: Annotated[ str | None, Field(description='Optional account identifier on the agent') diff --git a/src/adcp/types/generated_poc/core/error.py b/src/adcp/types/generated_poc/core/error.py index bcdc0d849..13c448412 100644 --- a/src/adcp/types/generated_poc/core/error.py +++ b/src/adcp/types/generated_poc/core/error.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/error.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,12 +12,12 @@ class Error(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) code: Annotated[str, Field(description='Error code for programmatic handling')] - details: Annotated[Any | None, Field(description='Additional task-specific error details')] = ( - None - ) + details: Annotated[ + dict[str, Any] | None, Field(description='Additional task-specific error details') + ] = None field: Annotated[ str | None, Field(description="Field path associated with the error (e.g., 'packages[0].targeting')"), diff --git a/src/adcp/types/generated_poc/core/ext.py b/src/adcp/types/generated_poc/core/ext.py index 78c4d8d6b..20b2ccc5c 100644 --- a/src/adcp/types/generated_poc/core/ext.py +++ b/src/adcp/types/generated_poc/core/ext.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/ext.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -9,7 +9,6 @@ class ExtensionObject(AdCPBaseModel): - pass model_config = ConfigDict( extra='allow', ) diff --git a/src/adcp/types/generated_poc/core/format.py b/src/adcp/types/generated_poc/core/format.py index e6fa88723..067f33349 100644 --- a/src/adcp/types/generated_poc/core/format.py +++ b/src/adcp/types/generated_poc/core/format.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/format.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -13,6 +13,84 @@ from . import format_id as format_id_1 +class Assets(AdCPBaseModel): + asset_id: Annotated[ + str, + Field( + description='Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object.' + ), + ] + asset_role: Annotated[ + str | None, + Field( + description="Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo', 'third_party_tracking'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." + ), + ] = None + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] + item_type: Annotated[ + Literal['individual'], + Field(description='Discriminator indicating this is an individual asset'), + ] + required: Annotated[ + bool, + Field( + description='Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.' + ), + ] + requirements: Annotated[ + dict[str, Any] | None, + Field( + description='Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' + ), + ] = None + + +class Asset(AdCPBaseModel): + asset_id: Annotated[str, Field(description='Identifier for this asset within the group')] + asset_role: Annotated[ + str | None, + Field( + description="Optional descriptive label for this asset's purpose. Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." + ), + ] = None + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] + required: Annotated[ + bool, + Field(description='Whether this asset is required within each repetition of the group'), + ] + requirements: Annotated[ + dict[str, Any] | None, + Field( + description='Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' + ), + ] = None + + +class Assets1(AdCPBaseModel): + asset_group_id: Annotated[ + str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") + ] + assets: Annotated[list[Asset], Field(description='Assets within each repetition of this group')] + item_type: Annotated[ + Literal['repeatable_group'], + Field(description='Discriminator indicating this is a repeatable asset group'), + ] + max_count: Annotated[int, Field(description='Maximum number of repetitions allowed', ge=1)] + min_count: Annotated[ + int, + Field( + description='Minimum number of repetitions required (if group is required) or allowed (if optional)', + ge=0, + ), + ] + required: Annotated[ + bool, + Field( + description='Whether this asset group is required. If true, at least min_count repetitions must be provided.' + ), + ] + + class AssetsRequired(AdCPBaseModel): asset_id: Annotated[ str, @@ -40,7 +118,7 @@ class AssetsRequired(AdCPBaseModel): ] = None -class Asset(AdCPBaseModel): +class Asset2(AdCPBaseModel): asset_id: Annotated[str, Field(description='Identifier for this asset within the group')] asset_role: Annotated[ str | None, @@ -64,7 +142,9 @@ class AssetsRequired1(AdCPBaseModel): asset_group_id: Annotated[ str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] - assets: Annotated[list[Asset], Field(description='Assets within each repetition of this group')] + assets: Annotated[ + list[Asset2], Field(description='Assets within each repetition of this group') + ] item_type: Annotated[ Literal['repeatable_group'], Field(description='Discriminator indicating this is a repeatable asset group'), @@ -146,7 +226,7 @@ class Renders1(AdCPBaseModel): class FormatCard(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, @@ -162,7 +242,7 @@ class FormatCard(AdCPBaseModel): class FormatCardDetailed(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, @@ -180,7 +260,7 @@ class FormatCardDetailed(AdCPBaseModel): class Format(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) accepts_parameters: Annotated[ list[format_id_parameter.FormatIdParameter] | None, @@ -188,10 +268,16 @@ class Format(AdCPBaseModel): description='List of parameters this format accepts in format_id. Template formats define which parameters (dimensions, duration, etc.) can be specified when instantiating the format. Empty or omitted means this is a concrete format with fixed parameters.' ), ] = None + assets: Annotated[ + list[Assets | Assets1] | None, + Field( + description="Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. This field replaces the deprecated 'assets_required' and enables full asset discovery for buyers and AI agents." + ), + ] = None assets_required: Annotated[ list[AssetsRequired | AssetsRequired1] | None, Field( - description='Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames).' + description="DEPRECATED: Use 'assets' instead. Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames). This field is maintained for backward compatibility; new implementations should use 'assets' with the 'required' boolean on each asset." ), ] = None delivery: Annotated[ diff --git a/src/adcp/types/generated_poc/core/format_id.py b/src/adcp/types/generated_poc/core/format_id.py index 92741534b..d38bda833 100644 --- a/src/adcp/types/generated_poc/core/format_id.py +++ b/src/adcp/types/generated_poc/core/format_id.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/format_id.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class FormatId(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) agent_url: Annotated[ AnyUrl, diff --git a/src/adcp/types/generated_poc/core/frequency_cap.py b/src/adcp/types/generated_poc/core/frequency_cap.py index cc9a749cf..02d931f17 100644 --- a/src/adcp/types/generated_poc/core/frequency_cap.py +++ b/src/adcp/types/generated_poc/core/frequency_cap.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/frequency_cap.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class FrequencyCap(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) suppress_minutes: Annotated[ float, Field(description='Minutes to suppress after impression', ge=0.0) diff --git a/src/adcp/types/generated_poc/core/measurement.py b/src/adcp/types/generated_poc/core/measurement.py index e167e8308..a45cc8e0b 100644 --- a/src/adcp/types/generated_poc/core/measurement.py +++ b/src/adcp/types/generated_poc/core/measurement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/measurement.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class Measurement(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) attribution: Annotated[ str, diff --git a/src/adcp/types/generated_poc/core/media_buy.py b/src/adcp/types/generated_poc/core/media_buy.py index bb7046558..1697ef172 100644 --- a/src/adcp/types/generated_poc/core/media_buy.py +++ b/src/adcp/types/generated_poc/core/media_buy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/media_buy.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class MediaBuy(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference identifier for this media buy") diff --git a/src/adcp/types/generated_poc/core/package.py b/src/adcp/types/generated_poc/core/package.py index 1dd81db62..658e4c349 100644 --- a/src/adcp/types/generated_poc/core/package.py +++ b/src/adcp/types/generated_poc/core/package.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/package.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Package(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bid_price: Annotated[ float | None, diff --git a/src/adcp/types/generated_poc/core/performance_feedback.py b/src/adcp/types/generated_poc/core/performance_feedback.py index 34b998ef5..0dbcd29e1 100644 --- a/src/adcp/types/generated_poc/core/performance_feedback.py +++ b/src/adcp/types/generated_poc/core/performance_feedback.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/performance_feedback.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class MeasurementPeriod(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) end: Annotated[ AwareDatetime, Field(description='ISO 8601 end timestamp for measurement period') @@ -35,7 +35,7 @@ class Status(Enum): class PerformanceFeedback(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) applied_at: Annotated[ AwareDatetime | None, diff --git a/src/adcp/types/generated_poc/core/placement.py b/src/adcp/types/generated_poc/core/placement.py index 81efcb4c2..76add5bbf 100644 --- a/src/adcp/types/generated_poc/core/placement.py +++ b/src/adcp/types/generated_poc/core/placement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/placement.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class Placement(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) description: Annotated[ str | None, Field(description='Detailed description of where and how the placement appears') diff --git a/src/adcp/types/generated_poc/core/product.py b/src/adcp/types/generated_poc/core/product.py index e767c4e84..c89a05586 100644 --- a/src/adcp/types/generated_poc/core/product.py +++ b/src/adcp/types/generated_poc/core/product.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -35,7 +35,7 @@ class DeliveryMeasurement(AdCPBaseModel): class ProductCard(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, @@ -51,7 +51,7 @@ class ProductCard(AdCPBaseModel): class ProductCardDetailed(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, @@ -69,7 +69,7 @@ class ProductCardDetailed(AdCPBaseModel): class Product(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) brief_relevance: Annotated[ str | None, diff --git a/src/adcp/types/generated_poc/core/product_filters.py b/src/adcp/types/generated_poc/core/product_filters.py index 7efe29437..b63f935cf 100644 --- a/src/adcp/types/generated_poc/core/product_filters.py +++ b/src/adcp/types/generated_poc/core/product_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product_filters.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class BudgetRange(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, @@ -32,7 +32,7 @@ class BudgetRange(AdCPBaseModel): class BudgetRange1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, @@ -50,7 +50,7 @@ class Country(RootModel[str]): class ProductFilters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) budget_range: Annotated[ BudgetRange | BudgetRange1 | None, diff --git a/src/adcp/types/generated_poc/core/promoted_offerings.py b/src/adcp/types/generated_poc/core/promoted_offerings.py index 5039e65e9..ba031503e 100644 --- a/src/adcp/types/generated_poc/core/promoted_offerings.py +++ b/src/adcp/types/generated_poc/core/promoted_offerings.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/promoted_offerings.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -29,7 +29,7 @@ class AssetType(Enum): class AssetSelectors(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_types: Annotated[ list[AssetType] | None, Field(description="Filter by asset type (e.g., ['image', 'video'])") @@ -45,7 +45,7 @@ class AssetSelectors(AdCPBaseModel): class Offering(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assets: Annotated[ list[dict[str, Any]] | None, Field(description='Assets specific to this offering') @@ -60,7 +60,7 @@ class Offering(AdCPBaseModel): class PromotedOfferings(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_selectors: Annotated[ AssetSelectors | None, diff --git a/src/adcp/types/generated_poc/core/promoted_products.py b/src/adcp/types/generated_poc/core/promoted_products.py index a9846b11b..b3fa8d011 100644 --- a/src/adcp/types/generated_poc/core/promoted_products.py +++ b/src/adcp/types/generated_poc/core/promoted_products.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/promoted_products.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class PromotedProducts(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) manifest_category: Annotated[ str | None, diff --git a/src/adcp/types/generated_poc/core/property.py b/src/adcp/types/generated_poc/core/property.py index f59ea5a2d..deb01cf56 100644 --- a/src/adcp/types/generated_poc/core/property.py +++ b/src/adcp/types/generated_poc/core/property.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/property.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Identifier(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) type: Annotated[ identifier_types.PropertyIdentifierTypes, @@ -33,7 +33,7 @@ class Identifier(AdCPBaseModel): class Property(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) identifiers: Annotated[ list[Identifier], Field(description='Array of identifiers for this property', min_length=1) diff --git a/src/adcp/types/generated_poc/core/protocol_envelope.py b/src/adcp/types/generated_poc/core/protocol_envelope.py index c7f912f09..c32caac74 100644 --- a/src/adcp/types/generated_poc/core/protocol_envelope.py +++ b/src/adcp/types/generated_poc/core/protocol_envelope.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/protocol_envelope.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class ProtocolEnvelope(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context_id: Annotated[ str | None, diff --git a/src/adcp/types/generated_poc/core/publisher_property_selector.py b/src/adcp/types/generated_poc/core/publisher_property_selector.py index b0ed5b280..ce36f8bb2 100644 --- a/src/adcp/types/generated_poc/core/publisher_property_selector.py +++ b/src/adcp/types/generated_poc/core/publisher_property_selector.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/publisher_property_selector.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class PublisherPropertySelector1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) publisher_domain: Annotated[ str, @@ -33,7 +33,7 @@ class PublisherPropertySelector1(AdCPBaseModel): class PublisherPropertySelector2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) property_ids: Annotated[ list[property_id.PropertyId], @@ -54,7 +54,7 @@ class PublisherPropertySelector2(AdCPBaseModel): class PublisherPropertySelector3(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) property_tags: Annotated[ list[property_tag.PropertyTag], diff --git a/src/adcp/types/generated_poc/core/reporting_capabilities.py b/src/adcp/types/generated_poc/core/reporting_capabilities.py index 3f62a68dd..651b65147 100644 --- a/src/adcp/types/generated_poc/core/reporting_capabilities.py +++ b/src/adcp/types/generated_poc/core/reporting_capabilities.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/reporting_capabilities.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class ReportingCapabilities(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) available_metrics: Annotated[ list[available_metric.AvailableMetric], diff --git a/src/adcp/types/generated_poc/core/response.py b/src/adcp/types/generated_poc/core/response.py index 653925012..343adf1e2 100644 --- a/src/adcp/types/generated_poc/core/response.py +++ b/src/adcp/types/generated_poc/core/response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class ProtocolResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context_id: Annotated[str | None, Field(description='Session continuity identifier')] = None data: Annotated[ diff --git a/src/adcp/types/generated_poc/core/signal_filters.py b/src/adcp/types/generated_poc/core/signal_filters.py index cfe3951b2..142b28647 100644 --- a/src/adcp/types/generated_poc/core/signal_filters.py +++ b/src/adcp/types/generated_poc/core/signal_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_filters.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class SignalFilters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) catalog_types: Annotated[ list[signal_catalog_type.SignalCatalogType] | None, diff --git a/src/adcp/types/generated_poc/core/sub_asset.py b/src/adcp/types/generated_poc/core/sub_asset.py index 0b0e1d67d..469f176c6 100644 --- a/src/adcp/types/generated_poc/core/sub_asset.py +++ b/src/adcp/types/generated_poc/core/sub_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/sub_asset.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class SubAsset1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_id: Annotated[ str, Field(description='Unique identifier for the asset within the creative') @@ -32,7 +32,7 @@ class SubAsset1(AdCPBaseModel): class SubAsset2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_id: Annotated[ str, Field(description='Unique identifier for the asset within the creative') diff --git a/src/adcp/types/generated_poc/core/targeting.py b/src/adcp/types/generated_poc/core/targeting.py index 68f132f39..a382182ab 100644 --- a/src/adcp/types/generated_poc/core/targeting.py +++ b/src/adcp/types/generated_poc/core/targeting.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/targeting.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class GeoCountryAnyOfItem(RootModel[str]): class TargetingOverlay(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) axe_exclude_segment: Annotated[ str | None, Field(description='AXE segment ID to exclude from targeting') diff --git a/src/adcp/types/generated_poc/creative/list_creative_formats_request.py b/src/adcp/types/generated_poc/creative/list_creative_formats_request.py index 03e457178..2e9a62143 100644 --- a/src/adcp/types/generated_poc/creative/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/creative/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creative_formats_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -34,7 +34,7 @@ class Type(Enum): class ListCreativeFormatsRequestCreativeAgent(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_types: Annotated[ list[AssetType] | None, diff --git a/src/adcp/types/generated_poc/creative/list_creative_formats_response.py b/src/adcp/types/generated_poc/creative/list_creative_formats_response.py index a8264042d..5e85ce219 100644 --- a/src/adcp/types/generated_poc/creative/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/creative/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creative_formats_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -34,7 +34,7 @@ class CreativeAgent(AdCPBaseModel): class ListCreativeFormatsResponseCreativeAgent(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creative_agents: Annotated[ diff --git a/src/adcp/types/generated_poc/creative/preview_creative_request.py b/src/adcp/types/generated_poc/creative/preview_creative_request.py index f033d2db4..5b15d6a8b 100644 --- a/src/adcp/types/generated_poc/creative/preview_creative_request.py +++ b/src/adcp/types/generated_poc/creative/preview_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_creative_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class Input(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context_description: Annotated[ str | None, @@ -29,7 +29,7 @@ class Input(AdCPBaseModel): macros: Annotated[ dict[str, str] | None, Field( - description="Macro values to use for this preview. Supports all universal macros from the format's supported_macros list. See docs/media-buy/creatives/universal-macros.md for available macros." + description="Macro values to use for this preview. Supports all universal macros from the format's supported_macros list. See docs/creative/universal-macros.md for available macros." ), ] = None name: Annotated[ @@ -42,7 +42,7 @@ class Input(AdCPBaseModel): class Input2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context_description: Annotated[ str | None, @@ -56,7 +56,7 @@ class Input2(AdCPBaseModel): class PreviewCreativeRequest1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ @@ -92,7 +92,7 @@ class PreviewCreativeRequest1(AdCPBaseModel): class Request(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) creative_manifest: Annotated[ creative_manifest_1.CreativeManifest, @@ -118,7 +118,7 @@ class Request(AdCPBaseModel): class PreviewCreativeRequest2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/creative/preview_creative_response.py b/src/adcp/types/generated_poc/creative/preview_creative_response.py index 97e691bda..8a0282d90 100644 --- a/src/adcp/types/generated_poc/creative/preview_creative_response.py +++ b/src/adcp/types/generated_poc/creative/preview_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_creative_response.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -60,7 +60,7 @@ class Preview(AdCPBaseModel): class PreviewCreativeResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None expires_at: Annotated[ @@ -131,7 +131,7 @@ class Results1(AdCPBaseModel): class PreviewCreativeResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/creative/preview_render.py b/src/adcp/types/generated_poc/creative/preview_render.py index a6c85236b..f5c8ac78b 100644 --- a/src/adcp/types/generated_poc/creative/preview_render.py +++ b/src/adcp/types/generated_poc/creative/preview_render.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_render.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -35,7 +35,7 @@ class Embedding(AdCPBaseModel): class PreviewRender1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) dimensions: Annotated[ Dimensions | None, Field(description='Dimensions for this rendered piece') @@ -66,7 +66,7 @@ class PreviewRender1(AdCPBaseModel): class PreviewRender2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) dimensions: Annotated[ Dimensions | None, Field(description='Dimensions for this rendered piece') @@ -96,7 +96,7 @@ class PreviewRender2(AdCPBaseModel): class PreviewRender3(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) dimensions: Annotated[ Dimensions | None, Field(description='Dimensions for this rendered piece') diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_request.py b/src/adcp/types/generated_poc/media_buy/build_creative_request.py index 772c99adb..1b88ee972 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_request.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class BuildCreativeRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_response.py b/src/adcp/types/generated_poc/media_buy/build_creative_response.py index 1c26b0263..cb89baeab 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_response.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class BuildCreativeResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ @@ -31,7 +31,7 @@ class BuildCreativeResponse2(AdCPBaseModel): class BuildCreativeResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py index ec2aecff6..9c88a3b43 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_input_required.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class Reason(Enum): class CreateMediaBuyInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ 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 5635c3f3f..17cb9042d 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_submitted.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class CreateMediaBuySubmitted(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py index 79e4fc157..1c2b2e33f 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_working.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class CreateMediaBuyWorking(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py index 629b283e9..13830aba9 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_request.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -8,16 +8,37 @@ from typing import Annotated from adcp.types.base import AdCPBaseModel -from pydantic import AwareDatetime, ConfigDict, Field +from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field from ..core import brand_manifest_ref from ..core import context as context_1 from ..core import ext as ext_1 from ..core import start_timing -from ..core.push_notification_config import PushNotificationConfig +from ..enums import auth_scheme from . import package_request +class Authentication(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + credentials: Annotated[ + str, + Field( + description='Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.', + min_length=32, + ), + ] + schemes: Annotated[ + list[auth_scheme.AuthenticationScheme], + Field( + description="Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", + max_length=1, + min_length=1, + ), + ] + + class ReportingFrequency(Enum): hourly = 'hourly' daily = 'daily' @@ -36,7 +57,14 @@ class RequestedMetric(Enum): engagement_rate = 'engagement_rate' -class ReportingWebhook(PushNotificationConfig): +class ReportingWebhook(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + authentication: Annotated[ + Authentication, + Field(description='Authentication configuration for webhook delivery (A2A-compatible)'), + ] reporting_frequency: Annotated[ ReportingFrequency, Field( @@ -49,11 +77,19 @@ class ReportingWebhook(PushNotificationConfig): description="Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics." ), ] = None + token: Annotated[ + str | None, + Field( + description='Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.', + min_length=16, + ), + ] = None + url: Annotated[AnyUrl, Field(description='Webhook endpoint URL for reporting notifications')] class CreateMediaBuyRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) brand_manifest: Annotated[ brand_manifest_ref.BrandManifestReference, @@ -71,5 +107,10 @@ class CreateMediaBuyRequest(AdCPBaseModel): list[package_request.PackageRequest], Field(description='Array of package configurations') ] po_number: Annotated[str | None, Field(description='Purchase order number for tracking')] = None - reporting_webhook: ReportingWebhook | None = None + reporting_webhook: Annotated[ + ReportingWebhook | None, + Field( + description='Optional webhook configuration for automated reporting delivery. Combines push_notification_config structure with reporting-specific fields.' + ), + ] = None start_time: start_timing.StartTiming diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py index cbf359379..3e6b59cda 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class CreateMediaBuyResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ @@ -29,7 +29,7 @@ class CreateMediaBuyResponse2(AdCPBaseModel): class CreateMediaBuyResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[str, Field(description="Buyer's reference identifier for this media buy")] context: context_1.ContextObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py index 6dd71da7a..ba67080dc 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buy_delivery_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class GetMediaBuyDeliveryRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_refs: Annotated[ list[str] | None, Field(description='Array of buyer reference IDs to get delivery data for') diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py index 38394697b..467ecaa0a 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buy_delivery_response.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class AggregatedTotals(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) clicks: Annotated[ float | None, @@ -48,7 +48,7 @@ class DeliveryStatus(Enum): class DailyBreakdownItem(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) date: Annotated[str, Field(description='Date (YYYY-MM-DD)', pattern='^\\d{4}-\\d{2}-\\d{2}$')] impressions: Annotated[float, Field(description='Daily impressions', ge=0.0)] @@ -84,7 +84,7 @@ class NotificationType(Enum): class ReportingPeriod(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) end: Annotated[ AwareDatetime, @@ -139,7 +139,7 @@ class ByPackageItem(DeliveryMetrics): class MediaBuyDelivery(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference identifier for this media buy") @@ -176,7 +176,7 @@ class MediaBuyDelivery(AdCPBaseModel): class GetMediaBuyDeliveryResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) aggregated_totals: Annotated[ AggregatedTotals | None, diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py index c173bd852..3bf2f2e4d 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_input_required.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class Reason(Enum): class GetProductsInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py index f54963bdb..2502b6632 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_submitted.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class GetProductsSubmitted(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None estimated_completion: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py index e77495e42..07d1b15f6 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_working.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class GetProductsWorking(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/get_products_request.py b/src/adcp/types/generated_poc/media_buy/get_products_request.py index 31576dcb9..aaf469c75 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_request.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class GetProductsRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) brand_manifest: Annotated[ brand_manifest_ref.BrandManifestReference | None, diff --git a/src/adcp/types/generated_poc/media_buy/get_products_response.py b/src/adcp/types/generated_poc/media_buy/get_products_response.py index 922679866..7e9fb0719 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class GetProductsResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py index e5ba6b200..a0b495ea7 100644 --- a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_authorized_properties_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -25,7 +25,7 @@ class PublisherDomain(RootModel[str]): class ListAuthorizedPropertiesRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py index 8c76959b9..e5e8cb3d4 100644 --- a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_authorized_properties_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -31,7 +31,7 @@ class PublisherDomain(RootModel[str]): class ListAuthorizedPropertiesResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) advertising_policies: Annotated[ str | None, diff --git a/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py b/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py index 18b10952a..d50b4f66c 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creative_formats_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class ListCreativeFormatsRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) asset_types: Annotated[ list[asset_content_type.AssetContentType] | None, diff --git a/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py b/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py index 57a16b161..e60933f41 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creative_formats_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -34,7 +34,7 @@ class CreativeAgent(AdCPBaseModel): class ListCreativeFormatsResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creative_agents: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py index 8bd56f0a0..1e73a9c81 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creatives_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class FieldModel(Enum): creative_id = 'creative_id' name = 'name' - format = 'format' + format_ = 'format' status = 'status' created_date = 'created_date' updated_date = 'updated_date' @@ -31,7 +31,7 @@ class FieldModel(Enum): class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) limit: Annotated[ int | None, Field(description='Maximum number of creatives to return', ge=1, le=100) @@ -41,7 +41,7 @@ class Pagination(AdCPBaseModel): class Sort(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) direction: Annotated[ sort_direction.SortDirection | None, Field(description='Sort direction') @@ -53,7 +53,7 @@ class Sort(AdCPBaseModel): class ListCreativesRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/list_creatives_response.py b/src/adcp/types/generated_poc/media_buy/list_creatives_response.py index b34a72806..c1dc2cfe9 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creatives_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creatives_response.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -37,7 +37,7 @@ class Status(Enum): class AssignedPackage(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assigned_date: Annotated[AwareDatetime, Field(description='When this assignment was created')] package_id: Annotated[str, Field(description='Package identifier')] @@ -47,7 +47,7 @@ class AssignedPackage(AdCPBaseModel): class Assignments(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assigned_packages: Annotated[ list[AssignedPackage] | None, @@ -60,7 +60,7 @@ class Assignments(AdCPBaseModel): class Performance(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) clicks: Annotated[ int | None, Field(description='Total clicks across all assignments', ge=0) @@ -84,7 +84,7 @@ class Performance(AdCPBaseModel): class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) current_page: Annotated[ int | None, Field(description='Current page number (1-based)', ge=1) @@ -99,7 +99,7 @@ class Pagination(AdCPBaseModel): class StatusSummary(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) approved: Annotated[int | None, Field(description='Number of approved creatives', ge=0)] = None archived: Annotated[int | None, Field(description='Number of archived creatives', ge=0)] = None @@ -116,7 +116,7 @@ class SortApplied(AdCPBaseModel): class QuerySummary(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) filters_applied: Annotated[ list[str] | None, Field(description='List of filters that were applied to the query') @@ -135,7 +135,7 @@ class QuerySummary(AdCPBaseModel): class Creative(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assets: Annotated[ dict[ @@ -191,7 +191,7 @@ class Creative(AdCPBaseModel): class ListCreativesResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creatives: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/package_request.py b/src/adcp/types/generated_poc/media_buy/package_request.py index 6df35ead3..16c64ec60 100644 --- a/src/adcp/types/generated_poc/media_buy/package_request.py +++ b/src/adcp/types/generated_poc/media_buy/package_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/package_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class PackageRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bid_price: Annotated[ float | None, diff --git a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py index d32432524..0b98f46b4 100644 --- a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py +++ b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/provide_performance_feedback_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class MeasurementPeriod(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) end: Annotated[ AwareDatetime, Field(description='ISO 8601 end timestamp for measurement period') @@ -29,7 +29,7 @@ class MeasurementPeriod(AdCPBaseModel): class ProvidePerformanceFeedbackRequest1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference for the media buy", min_length=1) @@ -72,7 +72,7 @@ class ProvidePerformanceFeedbackRequest1(AdCPBaseModel): class ProvidePerformanceFeedbackRequest2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[ str, Field(description="Buyer's reference for the media buy", min_length=1) diff --git a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py index c3fe9a80d..c3d5a7829 100644 --- a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py +++ b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/provide_performance_feedback_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class ProvidePerformanceFeedbackResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None @@ -28,7 +28,7 @@ class ProvidePerformanceFeedbackResponse1(AdCPBaseModel): class ProvidePerformanceFeedbackResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py index b34fbad1c..4b07b57ac 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_input_required.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class Reason(Enum): class SyncCreativesInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py index 4458b6e0b..6143049e5 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_submitted.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class SyncCreativesSubmitted(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py index bca867c47..c37cf5df6 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_working.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class SyncCreativesWorking(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creatives_processed: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py index 7af2378fb..38d1730e2 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_request.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class SyncCreativesRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) assignments: Annotated[ dict[str, list[str]] | None, diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py index 0f9334616..62b64ef60 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Creative(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) action: Annotated[ creative_action.CreativeAction, Field(description='Action taken for this creative') @@ -65,7 +65,7 @@ class Creative(AdCPBaseModel): class SyncCreativesResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None creatives: Annotated[ @@ -82,7 +82,7 @@ class SyncCreativesResponse1(AdCPBaseModel): class SyncCreativesResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py index aa5a1a40f..424db6456 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_input_required.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -21,7 +21,7 @@ class Reason(Enum): class UpdateMediaBuyInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py index bee573cdc..406b463b5 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_submitted.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class UpdateMediaBuySubmitted(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py index 9b332c56a..5d394d510 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_working.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class UpdateMediaBuyWorking(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py index 966842864..a66ad56e1 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_request.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class Packages(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bid_price: Annotated[ float | None, @@ -66,7 +66,7 @@ class Packages(AdCPBaseModel): class Packages1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) bid_price: Annotated[ float | None, @@ -113,7 +113,7 @@ class Packages1(AdCPBaseModel): class UpdateMediaBuyRequest1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference for the media buy to update") @@ -148,7 +148,7 @@ class UpdateMediaBuyRequest1(AdCPBaseModel): class UpdateMediaBuyRequest2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) buyer_ref: Annotated[str, Field(description="Buyer's reference for the media buy to update")] context: context_1.ContextObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py index 2cc4beab7..35432c686 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_response.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class UpdateMediaBuyResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ @@ -29,7 +29,7 @@ class UpdateMediaBuyResponse2(AdCPBaseModel): class UpdateMediaBuyResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) affected_packages: Annotated[ list[package.Package] | None, diff --git a/src/adcp/types/generated_poc/pricing_options/cpc_option.py b/src/adcp/types/generated_poc/pricing_options/cpc_option.py index da0191721..9f9483b0e 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpc_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpc_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpc_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class CpcPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py index e5cea2ead..abe88f5ae 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpcv_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class CpcvPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py index a779d1e47..e68551436 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpm_auction_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -25,7 +25,7 @@ class PriceGuidance(AdCPBaseModel): class CpmAuctionPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py index 5ad45fe52..fa0b81c3a 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpm_fixed_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class CpmFixedRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/cpp_option.py b/src/adcp/types/generated_poc/pricing_options/cpp_option.py index de936040b..8cc2bffc4 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpp_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpp_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpp_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) demographic: Annotated[ str, @@ -29,7 +29,7 @@ class Parameters(AdCPBaseModel): class CppPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/cpv_option.py b/src/adcp/types/generated_poc/pricing_options/cpv_option.py index f351736bc..24a72d734 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpv_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -23,7 +23,7 @@ class ViewThreshold(RootModel[float]): class ViewThreshold1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) duration_seconds: Annotated[ int, @@ -36,14 +36,14 @@ class ViewThreshold1(AdCPBaseModel): class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) view_threshold: ViewThreshold | ViewThreshold1 class CpvPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py index a862aecf4..d57b7e78f 100644 --- a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py +++ b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/flat_rate_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) daypart: Annotated[ str | None, @@ -56,7 +56,7 @@ class Parameters(AdCPBaseModel): class FlatRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py index 6efb8e73d..7790e5b96 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/vcpm_auction_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -26,7 +26,7 @@ class PriceGuidance(AdCPBaseModel): class VcpmAuctionPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py index 4fa574ba8..bf6fc44cc 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py +++ b/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/vcpm_fixed_option.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class VcpmFixedRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) currency: Annotated[ str, diff --git a/src/adcp/types/generated_poc/protocols/adcp_extension.py b/src/adcp/types/generated_poc/protocols/adcp_extension.py index 93ab0a406..e02a3471e 100644 --- a/src/adcp/types/generated_poc/protocols/adcp_extension.py +++ b/src/adcp/types/generated_poc/protocols/adcp_extension.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: protocols/adcp_extension.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class ProtocolsSupportedEnum(Enum): class AdcpAgentCardExtension(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) adcp_version: Annotated[ str, diff --git a/src/adcp/types/generated_poc/signals/activate_signal_request.py b/src/adcp/types/generated_poc/signals/activate_signal_request.py index 75872d4a5..cf9eea768 100644 --- a/src/adcp/types/generated_poc/signals/activate_signal_request.py +++ b/src/adcp/types/generated_poc/signals/activate_signal_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/activate_signal_request.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class ActivateSignalRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None deployments: Annotated[ diff --git a/src/adcp/types/generated_poc/signals/activate_signal_response.py b/src/adcp/types/generated_poc/signals/activate_signal_response.py index cce93060f..0ea7f6dee 100644 --- a/src/adcp/types/generated_poc/signals/activate_signal_response.py +++ b/src/adcp/types/generated_poc/signals/activate_signal_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/activate_signal_response.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class ActivateSignalResponse1(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None deployments: Annotated[ @@ -28,7 +28,7 @@ class ActivateSignalResponse1(AdCPBaseModel): class ActivateSignalResponse2(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ diff --git a/src/adcp/types/generated_poc/signals/get_signals_request.py b/src/adcp/types/generated_poc/signals/get_signals_request.py index 78844115f..2e69ba93f 100644 --- a/src/adcp/types/generated_poc/signals/get_signals_request.py +++ b/src/adcp/types/generated_poc/signals/get_signals_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/get_signals_request.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -21,7 +21,7 @@ class Country(RootModel[str]): class DeliverTo(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) countries: Annotated[ list[Country], Field(description='Countries where signals will be used (ISO codes)') @@ -37,7 +37,7 @@ class DeliverTo(AdCPBaseModel): class GetSignalsRequest(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None deliver_to: Annotated[ diff --git a/src/adcp/types/generated_poc/signals/get_signals_response.py b/src/adcp/types/generated_poc/signals/get_signals_response.py index 7e45606ca..dffdbdd8e 100644 --- a/src/adcp/types/generated_poc/signals/get_signals_response.py +++ b/src/adcp/types/generated_poc/signals/get_signals_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/get_signals_response.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-08T19:25:24+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Pricing(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) cpm: Annotated[float, Field(description='Cost per thousand impressions', ge=0.0)] currency: Annotated[str, Field(description='Currency code', pattern='^[A-Z]{3}$')] @@ -25,7 +25,7 @@ class Pricing(AdCPBaseModel): class Signal(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) coverage_percentage: Annotated[ float, Field(description='Percentage of audience coverage', ge=0.0, le=100.0) @@ -45,7 +45,7 @@ class Signal(AdCPBaseModel): class GetSignalsResponse(AdCPBaseModel): model_config = ConfigDict( - extra='forbid', + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ From 45350d1a33b8fe6823b883bccb5bff07d388f596 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 14:36:58 -0500 Subject: [PATCH 2/8] fix: resolve import sorting lint error in generated _ergonomic.py - Remove inline comments that broke import block sorting - Fix generate_ergonomic_coercion.py to not emit comments in import block --- scripts/generate_ergonomic_coercion.py | 2 -- src/adcp/types/_ergonomic.py | 31 ++++++++++++-------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/scripts/generate_ergonomic_coercion.py b/scripts/generate_ergonomic_coercion.py index 9bd5fe7cf..d39483d4a 100644 --- a/scripts/generate_ergonomic_coercion.py +++ b/scripts/generate_ergonomic_coercion.py @@ -326,7 +326,6 @@ def generate_code() -> str: ' coerce_to_model,', ')', '', - '# Import types that need coercion', ] # Add core imports @@ -357,7 +356,6 @@ def generate_code() -> str: lines.append(')') # Add response type imports - lines.append('# Response types') lines.append('from adcp.types.generated_poc.media_buy.create_media_buy_response import (') lines.append(' CreateMediaBuyResponse1,') lines.append(')') diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index e49ff2ad9..22a97d63e 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,8 +39,6 @@ coerce_to_enum_list, coerce_to_model, ) - -# Import types that need coercion from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -57,21 +55,6 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.update_media_buy_request import ( - Packages, - Packages1, -) -# Response types from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) @@ -80,15 +63,29 @@ MediaBuyDelivery, NotificationType, ) +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.update_media_buy_request import ( + Packages, + Packages1, +) def _apply_coercion() -> None: From 1a6ab9a1528da3c37e7dce8b7ad72cfd416c190b Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 15:27:23 -0500 Subject: [PATCH 3/8] fix: rename format_ to format in FieldModel enum Change format_ back to format in the FieldModel enum since enum members are accessed via EnumName.member and don't conflict with Python builtins. The enum value remains 'format' for correct JSON serialization. --- .../types/generated_poc/media_buy/list_creatives_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py index 1e73a9c81..8438d2528 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py @@ -19,7 +19,7 @@ class FieldModel(Enum): creative_id = 'creative_id' name = 'name' - format_ = 'format' + format = 'format' status = 'status' created_date = 'created_date' updated_date = 'updated_date' From c3c379aaf47a62be29e310de5df59299ab5983c0 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 17:08:44 -0500 Subject: [PATCH 4/8] feat: add format asset utilities and deprecation warnings for assets_required migration - Add format_assets.py with utilities for backward-compatible asset access: - get_format_assets(): prefers new 'assets' field, falls back to assets_required - normalize_assets_required(): converts deprecated format with required=True - get_required_assets() / get_optional_assets(): filter by required status - get_individual_assets() / get_repeatable_groups(): filter by item type - uses_deprecated_assets_field(): check if using deprecated field - get_asset_count() / has_assets(): utility helpers - Add generic deprecation warning in CLI for any field with deprecated=True - Update _create_sample_manifest_for_format() to use new utilities - Export all utilities from adcp package - Add comprehensive tests for new utilities (19 tests) - Add new tests for assets field while keeping assets_required tests for backward compat No breaking changes - all changes are backward compatible. --- src/adcp/__init__.py | 21 ++ src/adcp/__main__.py | 62 ++++++ src/adcp/utils/__init__.py | 25 ++- src/adcp/utils/format_assets.py | 228 +++++++++++++++++++++ src/adcp/utils/preview_cache.py | 34 +++- tests/test_format_assets.py | 347 ++++++++++++++++++++++++++++++++ tests/test_preview_html.py | 54 ++++- tests/test_public_api.py | 12 +- 8 files changed, 773 insertions(+), 10 deletions(-) create mode 100644 src/adcp/utils/format_assets.py create mode 100644 tests/test_format_assets.py diff --git a/src/adcp/__init__.py b/src/adcp/__init__.py index a0a6a3fb3..f376329ef 100644 --- a/src/adcp/__init__.py +++ b/src/adcp/__init__.py @@ -172,6 +172,17 @@ UrlVastAsset, ) from adcp.types.core import AgentConfig, Protocol, TaskResult, TaskStatus, WebhookMetadata +from adcp.utils import ( + get_asset_count, + get_format_assets, + get_individual_assets, + get_optional_assets, + get_repeatable_groups, + get_required_assets, + has_assets, + normalize_assets_required, + uses_deprecated_assets_field, +) from adcp.validation import ( ValidationError, validate_adagents, @@ -333,6 +344,16 @@ def get_adcp_version() -> str: "validate_agent_authorization", "validate_product", "validate_publisher_properties_item", + # Format asset utilities + "get_format_assets", + "normalize_assets_required", + "get_required_assets", + "get_optional_assets", + "get_individual_assets", + "get_repeatable_groups", + "uses_deprecated_assets_field", + "get_asset_count", + "has_assets", # Generated types modules "generated", "aliases", diff --git a/src/adcp/__main__.py b/src/adcp/__main__.py index 956219d32..90af1b2ad 100644 --- a/src/adcp/__main__.py +++ b/src/adcp/__main__.py @@ -32,8 +32,70 @@ def print_json(data: Any) -> None: print(json.dumps(data, indent=2, default=str)) +def _check_deprecated_fields(data: Any) -> None: + """Check response data for deprecated fields and emit warnings to stderr. + + Uses Pydantic's Field(deprecated=True) metadata to generically detect + any deprecated fields that are populated in the response. + """ + from pydantic import BaseModel + + deprecated_found: set[str] = set() + + def _find_deprecated_fields(obj: Any, visited: set[int] | None = None) -> None: + """Recursively find deprecated fields that are populated.""" + if obj is None: + return + + # Prevent infinite recursion on circular references + if visited is None: + visited = set() + obj_id = id(obj) + if obj_id in visited: + return + visited.add(obj_id) + + # Check Pydantic models for deprecated fields + if isinstance(obj, BaseModel): + for field_name, field_info in obj.model_fields.items(): + if field_info.deprecated: + value = getattr(obj, field_name, None) + if value is not None: + deprecated_found.add(field_name) + + # Recursively check field values + for field_name in obj.model_fields: + value = getattr(obj, field_name, None) + if value is not None: + _find_deprecated_fields(value, visited) + + # Check lists + elif isinstance(obj, list): + for item in obj: + _find_deprecated_fields(item, visited) + + # Check dicts + elif isinstance(obj, dict): + for value in obj.values(): + _find_deprecated_fields(value, visited) + + _find_deprecated_fields(data) + + if deprecated_found: + fields_list = ", ".join(f"'{f}'" for f in sorted(deprecated_found)) + print( + f"\n⚠️ Warning: Response contains deprecated field(s): {fields_list}\n" + " See field descriptions or AdCP spec for migration details.\n", + file=sys.stderr, + ) + + def print_result(result: Any, json_output: bool = False) -> None: """Print result in formatted or JSON mode.""" + # Check for deprecated fields and warn (to stderr, so JSON output isn't affected) + if result.success and result.data: + _check_deprecated_fields(result.data) + if json_output: # Match JavaScript client: output just the data for scripting if result.success and result.data: diff --git a/src/adcp/utils/__init__.py b/src/adcp/utils/__init__.py index 650285add..7e7699dc3 100644 --- a/src/adcp/utils/__init__.py +++ b/src/adcp/utils/__init__.py @@ -2,6 +2,29 @@ """Utility functions.""" +from adcp.utils.format_assets import ( + get_asset_count, + get_format_assets, + get_individual_assets, + get_optional_assets, + get_repeatable_groups, + get_required_assets, + has_assets, + normalize_assets_required, + uses_deprecated_assets_field, +) from adcp.utils.operation_id import create_operation_id -__all__ = ["create_operation_id"] +__all__ = [ + "create_operation_id", + # Format asset utilities + "get_format_assets", + "normalize_assets_required", + "get_required_assets", + "get_optional_assets", + "get_individual_assets", + "get_repeatable_groups", + "uses_deprecated_assets_field", + "get_asset_count", + "has_assets", +] diff --git a/src/adcp/utils/format_assets.py b/src/adcp/utils/format_assets.py new file mode 100644 index 000000000..2b289e467 --- /dev/null +++ b/src/adcp/utils/format_assets.py @@ -0,0 +1,228 @@ +"""Format Asset Utilities. + +Provides backward-compatible access to format assets. +The v2.6 `assets` field replaces the deprecated `assets_required` field. + +These utilities help users work with format assets regardless of which field +the agent uses, providing a smooth migration path. + +Example: + ```python + from adcp import Format + from adcp.utils.format_assets import get_format_assets, get_required_assets + + # Get all assets from a format (handles both new and deprecated fields) + all_assets = get_format_assets(format) + + # Get only required assets + required = get_required_assets(format) + + # Check if using deprecated field + if uses_deprecated_assets_field(format): + print("Agent should migrate to 'assets' field") + ``` +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Union + +if TYPE_CHECKING: + from adcp.types.generated_poc.core.format import Assets, Assets1, Format + +# Import at runtime for model creation +from adcp.types.generated_poc.core.format import Assets as AssetsModel, Assets1 as Assets1Model + + +# Type alias for any format asset (individual or repeatable group) +FormatAsset = Union["Assets", "Assets1"] + + +def get_format_assets(format: Format) -> list[FormatAsset]: + """Get assets from a Format, preferring new `assets` field, falling back to `assets_required`. + + This provides backward compatibility during the migration from `assets_required` to `assets`. + - If `assets` exists and has items, returns it directly + - If only `assets_required` exists, normalizes it to the new format (sets required=True) + - Returns empty list if neither field exists (flexible format with no assets) + + Args: + format: The Format object from list_creative_formats response + + Returns: + List of assets in the new format structure + + Example: + ```python + formats = await agent.simple.list_creative_formats() + for format in formats.formats: + assets = get_format_assets(format) + print(f"{format.name} has {len(assets)} assets") + ``` + """ + # Prefer new `assets` field (v2.6+) + if format.assets and len(format.assets) > 0: + return list(format.assets) + + # Fall back to deprecated `assets_required` and normalize + if format.assets_required and len(format.assets_required) > 0: + return normalize_assets_required(format.assets_required) + + return [] + + +def normalize_assets_required(assets_required: list[Any]) -> list[FormatAsset]: + """Convert deprecated assets_required to new assets format. + + All assets in assets_required are required by definition (that's why they were in that array). + The new `assets` field has an explicit `required: boolean` to allow both required AND optional assets. + + Args: + assets_required: The deprecated assets_required array + + Returns: + Normalized assets as Pydantic models with explicit required=True + """ + normalized: list[FormatAsset] = [] + for asset in assets_required: + # Get asset data as dict + if isinstance(asset, dict): + asset_dict = asset + else: + asset_dict = asset.model_dump() if hasattr(asset, "model_dump") else dict(asset) + + # Check if it's a repeatable group (has asset_group_id) or individual asset + if "asset_group_id" in asset_dict: + # Repeatable group - use Assets1Model + normalized.append(Assets1Model(**{**asset_dict, "required": True})) + else: + # Individual asset - use AssetsModel + normalized.append(AssetsModel(**{**asset_dict, "required": True})) + + return normalized + + +def get_required_assets(format: Format) -> list[FormatAsset]: + """Get only required assets from a Format. + + Args: + format: The Format object + + Returns: + List of required assets only + + Example: + ```python + required_assets = get_required_assets(format) + print(f"Must provide {len(required_assets)} assets") + ``` + """ + return [asset for asset in get_format_assets(format) if _is_required(asset)] + + +def get_optional_assets(format: Format) -> list[FormatAsset]: + """Get only optional assets from a Format. + + Note: When using deprecated `assets_required`, this will always return empty + since assets_required only contained required assets. + + Args: + format: The Format object + + Returns: + List of optional assets only + + Example: + ```python + optional_assets = get_optional_assets(format) + print(f"Can optionally provide {len(optional_assets)} additional assets") + ``` + """ + return [asset for asset in get_format_assets(format) if not _is_required(asset)] + + +def get_individual_assets(format: Format) -> list[FormatAsset]: + """Get individual assets (not repeatable groups) from a Format. + + Args: + format: The Format object + + Returns: + List of individual assets (item_type='individual') + """ + return [asset for asset in get_format_assets(format) if _get_item_type(asset) == "individual"] + + +def get_repeatable_groups(format: Format) -> list[FormatAsset]: + """Get repeatable asset groups from a Format. + + Args: + format: The Format object + + Returns: + List of repeatable asset groups (item_type='repeatable_group') + """ + return [ + asset for asset in get_format_assets(format) if _get_item_type(asset) == "repeatable_group" + ] + + +def uses_deprecated_assets_field(format: Format) -> bool: + """Check if format uses deprecated assets_required field (for migration warnings). + + Args: + format: The Format object + + Returns: + True if using deprecated field, False if using new field or neither + + Example: + ```python + if uses_deprecated_assets_field(format): + print(f"Format {format.name} uses deprecated assets_required field") + ``` + """ + has_assets = format.assets is not None and len(format.assets) > 0 + has_assets_required = format.assets_required is not None and len(format.assets_required) > 0 + return not has_assets and has_assets_required + + +def get_asset_count(format: Format) -> int: + """Get the count of assets in a format (for display purposes). + + Args: + format: The Format object + + Returns: + Number of assets, or 0 if none defined + """ + return len(get_format_assets(format)) + + +def has_assets(format: Format) -> bool: + """Check if a format has any assets defined. + + Args: + format: The Format object + + Returns: + True if format has assets, False otherwise + """ + return get_asset_count(format) > 0 + + +# Internal helpers + + +def _is_required(asset: FormatAsset) -> bool: + """Check if an asset is required.""" + if isinstance(asset, dict): + return asset.get("required", False) is True + return getattr(asset, "required", False) is True + + +def _get_item_type(asset: FormatAsset) -> str: + """Get the item_type of an asset.""" + if isinstance(asset, dict): + return asset.get("item_type", "individual") + return getattr(asset, "item_type", "individual") diff --git a/src/adcp/utils/preview_cache.py b/src/adcp/utils/preview_cache.py index 55548d9b1..cee003afa 100644 --- a/src/adcp/utils/preview_cache.py +++ b/src/adcp/utils/preview_cache.py @@ -399,25 +399,45 @@ def _create_sample_manifest_for_format(fmt: Format) -> CreativeManifest | None: Sample CreativeManifest, or None if unable to create one """ from adcp.types import CreativeManifest + from adcp.utils.format_assets import get_required_assets - if not fmt.assets_required: + required_assets = get_required_assets(fmt) + if not required_assets: return None assets: dict[str, Any] = {} - for asset in fmt.assets_required: + for asset in required_assets: if isinstance(asset, dict): + # Handle dict input asset_id = asset.get("asset_id") asset_type = asset.get("asset_type") if asset_id: assets[asset_id] = _create_sample_asset(asset_type) else: - # Handle Pydantic model - asset_id = asset.asset_id - has_value = hasattr(asset.asset_type, "value") - asset_type = asset.asset_type.value if has_value else str(asset.asset_type) - assets[asset_id] = _create_sample_asset(asset_type) + # Handle Pydantic model - check for individual vs repeatable_group + item_type = getattr(asset, "item_type", "individual") + + if item_type == "individual": + asset_id = asset.asset_id + has_value = hasattr(asset.asset_type, "value") + asset_type = asset.asset_type.value if has_value else str(asset.asset_type) + assets[asset_id] = _create_sample_asset(asset_type) + elif item_type == "repeatable_group": + # For repeatable groups, create sample assets for each asset in the group + group_assets = getattr(asset, "assets", []) + for group_asset in group_assets: + if isinstance(group_asset, dict): + asset_id = group_asset.get("asset_id") + asset_type = group_asset.get("asset_type") + else: + asset_id = group_asset.asset_id + has_value = hasattr(group_asset.asset_type, "value") + asset_type = group_asset.asset_type.value if has_value else str(group_asset.asset_type) + + if asset_id: + assets[asset_id] = _create_sample_asset(asset_type) if not assets: return None diff --git a/tests/test_format_assets.py b/tests/test_format_assets.py new file mode 100644 index 000000000..1080ed560 --- /dev/null +++ b/tests/test_format_assets.py @@ -0,0 +1,347 @@ +"""Tests for format asset utilities. + +These utilities provide backward-compatible access to format assets, +handling the migration from deprecated `assets_required` to new `assets` field. +""" + +import pytest + +from adcp import Format, FormatId, FormatCategory +from adcp.utils.format_assets import ( + get_format_assets, + normalize_assets_required, + get_required_assets, + get_optional_assets, + get_individual_assets, + get_repeatable_groups, + uses_deprecated_assets_field, + get_asset_count, + has_assets, +) + + +def make_format_id(format_name: str) -> FormatId: + """Create a test format ID.""" + return FormatId(agent_url="https://test-agent.example.com", id=format_name) + + +def get_asset_id(asset) -> str: + """Get asset_id or asset_group_id from asset.""" + return getattr(asset, "asset_id", None) or getattr(asset, "asset_group_id", None) + + +def get_asset_ids(assets) -> list[str]: + """Get list of asset_ids from assets.""" + return [get_asset_id(a) for a in assets] + + +class TestGetFormatAssets: + """Tests for get_format_assets() utility.""" + + def test_prefers_new_assets_field(self): + """Should prefer new assets field when present.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "new_img", "asset_type": "image", "item_type": "individual", "required": True}, + ], + assets_required=[ + {"asset_id": "old_img", "asset_type": "image", "item_type": "individual"}, + ], + ) + assets = get_format_assets(fmt) + assert len(assets) == 1 + assert get_asset_id(assets[0]) == "new_img" + + def test_falls_back_to_assets_required(self): + """Should fall back to deprecated assets_required when assets is empty.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "legacy_img", "asset_type": "image", "item_type": "individual"}, + ], + ) + assets = get_format_assets(fmt) + assert len(assets) == 1 + # Normalized to have required=True + assert get_asset_id(assets[0]) == "legacy_img" + assert assets[0].required is True + + def test_returns_empty_list_when_no_assets(self): + """Should return empty list when neither field has assets.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + ) + assets = get_format_assets(fmt) + assert assets == [] + + +class TestNormalizeAssetsRequired: + """Tests for normalize_assets_required() utility.""" + + def test_adds_required_true_to_dict_assets(self): + """Should add required=True to dict assets.""" + assets_required = [ + {"asset_id": "img", "asset_type": "image", "item_type": "individual"}, + ] + normalized = normalize_assets_required(assets_required) + assert len(normalized) == 1 + assert normalized[0].required is True + assert get_asset_id(normalized[0]) == "img" + + def test_preserves_other_fields(self): + """Should preserve all other fields when normalizing.""" + assets_required = [ + { + "asset_id": "img", + "asset_type": "image", + "item_type": "individual", + "requirements": {"width": 300, "height": 250}, + }, + ] + normalized = normalize_assets_required(assets_required) + # normalize_assets_required returns Pydantic models + assert normalized[0].requirements == {"width": 300, "height": 250} + + +class TestGetRequiredAssets: + """Tests for get_required_assets() utility.""" + + def test_filters_to_required_only(self): + """Should return only assets with required=True.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "required_img", "asset_type": "image", "item_type": "individual", "required": True}, + {"asset_id": "optional_logo", "asset_type": "image", "item_type": "individual", "required": False}, + {"asset_id": "required_url", "asset_type": "url", "item_type": "individual", "required": True}, + ], + ) + required = get_required_assets(fmt) + assert len(required) == 2 + ids = get_asset_ids(required) + assert "required_img" in ids + assert "required_url" in ids + assert "optional_logo" not in ids + + def test_all_required_from_assets_required(self): + """All assets from deprecated assets_required should be considered required.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "img1", "asset_type": "image", "item_type": "individual"}, + {"asset_id": "img2", "asset_type": "image", "item_type": "individual"}, + ], + ) + required = get_required_assets(fmt) + assert len(required) == 2 + + +class TestGetOptionalAssets: + """Tests for get_optional_assets() utility.""" + + def test_filters_to_optional_only(self): + """Should return only assets with required=False.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "required_img", "asset_type": "image", "item_type": "individual", "required": True}, + {"asset_id": "optional_logo", "asset_type": "image", "item_type": "individual", "required": False}, + ], + ) + optional = get_optional_assets(fmt) + assert len(optional) == 1 + assert get_asset_id(optional[0]) == "optional_logo" + + def test_empty_for_assets_required(self): + """Should return empty for deprecated assets_required (all are required).""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual"}, + ], + ) + optional = get_optional_assets(fmt) + assert optional == [] + + +class TestGetIndividualAssets: + """Tests for get_individual_assets() utility.""" + + def test_filters_to_individual_only(self): + """Should return only individual assets (not groups).""" + fmt = Format( + format_id=make_format_id("carousel"), + name="Carousel", + type=FormatCategory.display, + assets=[ + {"asset_id": "headline", "asset_type": "text", "item_type": "individual", "required": True}, + { + "asset_group_id": "product", + "item_type": "repeatable_group", + "required": True, + "min_count": 2, + "max_count": 10, + "assets": [], + }, + ], + ) + individual = get_individual_assets(fmt) + assert len(individual) == 1 + assert get_asset_id(individual[0]) == "headline" + + +class TestGetRepeatableGroups: + """Tests for get_repeatable_groups() utility.""" + + def test_filters_to_groups_only(self): + """Should return only repeatable groups.""" + fmt = Format( + format_id=make_format_id("carousel"), + name="Carousel", + type=FormatCategory.display, + assets=[ + {"asset_id": "headline", "asset_type": "text", "item_type": "individual", "required": True}, + { + "asset_group_id": "product", + "item_type": "repeatable_group", + "required": True, + "min_count": 2, + "max_count": 10, + "assets": [], + }, + ], + ) + groups = get_repeatable_groups(fmt) + assert len(groups) == 1 + assert get_asset_id(groups[0]) == "product" + + +class TestUsesDeprecatedAssetsField: + """Tests for uses_deprecated_assets_field() utility.""" + + def test_true_when_only_assets_required(self): + """Should return True when only deprecated field is used.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual"}, + ], + ) + assert uses_deprecated_assets_field(fmt) is True + + def test_false_when_using_new_assets(self): + """Should return False when new assets field is used.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual", "required": True}, + ], + ) + assert uses_deprecated_assets_field(fmt) is False + + def test_false_when_no_assets(self): + """Should return False when neither field is used.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + ) + assert uses_deprecated_assets_field(fmt) is False + + +class TestGetAssetCount: + """Tests for get_asset_count() utility.""" + + def test_counts_all_assets(self): + """Should count all assets.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "img1", "asset_type": "image", "item_type": "individual", "required": True}, + {"asset_id": "img2", "asset_type": "image", "item_type": "individual", "required": False}, + ], + ) + assert get_asset_count(fmt) == 2 + + def test_zero_when_no_assets(self): + """Should return 0 when no assets.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + ) + assert get_asset_count(fmt) == 0 + + +class TestHasAssets: + """Tests for has_assets() utility.""" + + def test_true_when_has_assets(self): + """Should return True when format has assets.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual", "required": True}, + ], + ) + assert has_assets(fmt) is True + + def test_false_when_no_assets(self): + """Should return False when format has no assets.""" + fmt = Format( + format_id=make_format_id("test"), + name="Test", + type=FormatCategory.display, + ) + assert has_assets(fmt) is False + + +class TestPublicImports: + """Tests for public API imports.""" + + def test_can_import_from_adcp(self): + """Should be able to import utilities from main adcp package.""" + from adcp import ( + get_format_assets, + get_required_assets, + get_optional_assets, + get_individual_assets, + get_repeatable_groups, + uses_deprecated_assets_field, + normalize_assets_required, + get_asset_count, + has_assets, + ) + # All should be callable + assert callable(get_format_assets) + assert callable(get_required_assets) + assert callable(get_optional_assets) + assert callable(get_individual_assets) + assert callable(get_repeatable_groups) + assert callable(uses_deprecated_assets_field) + assert callable(normalize_assets_required) + assert callable(get_asset_count) + assert callable(has_assets) diff --git a/tests/test_preview_html.py b/tests/test_preview_html.py index 7dd601c70..4fca72035 100644 --- a/tests/test_preview_html.py +++ b/tests/test_preview_html.py @@ -473,7 +473,7 @@ def test_create_sample_manifest_for_format(): def test_create_sample_manifest_for_format_no_assets(): - """Test creating sample manifest for a format without assets.""" + """Test creating sample manifest for a format without assets (backward compat).""" format_id = make_format_id("display_300x250") fmt = Format( format_id=format_id, @@ -485,3 +485,55 @@ def test_create_sample_manifest_for_format_no_assets(): manifest = _create_sample_manifest_for_format(fmt) assert manifest is None + + +# New tests for v2.6+ assets field + + +def test_create_sample_manifest_for_format_with_new_assets_field(): + """Test creating sample manifest using new assets field (v2.6+).""" + format_id = make_format_id("display_300x250") + fmt = Format( + format_id=format_id, + name="Display 300x250", + description="Standard banner", + type="display", + assets=[ + {"asset_id": "banner_image", "asset_type": "image", "item_type": "individual", "required": True}, + {"asset_id": "logo", "asset_type": "image", "item_type": "individual", "required": False}, + {"asset_id": "cta_url", "asset_type": "url", "item_type": "individual", "required": True}, + ], + ) + + manifest = _create_sample_manifest_for_format(fmt) + assert manifest is not None + # Only required assets should be in the sample manifest + assert "banner_image" in manifest.assets + assert "cta_url" in manifest.assets + # Optional asset should NOT be included + assert "logo" not in manifest.assets + + +def test_create_sample_manifest_prefers_assets_over_assets_required(): + """Test that new assets field takes precedence over deprecated assets_required.""" + format_id = make_format_id("display_300x250") + fmt = Format( + format_id=format_id, + name="Display 300x250", + description="Standard banner", + type="display", + # Both fields present - should prefer assets + assets=[ + {"asset_id": "new_image", "asset_type": "image", "item_type": "individual", "required": True}, + ], + assets_required=[ + {"asset_id": "old_image", "asset_type": "image", "item_type": "individual"}, + ], + ) + + manifest = _create_sample_manifest_for_format(fmt) + assert manifest is not None + # Should use new assets field + assert "new_image" in manifest.assets + # Should NOT use deprecated assets_required + assert "old_image" not in manifest.assets diff --git a/tests/test_public_api.py b/tests/test_public_api.py index 9f35b3c9e..90a5c6f47 100644 --- a/tests/test_public_api.py +++ b/tests/test_public_api.py @@ -141,7 +141,7 @@ def test_product_has_expected_public_fields(): def test_format_has_expected_public_fields(): - """Format type from public API has expected fields.""" + """Format type from public API has expected fields (backward compatibility).""" from adcp import Format expected_fields = [ @@ -157,6 +157,16 @@ def test_format_has_expected_public_fields(): assert field_name in model_fields, f"Format missing field: {field_name}" +def test_format_has_new_assets_field(): + """Format type has new assets field (v2.6+).""" + from adcp import Format + + model_fields = Format.model_fields + # New field added in v2.6 + assert "assets" in model_fields, "Format missing new 'assets' field" + # Note: assets_required is deprecated and may be removed in future versions + + def test_pricing_options_are_discriminated_by_is_fixed(): """Pricing option types have is_fixed discriminator field.""" from adcp import CpcPricingOption, CpmAuctionPricingOption, CpmFixedRatePricingOption From b46c23b485952be4bfffe4eed2125a524bd70586 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 17:14:51 -0500 Subject: [PATCH 5/8] chore: restore comment lines in _ergonomic.py --- src/adcp/types/_ergonomic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index 22a97d63e..f828abab7 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,6 +39,8 @@ coerce_to_enum_list, coerce_to_model, ) + +# Import types that need coercion from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -55,6 +57,8 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) + +# Response types from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) From 4a53e33dd34254b34a39737bba9e0ea0c6b9960c Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 17:29:32 -0500 Subject: [PATCH 6/8] fix: resolve linter errors (import sorting, line length) --- src/adcp/utils/format_assets.py | 12 ++++++------ src/adcp/utils/preview_cache.py | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/adcp/utils/format_assets.py b/src/adcp/utils/format_assets.py index 2b289e467..f7f70073c 100644 --- a/src/adcp/utils/format_assets.py +++ b/src/adcp/utils/format_assets.py @@ -27,13 +27,12 @@ from typing import TYPE_CHECKING, Any, Union +from adcp.types.generated_poc.core.format import Assets as AssetsModel +from adcp.types.generated_poc.core.format import Assets1 as Assets1Model + if TYPE_CHECKING: from adcp.types.generated_poc.core.format import Assets, Assets1, Format -# Import at runtime for model creation -from adcp.types.generated_poc.core.format import Assets as AssetsModel, Assets1 as Assets1Model - - # Type alias for any format asset (individual or repeatable group) FormatAsset = Union["Assets", "Assets1"] @@ -74,8 +73,9 @@ def get_format_assets(format: Format) -> list[FormatAsset]: def normalize_assets_required(assets_required: list[Any]) -> list[FormatAsset]: """Convert deprecated assets_required to new assets format. - All assets in assets_required are required by definition (that's why they were in that array). - The new `assets` field has an explicit `required: boolean` to allow both required AND optional assets. + All assets in assets_required are required by definition (that's why they were in + that array). The new `assets` field has an explicit `required: boolean` to allow + both required AND optional assets. Args: assets_required: The deprecated assets_required array diff --git a/src/adcp/utils/preview_cache.py b/src/adcp/utils/preview_cache.py index cee003afa..168fd41df 100644 --- a/src/adcp/utils/preview_cache.py +++ b/src/adcp/utils/preview_cache.py @@ -433,8 +433,10 @@ def _create_sample_manifest_for_format(fmt: Format) -> CreativeManifest | None: asset_type = group_asset.get("asset_type") else: asset_id = group_asset.asset_id - has_value = hasattr(group_asset.asset_type, "value") - asset_type = group_asset.asset_type.value if has_value else str(group_asset.asset_type) + if hasattr(group_asset.asset_type, "value"): + asset_type = group_asset.asset_type.value + else: + asset_type = str(group_asset.asset_type) if asset_id: assets[asset_id] = _create_sample_asset(asset_type) From 89470901617eece1bb9e6bb3ca6d78d69b4d0813 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 17:56:04 -0500 Subject: [PATCH 7/8] feat: add deprecated field metadata injection and CLI warnings - Add add_deprecated_field_metadata() to post_generate_fixes.py - Reads JSON schemas to find fields with deprecated: true - Injects Field(deprecated=True) into generated Python files - Fix Pydantic v2.11 deprecation warnings in CLI - Access model_fields from class instead of instance - Suppress DeprecationWarning when checking deprecated field values - Add tests for CLI deprecation warning functionality - Add test for normalize_assets_required with repeatable groups - Simplify _is_required and _get_item_type helpers Coverage: 80.47% --- scripts/post_generate_fixes.py | 88 +++++++++++++++++++++ src/adcp/__main__.py | 18 ++++- src/adcp/types/generated_poc/core/format.py | 1 + src/adcp/utils/format_assets.py | 4 - tests/test_cli.py | 69 ++++++++++++++++ tests/test_format_assets.py | 25 ++++++ 6 files changed, 197 insertions(+), 8 deletions(-) diff --git a/scripts/post_generate_fixes.py b/scripts/post_generate_fixes.py index f1e6efb14..40c482819 100644 --- a/scripts/post_generate_fixes.py +++ b/scripts/post_generate_fixes.py @@ -8,14 +8,18 @@ 1. Adds model_validators to types requiring mutual exclusivity checks 2. Fixes self-referential RootModel type annotations 3. Fixes BrandManifest forward references +4. Adds deprecated=True to fields marked deprecated in JSON schema """ from __future__ import annotations +import json +import re from pathlib import Path REPO_ROOT = Path(__file__).parent.parent OUTPUT_DIR = REPO_ROOT / "src" / "adcp" / "types" / "generated_poc" +SCHEMA_DIR = REPO_ROOT / "schemas" / "cache" def add_model_validator_to_product(): @@ -166,6 +170,89 @@ def fix_preview_creative_request_discriminator(): print(" preview_creative_request.py discriminator added") +def add_deprecated_field_metadata(): + """Add deprecated=True to fields marked deprecated in JSON schema. + + datamodel-code-generator doesn't translate JSON Schema's "deprecated": true + to Pydantic's Field(deprecated=True). This function reads the schemas and + injects the metadata into the generated Python files. + """ + deprecated_fields_fixed = 0 + + # Walk through all schema files + for schema_file in SCHEMA_DIR.rglob("*.json"): + try: + with open(schema_file) as f: + schema = json.load(f) + except (json.JSONDecodeError, OSError): + continue + + # Find deprecated fields in properties + properties = schema.get("properties", {}) + deprecated_fields = [ + field_name + for field_name, field_def in properties.items() + if isinstance(field_def, dict) and field_def.get("deprecated") is True + ] + + if not deprecated_fields: + continue + + # Map schema file to generated Python file + relative_path = schema_file.relative_to(SCHEMA_DIR) + # Convert path: core/format.json -> core/format.py + py_path = OUTPUT_DIR / relative_path.with_suffix(".py") + # Handle kebab-case to snake_case conversion + py_path = py_path.parent / py_path.name.replace("-", "_") + + if not py_path.exists(): + continue + + with open(py_path) as f: + content = f.read() + + modified = False + for field_name in deprecated_fields: + # Check if already has deprecated=True for this field + field_start = content.find(f"{field_name}:") + if field_start == -1: + continue + + # Find the Field( after this field definition + field_section = content[field_start:field_start + 500] + if "deprecated=True" in field_section.split("] = ")[0]: + continue # Already fixed + + # Pattern to find Field( and add deprecated=True after it + # Use DOTALL to match across newlines + pattern = rf"({field_name}:\s*Annotated\[[\s\S]*?Field\(\s*\n?\s*)" + match = re.search(pattern, content) + + if match: + # Insert deprecated=True after Field( + insert_pos = match.end() + # Check what comes after - if it's description=, add before it + after_match = content[insert_pos:insert_pos + 50] + if after_match.strip().startswith("description="): + new_content = content[:insert_pos] + "deprecated=True,\n " + content[insert_pos:] + else: + new_content = content[:insert_pos] + "deprecated=True, " + content[insert_pos:] + + if new_content != content: + content = new_content + modified = True + deprecated_fields_fixed += 1 + + if modified: + with open(py_path, "w") as f: + f.write(content) + + if deprecated_fields_fixed > 0: + print(f" Added deprecated=True to {deprecated_fields_fixed} field(s)") + else: + print(" No deprecated fields needed fixing") + + def main(): """Apply all post-generation fixes.""" print("Applying post-generation fixes...") @@ -175,6 +262,7 @@ def main(): fix_brand_manifest_references() fix_enum_defaults() fix_preview_creative_request_discriminator() + add_deprecated_field_metadata() print("\n✓ Post-generation fixes complete\n") diff --git a/src/adcp/__main__.py b/src/adcp/__main__.py index 90af1b2ad..35a7eae15 100644 --- a/src/adcp/__main__.py +++ b/src/adcp/__main__.py @@ -57,15 +57,25 @@ def _find_deprecated_fields(obj: Any, visited: set[int] | None = None) -> None: # Check Pydantic models for deprecated fields if isinstance(obj, BaseModel): - for field_name, field_info in obj.model_fields.items(): + import warnings + + # Access model_fields from the class, not the instance (Pydantic v2.11+) + model_fields = type(obj).model_fields + + for field_name, field_info in model_fields.items(): if field_info.deprecated: - value = getattr(obj, field_name, None) + # Suppress default Pydantic's DeprecationWarning when accessing deprecated fields + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + value = getattr(obj, field_name, None) if value is not None: deprecated_found.add(field_name) # Recursively check field values - for field_name in obj.model_fields: - value = getattr(obj, field_name, None) + for field_name in model_fields: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + value = getattr(obj, field_name, None) if value is not None: _find_deprecated_fields(value, visited) diff --git a/src/adcp/types/generated_poc/core/format.py b/src/adcp/types/generated_poc/core/format.py index 067f33349..6c52573ca 100644 --- a/src/adcp/types/generated_poc/core/format.py +++ b/src/adcp/types/generated_poc/core/format.py @@ -277,6 +277,7 @@ class Format(AdCPBaseModel): assets_required: Annotated[ list[AssetsRequired | AssetsRequired1] | None, Field( + deprecated=True, description="DEPRECATED: Use 'assets' instead. Array of required assets or asset groups for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Can contain individual assets or repeatable asset sequences (e.g., carousel products, slideshow frames). This field is maintained for backward compatibility; new implementations should use 'assets' with the 'required' boolean on each asset." ), ] = None diff --git a/src/adcp/utils/format_assets.py b/src/adcp/utils/format_assets.py index f7f70073c..3939686a4 100644 --- a/src/adcp/utils/format_assets.py +++ b/src/adcp/utils/format_assets.py @@ -216,13 +216,9 @@ def has_assets(format: Format) -> bool: def _is_required(asset: FormatAsset) -> bool: """Check if an asset is required.""" - if isinstance(asset, dict): - return asset.get("required", False) is True return getattr(asset, "required", False) is True def _get_item_type(asset: FormatAsset) -> str: """Get the item_type of an asset.""" - if isinstance(asset, dict): - return asset.get("item_type", "individual") return getattr(asset, "item_type", "individual") diff --git a/tests/test_cli.py b/tests/test_cli.py index 6158fd508..7310abce1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -359,3 +359,72 @@ def test_payload_with_backslashes(self): payload = '{"path": "C:\\\\Users\\\\test"}' result = load_payload(payload) assert result["path"] == "C:\\Users\\test" + + +class TestDeprecatedFieldWarnings: + """Tests for deprecated field warning functionality.""" + + def test_check_deprecated_fields_warns_on_assets_required(self, capsys): + """Should warn when response contains deprecated assets_required field.""" + from adcp.__main__ import _check_deprecated_fields + from adcp import Format, FormatId, FormatCategory + + fmt = Format( + format_id=FormatId(agent_url="https://test.com", id="test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual"}, + ], + ) + + _check_deprecated_fields(fmt) + captured = capsys.readouterr() + assert "deprecated" in captured.err.lower() + assert "assets_required" in captured.err + + def test_check_deprecated_fields_no_warning_for_new_assets(self, capsys): + """Should not warn when using new assets field.""" + from adcp.__main__ import _check_deprecated_fields + from adcp import Format, FormatId, FormatCategory + + fmt = Format( + format_id=FormatId(agent_url="https://test.com", id="test"), + name="Test", + type=FormatCategory.display, + assets=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual", "required": True}, + ], + ) + + _check_deprecated_fields(fmt) + captured = capsys.readouterr() + assert "deprecated" not in captured.err.lower() + + def test_check_deprecated_fields_handles_none(self, capsys): + """Should handle None input gracefully.""" + from adcp.__main__ import _check_deprecated_fields + + _check_deprecated_fields(None) + captured = capsys.readouterr() + assert captured.err == "" + + def test_check_deprecated_fields_handles_list(self, capsys): + """Should check items in a list.""" + from adcp.__main__ import _check_deprecated_fields + from adcp import Format, FormatId, FormatCategory + + formats = [ + Format( + format_id=FormatId(agent_url="https://test.com", id="test"), + name="Test", + type=FormatCategory.display, + assets_required=[ + {"asset_id": "img", "asset_type": "image", "item_type": "individual"}, + ], + ), + ] + + _check_deprecated_fields(formats) + captured = capsys.readouterr() + assert "assets_required" in captured.err diff --git a/tests/test_format_assets.py b/tests/test_format_assets.py index 1080ed560..e0ce07386 100644 --- a/tests/test_format_assets.py +++ b/tests/test_format_assets.py @@ -109,6 +109,31 @@ def test_preserves_other_fields(self): # normalize_assets_required returns Pydantic models assert normalized[0].requirements == {"width": 300, "height": 250} + def test_normalizes_repeatable_groups(self): + """Should normalize repeatable groups with required=True.""" + assets_required = [ + { + "asset_group_id": "products", + "item_type": "repeatable_group", + "min_count": 2, + "max_count": 10, + "assets": [ + { + "asset_id": "product_img", + "asset_type": "image", + "item_type": "individual", + "required": True, + }, + ], + }, + ] + normalized = normalize_assets_required(assets_required) + assert len(normalized) == 1 + assert normalized[0].required is True + assert normalized[0].asset_group_id == "products" + assert normalized[0].min_count == 2 + assert normalized[0].max_count == 10 + class TestGetRequiredAssets: """Tests for get_required_assets() utility.""" From 7a2e30ed4b9ab5ef6141662356196e9f7bc0b8c7 Mon Sep 17 00:00:00 2001 From: BaiyuScope3 Date: Thu, 8 Jan 2026 17:57:12 -0500 Subject: [PATCH 8/8] fix: shorten comment line to pass lint --- src/adcp/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adcp/__main__.py b/src/adcp/__main__.py index 35a7eae15..3a1277f07 100644 --- a/src/adcp/__main__.py +++ b/src/adcp/__main__.py @@ -64,7 +64,7 @@ def _find_deprecated_fields(obj: Any, visited: set[int] | None = None) -> None: for field_name, field_info in model_fields.items(): if field_info.deprecated: - # Suppress default Pydantic's DeprecationWarning when accessing deprecated fields + # Suppress Pydantic's DeprecationWarning when accessing deprecated fields with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) value = getattr(obj, field_name, None)