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 fb772eec..2ce963f7 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 819cf0e7..1b43218a 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 ae355994..d1511248 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 ac254331..6ad5331b 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 5b5206e8..4fd73b6f 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 aaaf521a..2327c516 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 07f17adb..6e25a751 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 fbfa7b5f..0442fa79 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 e2aa4840..68aa14df 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 7c3d9bc8..a43cd804 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 3d236289..7f4b2d40 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 4b714de2..ac5ea5bb 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 5042129c..4dc467ac 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 de1747ad..d73c6509 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 9db9a401..5ad3f28b 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 bc7d63b7..28fa3c34 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 b23da743..ae5dfc6d 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 50aa36c3..5ddea189 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 c36c04dd..2dad375d 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 ac7cda7e..aaf9042d 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 a6cdd813..bf17bb57 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 e1dc6dce..f4d074f4 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 047266b6..b240bb96 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 81f51cf5..323cd69a 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 c905c0b2..31adf984 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 21a55ed4..a2153f0b 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 7fb1bc13..e3284068 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 2eb753af..7a658fd1 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 6ae8e3f3..b0ba1c51 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 a7e2c74c..e738afb6 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 5e97f457..868e443e 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 6d5a9c01..1e289867 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 35fab2c8..3fd39037 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 7fcdc81c..2104a47c 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 d8656b57..094887db 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 d22d4b81..d956dce4 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 3b65cb08..65c7e0a7 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 1cad9cb6..7d653506 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 6e7220de..8ff95b50 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 8429b23e..f4df5fe6 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 7cec3843..3ce119a1 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 b23290ad..1e33e1b7 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 f3a1d5f7..e65e896a 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 ab332500..79805706 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 2518463d..318ee547 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 aa6c6340..e29da17b 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 17aae342..948f7283 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 cc66572c..f211c4ca 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 fa175b7d..0166a8d1 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 3290efd3..e04712c9 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 9d1a2c21..509aaf91 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 a0aa5f2e..ab575837 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 5ee757c2..bf8c9256 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 61dfab09..2585b957 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 306f1889..e95a3d0b 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 aa8469c2..3db30764 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 926c581e..2d2686b0 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 0e869af2..b0673a3c 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 f99c9cde..f1c7600a 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 a73bda16..5b8662a9 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 95343e44..bc82fea0 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 57d8599c..b91031a7 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 67343fd5..e0dbc181 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 338c7e24..1896428c 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 c78add6d..ee961efa 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 93f6e405..352f329f 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 ca0fbebe..7fb862a1 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 6ffe0fbf..39bae204 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 aca33f51..0c8f657f 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 fd6965c4..6ab366c6 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 437e37bd..96b857bb 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 ad22e323..09002e63 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 5d50d832..43e3f098 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 f32a3fd1..d109718f 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 4c803b36..7cd90753 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 364dfcb9..e0ba0311 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 b92ba7e3..83f360b0 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 3261d410..51961fc7 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 fc9ea41d..fb8b4c6c 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 9547de76..8e20eb5c 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 f56be9f4..681a5da7 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 c92509e7..775c885a 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 cf260f56..86d97717 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 99b2eacc..a05318bb 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 7bf78358..26ede76e 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 1ec45714..064fa2ef 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 21354551..8735617e 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 ef965663..279b4361 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 20f5cb4c..5be3c6a6 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 5d4535c3..e2fecdf9 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 66e88202..a532550c 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 4243104c..c2f03350 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 c95bccca..b811c932 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 759bd1b1..a5dbab16 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 24f1da46..49d89f43 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 c76b35a9..4c09e523 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 6076a29e..08a55211 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 61402235..30089b52 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 267e5e4f..2f00284d 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 437459cd..e70b4523 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 f828abab..e49ff2ad 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 a555dc4c..62b34202 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 09701921..e5dfea04 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 effa4ae0..b8509374 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 d5bdb770..33a0ca65 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 0b1d0a83..91e797ae 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 c9c9a5be..4b596033 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 aebc86fe..f953a6db 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 7ce67379..1af037fc 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 c846dedb..a382ad05 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 5763b474..f16ccfa3 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 cb4c95d0..7969e41f 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 71fa502c..dcb24220 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 774c37ff..47fbcc67 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 3d218b83..d68f20ea 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 2a1f9e30..d009a778 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 6af67cbe..5a98be66 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 cc0bd3f9..fc123911 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 fcfdef56..ed6aa184 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 9bd6a5c8..030382bb 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 5f30d13b..ef22303a 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 64685209..d3a38cb9 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 2d3a6564..33cdd893 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 3af77f89..b3c05447 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 ab1d1c5a..2a811ba3 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 bcdc0d84..13c44841 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 78c4d8d6..20b2ccc5 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 e6fa8872..067f3334 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 92741534..d38bda83 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 cc9a749c..02d931f1 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 e167e830..a45cc8e0 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 bb704655..1697ef17 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 1dd81db6..658e4c34 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 34b998ef..0dbcd29e 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 81efcb4c..76add5bb 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 e767c4e8..c89a0558 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 7efe2943..b63f935c 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 5039e65e..ba031503 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 a9846b11..b3fa8d01 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 f59ea5a2..deb01cf5 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 c7f912f0..c32caac7 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 b0ed5b28..ce36f8bb 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 3f62a68d..651b6514 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 65392501..343adf1e 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 cfe3951b..142b2864 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 0b0e1d67..469f176c 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 68f132f3..a382182a 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 03e45717..2e9a6214 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 a8264042..5e85ce21 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 f033d2db..5b15d6a8 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 97e691bd..8a0282d9 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 a6c85236..f5c8ac78 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 772c99ad..1b88ee97 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 1c26b026..cb89baea 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 ec2aecff..9c88a3b4 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 5635c3f3..17cb9042 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 79e4fc15..1c2b2e33 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 629b283e..13830aba 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 cbf35937..3e6b59cd 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 6dd71da7..ba67080d 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 38394697..467ecaa0 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 c173bd85..3bf2f2e4 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 f54963bd..2502b663 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 e77495e4..07d1b15f 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 31576dcb..aaf469c7 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 92267986..7e9fb071 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 e5ba6b20..a0b495ea 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 8c76959b..e5e8cb3d 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 18b10952..d50b4f66 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 57a16b16..e60933f4 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 8bd56f0a..1e73a9c8 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 b34a7280..c1dc2cfe 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 6df35ead..16c64ec6 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 d3243252..0b98f46b 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 c3fe9a80..c3d5a782 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 b34fbad1..4b07b57a 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 4458b6e0..6143049e 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 bca867c4..c37cf5df 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 7af2378f..38d1730e 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 0f933461..62b64ef6 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 aa5a1a40..424db645 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 bee573cd..406b463b 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 9b332c56..5d394d51 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 96684286..a66ad56e 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 2cc4beab..35432c68 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 da019172..9f9483b0 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 e5cea2ea..abe88f5a 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 a779d1e4..e6855143 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 5ad45fe5..fa0b81c3 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 de936040..8cc2bffc 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 f351736b..24a72d73 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 a862aecf..d57b7e78 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 6efb8e73..7790e5b9 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 4fa574ba..bf6fc44c 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 93ab0a40..e02a3471 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 75872d4a..cf9eea76 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 cce93060..0ea7f6de 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 78844115..2e69ba93 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 7e45606c..dffdbdd8 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 9bd5fe7c..d39483d4 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 e49ff2ad..22a97d63 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 1e73a9c8..8438d252 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 a0a6a3fb..f376329e 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 956219d3..90af1b2a 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 650285ad..7e7699dc 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 00000000..2b289e46 --- /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 55548d9b..cee003af 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 00000000..1080ed56 --- /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 7dd601c7..4fca7203 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 9f35b3c9..90a5c6f4 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 22a97d63..f828abab 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 2b289e46..f7f70073 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 cee003af..168fd41d 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 f1e6efb1..40c48281 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 90af1b2a..35a7eae1 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 067f3334..6c52573c 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 f7f70073..3939686a 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 6158fd50..7310abce 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 1080ed56..e0ce0738 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 35a7eae1..3a1277f0 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)