adcp 1.1.0__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adcp/__init__.py +187 -17
- adcp/client.py +12 -5
- adcp/protocols/base.py +5 -2
- adcp/types/generated.py +577 -60
- adcp/utils/response_parser.py +64 -15
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/METADATA +3 -1
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/RECORD +11 -11
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/WHEEL +0 -0
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/entry_points.txt +0 -0
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/licenses/LICENSE +0 -0
- {adcp-1.1.0.dist-info → adcp-1.2.1.dist-info}/top_level.txt +0 -0
adcp/__init__.py
CHANGED
|
@@ -20,33 +20,120 @@ from adcp.exceptions import (
|
|
|
20
20
|
)
|
|
21
21
|
from adcp.types.core import AgentConfig, Protocol, TaskResult, TaskStatus, WebhookMetadata
|
|
22
22
|
from adcp.types.generated import (
|
|
23
|
+
ActivateSignalError,
|
|
24
|
+
# Request/Response types
|
|
23
25
|
ActivateSignalRequest,
|
|
24
26
|
ActivateSignalResponse,
|
|
27
|
+
ActivateSignalSuccess,
|
|
28
|
+
ActivationKey,
|
|
29
|
+
AgentDeployment,
|
|
30
|
+
AgentDestination,
|
|
31
|
+
BothPreviewRender,
|
|
32
|
+
# Brand types
|
|
33
|
+
BrandManifest,
|
|
34
|
+
BrandManifestRef,
|
|
35
|
+
BuildCreativeRequest,
|
|
36
|
+
BuildCreativeResponse,
|
|
37
|
+
# Channel types
|
|
38
|
+
Channels,
|
|
39
|
+
CreateMediaBuyError,
|
|
25
40
|
CreateMediaBuyRequest,
|
|
26
41
|
CreateMediaBuyResponse,
|
|
42
|
+
CreateMediaBuySuccess,
|
|
43
|
+
# Creative types
|
|
44
|
+
CreativeAsset,
|
|
45
|
+
CreativeAssignment,
|
|
46
|
+
CreativeManifest,
|
|
47
|
+
CreativePolicy,
|
|
48
|
+
DaastAsset,
|
|
49
|
+
# Metrics types
|
|
50
|
+
DeliveryMetrics,
|
|
51
|
+
# Delivery types
|
|
52
|
+
DeliveryType,
|
|
53
|
+
Deployment,
|
|
54
|
+
# Deployment types
|
|
55
|
+
Destination,
|
|
56
|
+
Error,
|
|
57
|
+
Format,
|
|
58
|
+
FormatId,
|
|
59
|
+
FrequencyCap,
|
|
27
60
|
GetMediaBuyDeliveryRequest,
|
|
28
61
|
GetMediaBuyDeliveryResponse,
|
|
29
62
|
GetProductsRequest,
|
|
30
63
|
GetProductsResponse,
|
|
31
64
|
GetSignalsRequest,
|
|
32
65
|
GetSignalsResponse,
|
|
66
|
+
HtmlPreviewRender,
|
|
67
|
+
InlineDaastAsset,
|
|
68
|
+
InlineVastAsset,
|
|
69
|
+
Key_valueActivationKey,
|
|
33
70
|
ListAuthorizedPropertiesRequest,
|
|
34
71
|
ListAuthorizedPropertiesResponse,
|
|
35
72
|
ListCreativeFormatsRequest,
|
|
36
73
|
ListCreativeFormatsResponse,
|
|
37
74
|
ListCreativesRequest,
|
|
38
75
|
ListCreativesResponse,
|
|
76
|
+
Measurement,
|
|
77
|
+
# Core domain types
|
|
39
78
|
MediaBuy,
|
|
79
|
+
# Status enums
|
|
80
|
+
MediaBuyStatus,
|
|
81
|
+
# Sub-asset types
|
|
82
|
+
MediaSubAsset,
|
|
83
|
+
Pacing,
|
|
84
|
+
Package,
|
|
85
|
+
PackageStatus,
|
|
86
|
+
PerformanceFeedback,
|
|
87
|
+
Placement,
|
|
88
|
+
PlatformDeployment,
|
|
89
|
+
PlatformDestination,
|
|
90
|
+
PreviewCreativeRequest,
|
|
91
|
+
PreviewCreativeResponse,
|
|
92
|
+
# Preview render types
|
|
93
|
+
PreviewRender,
|
|
94
|
+
PricingModel,
|
|
95
|
+
# Pricing types
|
|
96
|
+
PricingOption,
|
|
40
97
|
Product,
|
|
98
|
+
PromotedProducts,
|
|
99
|
+
# Property and placement types
|
|
100
|
+
Property,
|
|
101
|
+
ProtocolEnvelope,
|
|
41
102
|
ProvidePerformanceFeedbackRequest,
|
|
42
103
|
ProvidePerformanceFeedbackResponse,
|
|
104
|
+
PushNotificationConfig,
|
|
105
|
+
ReportingCapabilities,
|
|
106
|
+
Response,
|
|
107
|
+
Segment_idActivationKey,
|
|
108
|
+
StandardFormatIds,
|
|
109
|
+
StartTiming,
|
|
110
|
+
SubAsset,
|
|
111
|
+
SyncCreativesError,
|
|
43
112
|
SyncCreativesRequest,
|
|
44
113
|
SyncCreativesResponse,
|
|
114
|
+
SyncCreativesSuccess,
|
|
115
|
+
# Targeting types
|
|
116
|
+
Targeting,
|
|
117
|
+
# Task types
|
|
118
|
+
TaskType,
|
|
119
|
+
TextSubAsset,
|
|
120
|
+
UpdateMediaBuyError,
|
|
45
121
|
UpdateMediaBuyRequest,
|
|
46
122
|
UpdateMediaBuyResponse,
|
|
123
|
+
UpdateMediaBuySuccess,
|
|
124
|
+
UrlDaastAsset,
|
|
125
|
+
UrlPreviewRender,
|
|
126
|
+
UrlVastAsset,
|
|
127
|
+
# Asset delivery types (VAST/DAAST)
|
|
128
|
+
VastAsset,
|
|
129
|
+
# Protocol types
|
|
130
|
+
WebhookPayload,
|
|
131
|
+
)
|
|
132
|
+
from adcp.types.generated import (
|
|
133
|
+
TaskStatus as GeneratedTaskStatus,
|
|
47
134
|
)
|
|
48
135
|
|
|
49
|
-
__version__ = "1.1
|
|
136
|
+
__version__ = "1.2.1"
|
|
50
137
|
|
|
51
138
|
__all__ = [
|
|
52
139
|
# Client classes
|
|
@@ -67,30 +154,113 @@ __all__ = [
|
|
|
67
154
|
"ADCPToolNotFoundError",
|
|
68
155
|
"ADCPWebhookError",
|
|
69
156
|
"ADCPWebhookSignatureError",
|
|
70
|
-
#
|
|
71
|
-
"
|
|
72
|
-
"
|
|
157
|
+
# Request/Response types
|
|
158
|
+
"ActivateSignalRequest",
|
|
159
|
+
"ActivateSignalResponse",
|
|
160
|
+
"ActivateSignalSuccess",
|
|
161
|
+
"ActivateSignalError",
|
|
162
|
+
"ActivationKey",
|
|
163
|
+
"Segment_idActivationKey",
|
|
164
|
+
"Key_valueActivationKey",
|
|
165
|
+
"BuildCreativeRequest",
|
|
166
|
+
"BuildCreativeResponse",
|
|
73
167
|
"CreateMediaBuyRequest",
|
|
74
168
|
"CreateMediaBuyResponse",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"SyncCreativesRequest",
|
|
78
|
-
"SyncCreativesResponse",
|
|
79
|
-
"ListCreativesRequest",
|
|
80
|
-
"ListCreativesResponse",
|
|
81
|
-
"ListCreativeFormatsRequest",
|
|
82
|
-
"ListCreativeFormatsResponse",
|
|
169
|
+
"CreateMediaBuySuccess",
|
|
170
|
+
"CreateMediaBuyError",
|
|
83
171
|
"GetMediaBuyDeliveryRequest",
|
|
84
172
|
"GetMediaBuyDeliveryResponse",
|
|
85
|
-
"
|
|
86
|
-
"
|
|
173
|
+
"GetProductsRequest",
|
|
174
|
+
"GetProductsResponse",
|
|
87
175
|
"GetSignalsRequest",
|
|
88
176
|
"GetSignalsResponse",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
177
|
+
"ListAuthorizedPropertiesRequest",
|
|
178
|
+
"ListAuthorizedPropertiesResponse",
|
|
179
|
+
"ListCreativeFormatsRequest",
|
|
180
|
+
"ListCreativeFormatsResponse",
|
|
181
|
+
"ListCreativesRequest",
|
|
182
|
+
"ListCreativesResponse",
|
|
183
|
+
"PreviewCreativeRequest",
|
|
184
|
+
"PreviewCreativeResponse",
|
|
91
185
|
"ProvidePerformanceFeedbackRequest",
|
|
92
186
|
"ProvidePerformanceFeedbackResponse",
|
|
187
|
+
"SyncCreativesRequest",
|
|
188
|
+
"SyncCreativesResponse",
|
|
189
|
+
"SyncCreativesSuccess",
|
|
190
|
+
"SyncCreativesError",
|
|
191
|
+
"UpdateMediaBuyRequest",
|
|
192
|
+
"UpdateMediaBuyResponse",
|
|
193
|
+
"UpdateMediaBuySuccess",
|
|
194
|
+
"UpdateMediaBuyError",
|
|
93
195
|
# Core domain types
|
|
94
|
-
"Product",
|
|
95
196
|
"MediaBuy",
|
|
197
|
+
"Product",
|
|
198
|
+
"Package",
|
|
199
|
+
"Error",
|
|
200
|
+
# Creative types
|
|
201
|
+
"CreativeAsset",
|
|
202
|
+
"CreativeManifest",
|
|
203
|
+
"CreativeAssignment",
|
|
204
|
+
"CreativePolicy",
|
|
205
|
+
"Format",
|
|
206
|
+
"FormatId",
|
|
207
|
+
# Property and placement types
|
|
208
|
+
"Property",
|
|
209
|
+
"Placement",
|
|
210
|
+
# Targeting types
|
|
211
|
+
"Targeting",
|
|
212
|
+
"FrequencyCap",
|
|
213
|
+
"Pacing",
|
|
214
|
+
# Brand types
|
|
215
|
+
"BrandManifest",
|
|
216
|
+
"BrandManifestRef",
|
|
217
|
+
# Metrics types
|
|
218
|
+
"DeliveryMetrics",
|
|
219
|
+
"Measurement",
|
|
220
|
+
"PerformanceFeedback",
|
|
221
|
+
# Status enums
|
|
222
|
+
"MediaBuyStatus",
|
|
223
|
+
"PackageStatus",
|
|
224
|
+
# Pricing types
|
|
225
|
+
"PricingOption",
|
|
226
|
+
"PricingModel",
|
|
227
|
+
# Delivery types
|
|
228
|
+
"DeliveryType",
|
|
229
|
+
"StartTiming",
|
|
230
|
+
# Channel types
|
|
231
|
+
"Channels",
|
|
232
|
+
"StandardFormatIds",
|
|
233
|
+
# Protocol types
|
|
234
|
+
"WebhookPayload",
|
|
235
|
+
"ProtocolEnvelope",
|
|
236
|
+
"Response",
|
|
237
|
+
"PromotedProducts",
|
|
238
|
+
"PushNotificationConfig",
|
|
239
|
+
"ReportingCapabilities",
|
|
240
|
+
# Deployment types
|
|
241
|
+
"Destination",
|
|
242
|
+
"Deployment",
|
|
243
|
+
"PlatformDestination",
|
|
244
|
+
"AgentDestination",
|
|
245
|
+
"PlatformDeployment",
|
|
246
|
+
"AgentDeployment",
|
|
247
|
+
# Sub-asset types
|
|
248
|
+
"MediaSubAsset",
|
|
249
|
+
"SubAsset",
|
|
250
|
+
"TextSubAsset",
|
|
251
|
+
# Asset delivery types (VAST/DAAST)
|
|
252
|
+
"VastAsset",
|
|
253
|
+
"UrlVastAsset",
|
|
254
|
+
"InlineVastAsset",
|
|
255
|
+
"DaastAsset",
|
|
256
|
+
"UrlDaastAsset",
|
|
257
|
+
"InlineDaastAsset",
|
|
258
|
+
# Preview render types
|
|
259
|
+
"PreviewRender",
|
|
260
|
+
"UrlPreviewRender",
|
|
261
|
+
"HtmlPreviewRender",
|
|
262
|
+
"BothPreviewRender",
|
|
263
|
+
# Task types
|
|
264
|
+
"TaskType",
|
|
265
|
+
"GeneratedTaskStatus",
|
|
96
266
|
]
|
adcp/client.py
CHANGED
|
@@ -11,6 +11,8 @@ from collections.abc import Callable
|
|
|
11
11
|
from datetime import datetime, timezone
|
|
12
12
|
from typing import Any
|
|
13
13
|
|
|
14
|
+
from pydantic import BaseModel
|
|
15
|
+
|
|
14
16
|
from adcp.exceptions import ADCPWebhookSignatureError
|
|
15
17
|
from adcp.protocols.a2a import A2AAdapter
|
|
16
18
|
from adcp.protocols.base import ProtocolAdapter
|
|
@@ -154,7 +156,9 @@ class ADCPClient:
|
|
|
154
156
|
)
|
|
155
157
|
)
|
|
156
158
|
|
|
157
|
-
result = self.adapter._parse_response(
|
|
159
|
+
result: TaskResult[GetProductsResponse] = self.adapter._parse_response(
|
|
160
|
+
raw_result, GetProductsResponse
|
|
161
|
+
)
|
|
158
162
|
|
|
159
163
|
if fetch_previews and result.success and result.data and creative_agent_client:
|
|
160
164
|
from adcp.utils.preview_cache import add_preview_urls_to_products
|
|
@@ -215,7 +219,9 @@ class ADCPClient:
|
|
|
215
219
|
)
|
|
216
220
|
)
|
|
217
221
|
|
|
218
|
-
result = self.adapter._parse_response(
|
|
222
|
+
result: TaskResult[ListCreativeFormatsResponse] = self.adapter._parse_response(
|
|
223
|
+
raw_result, ListCreativeFormatsResponse
|
|
224
|
+
)
|
|
219
225
|
|
|
220
226
|
if fetch_previews and result.success and result.data:
|
|
221
227
|
from adcp.utils.preview_cache import add_preview_urls_to_formats
|
|
@@ -617,15 +623,16 @@ class ADCPClient:
|
|
|
617
623
|
from adcp.utils.response_parser import parse_json_or_text
|
|
618
624
|
|
|
619
625
|
# Map task types to their response types (using string literals, not enum)
|
|
620
|
-
|
|
626
|
+
# Note: Some response types are Union types (e.g., ActivateSignalResponse = Success | Error)
|
|
627
|
+
response_type_map: dict[str, type[BaseModel] | Any] = {
|
|
621
628
|
"get_products": GetProductsResponse,
|
|
622
629
|
"list_creative_formats": ListCreativeFormatsResponse,
|
|
623
|
-
"sync_creatives": SyncCreativesResponse,
|
|
630
|
+
"sync_creatives": SyncCreativesResponse, # Union type
|
|
624
631
|
"list_creatives": ListCreativesResponse,
|
|
625
632
|
"get_media_buy_delivery": GetMediaBuyDeliveryResponse,
|
|
626
633
|
"list_authorized_properties": ListAuthorizedPropertiesResponse,
|
|
627
634
|
"get_signals": GetSignalsResponse,
|
|
628
|
-
"activate_signal": ActivateSignalResponse,
|
|
635
|
+
"activate_signal": ActivateSignalResponse, # Union type
|
|
629
636
|
"provide_performance_feedback": ProvidePerformanceFeedbackResponse,
|
|
630
637
|
}
|
|
631
638
|
|
adcp/protocols/base.py
CHANGED
|
@@ -30,15 +30,18 @@ class ProtocolAdapter(ABC):
|
|
|
30
30
|
# Helper methods for response parsing
|
|
31
31
|
# ========================================================================
|
|
32
32
|
|
|
33
|
-
def _parse_response(
|
|
33
|
+
def _parse_response(
|
|
34
|
+
self, raw_result: TaskResult[Any], response_type: type[T] | Any
|
|
35
|
+
) -> TaskResult[T]:
|
|
34
36
|
"""
|
|
35
37
|
Parse raw TaskResult into typed TaskResult.
|
|
36
38
|
|
|
37
39
|
Handles both MCP content arrays and A2A dict responses.
|
|
40
|
+
Supports both single types and Union types (for oneOf discriminated unions).
|
|
38
41
|
|
|
39
42
|
Args:
|
|
40
43
|
raw_result: Raw TaskResult from adapter
|
|
41
|
-
response_type: Expected Pydantic response type
|
|
44
|
+
response_type: Expected Pydantic response type (can be a Union type)
|
|
42
45
|
|
|
43
46
|
Returns:
|
|
44
47
|
Typed TaskResult
|
adcp/types/generated.py
CHANGED
|
@@ -14,19 +14,9 @@ from __future__ import annotations
|
|
|
14
14
|
import re
|
|
15
15
|
from typing import Any, Literal
|
|
16
16
|
|
|
17
|
-
from pydantic import BaseModel, Field, field_validator
|
|
17
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
# ============================================================================
|
|
21
|
-
# MISSING SCHEMA TYPES (referenced but not provided by upstream)
|
|
22
|
-
# ============================================================================
|
|
23
|
-
|
|
24
|
-
# These types are referenced in schemas but don't have schema files
|
|
25
|
-
# Defining them as type aliases to maintain type safety
|
|
26
|
-
PackageRequest = dict[str, Any]
|
|
27
|
-
PushNotificationConfig = dict[str, Any]
|
|
28
|
-
ReportingCapabilities = dict[str, Any]
|
|
29
|
-
|
|
30
20
|
|
|
31
21
|
# ============================================================================
|
|
32
22
|
# CORE DOMAIN TYPES
|
|
@@ -125,9 +115,22 @@ class BrandManifest(BaseModel):
|
|
|
125
115
|
metadata: dict[str, Any] | None = Field(None, description="Additional brand metadata")
|
|
126
116
|
|
|
127
117
|
|
|
128
|
-
# Type alias for Brand Manifest Reference
|
|
129
118
|
# Brand manifest provided either as an inline object or a URL string pointing to a hosted manifest
|
|
130
|
-
|
|
119
|
+
|
|
120
|
+
class BrandManifestRefVariant1(BaseModel):
|
|
121
|
+
"""Inline brand manifest object"""
|
|
122
|
+
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class BrandManifestRefVariant2(BaseModel):
|
|
127
|
+
"""URL to a hosted brand manifest JSON file. The manifest at this URL must conform to the brand-manifest.json schema."""
|
|
128
|
+
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Union type for Brand Manifest Reference
|
|
133
|
+
BrandManifestRef = BrandManifestRefVariant1 | BrandManifestRefVariant2
|
|
131
134
|
|
|
132
135
|
|
|
133
136
|
class Format(BaseModel):
|
|
@@ -255,18 +258,46 @@ class PerformanceFeedback(BaseModel):
|
|
|
255
258
|
applied_at: str | None = Field(None, description="ISO 8601 timestamp when feedback was applied to optimization algorithms")
|
|
256
259
|
|
|
257
260
|
|
|
258
|
-
# Type alias for Start Timing
|
|
259
261
|
# Campaign start timing: 'asap' or ISO 8601 date-time
|
|
260
|
-
StartTiming = Any
|
|
261
262
|
|
|
263
|
+
class StartTimingVariant1(BaseModel):
|
|
264
|
+
"""Start campaign as soon as possible"""
|
|
265
|
+
|
|
266
|
+
pass
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class StartTimingVariant2(BaseModel):
|
|
270
|
+
"""Scheduled start date/time in ISO 8601 format"""
|
|
271
|
+
|
|
272
|
+
pass
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# Union type for Start Timing
|
|
276
|
+
StartTiming = StartTimingVariant1 | StartTimingVariant2
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# Sub-asset for multi-asset creative formats, including carousel images and native ad template variables
|
|
280
|
+
|
|
281
|
+
class MediaSubAsset(BaseModel):
|
|
282
|
+
model_config = ConfigDict(extra="forbid")
|
|
262
283
|
|
|
263
|
-
|
|
264
|
-
|
|
284
|
+
asset_kind: Literal["media"] = Field(description="Discriminator indicating this is a media asset with content_uri")
|
|
285
|
+
asset_type: str = Field(description="Type of asset. Common types: thumbnail_image, product_image, featured_image, logo")
|
|
286
|
+
asset_id: str = Field(description="Unique identifier for the asset within the creative")
|
|
287
|
+
content_uri: str = Field(description="URL for media assets (images, videos, etc.)")
|
|
265
288
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
289
|
+
|
|
290
|
+
class TextSubAsset(BaseModel):
|
|
291
|
+
model_config = ConfigDict(extra="forbid")
|
|
292
|
+
|
|
293
|
+
asset_kind: Literal["text"] = Field(description="Discriminator indicating this is a text asset with content")
|
|
294
|
+
asset_type: str = Field(description="Type of asset. Common types: headline, body_text, cta_text, price_text, sponsor_name, author_name, click_url")
|
|
295
|
+
asset_id: str = Field(description="Unique identifier for the asset within the creative")
|
|
296
|
+
content: Any = Field(description="Text content for text-based assets like headlines, body text, CTA text, etc.")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# Union type for Sub-Asset
|
|
300
|
+
SubAsset = MediaSubAsset | TextSubAsset
|
|
270
301
|
|
|
271
302
|
|
|
272
303
|
class WebhookPayload(BaseModel):
|
|
@@ -281,7 +312,7 @@ class WebhookPayload(BaseModel):
|
|
|
281
312
|
message: str | None = Field(None, description="Human-readable summary of the current task state. Provides context about what happened and what action may be needed.")
|
|
282
313
|
context_id: str | None = Field(None, description="Session/conversation identifier. Use this to continue the conversation if input-required status needs clarification or additional parameters.")
|
|
283
314
|
progress: dict[str, Any] | None = Field(None, description="Progress information for tasks still in 'working' state. Rarely seen in webhooks since 'working' tasks typically complete synchronously, but may appear if a task transitions from 'submitted' to 'working'.")
|
|
284
|
-
result: Any | None = Field(None, description="Task-specific payload for this status update.
|
|
315
|
+
result: Any | None = Field(None, description="Task-specific payload for this status update. Validated against the appropriate response schema based on task_type.")
|
|
285
316
|
error: Any | None = Field(None, description="Error message for failed tasks. Only present when status is 'failed'.")
|
|
286
317
|
|
|
287
318
|
|
|
@@ -314,6 +345,97 @@ class PromotedProducts(BaseModel):
|
|
|
314
345
|
manifest_query: str | None = Field(None, description="Natural language query to select products from the brand manifest (e.g., 'all Kraft Heinz pasta sauces', 'organic products under $20')")
|
|
315
346
|
|
|
316
347
|
|
|
348
|
+
# A destination platform where signals can be activated (DSP, sales agent, etc.)
|
|
349
|
+
|
|
350
|
+
class PlatformDestination(BaseModel):
|
|
351
|
+
model_config = ConfigDict(extra="forbid")
|
|
352
|
+
|
|
353
|
+
type: Literal["platform"] = Field(description="Discriminator indicating this is a platform-based destination")
|
|
354
|
+
platform: str = Field(description="Platform identifier for DSPs (e.g., 'the-trade-desk', 'amazon-dsp')")
|
|
355
|
+
account: str | None = Field(None, description="Optional account identifier on the platform")
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class AgentDestination(BaseModel):
|
|
359
|
+
model_config = ConfigDict(extra="forbid")
|
|
360
|
+
|
|
361
|
+
type: Literal["agent"] = Field(description="Discriminator indicating this is an agent URL-based destination")
|
|
362
|
+
agent_url: str = Field(description="URL identifying the destination agent (for sales agents, etc.)")
|
|
363
|
+
account: str | None = Field(None, description="Optional account identifier on the agent")
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
# Union type for Destination
|
|
367
|
+
Destination = PlatformDestination | AgentDestination
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
# A signal deployment to a specific destination platform with activation status and key
|
|
371
|
+
|
|
372
|
+
class PlatformDeployment(BaseModel):
|
|
373
|
+
model_config = ConfigDict(extra="forbid")
|
|
374
|
+
|
|
375
|
+
type: Literal["platform"] = Field(description="Discriminator indicating this is a platform-based deployment")
|
|
376
|
+
platform: str = Field(description="Platform identifier for DSPs")
|
|
377
|
+
account: str | None = Field(None, description="Account identifier if applicable")
|
|
378
|
+
is_live: bool = Field(description="Whether signal is currently active on this destination")
|
|
379
|
+
activation_key: ActivationKey | None = Field(None, description="The key to use for targeting. Only present if is_live=true AND requester has access to this destination.")
|
|
380
|
+
estimated_activation_duration_minutes: float | None = Field(None, description="Estimated time to activate if not live, or to complete activation if in progress")
|
|
381
|
+
deployed_at: str | None = Field(None, description="Timestamp when activation completed (if is_live=true)")
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class AgentDeployment(BaseModel):
|
|
385
|
+
model_config = ConfigDict(extra="forbid")
|
|
386
|
+
|
|
387
|
+
type: Literal["agent"] = Field(description="Discriminator indicating this is an agent URL-based deployment")
|
|
388
|
+
agent_url: str = Field(description="URL identifying the destination agent")
|
|
389
|
+
account: str | None = Field(None, description="Account identifier if applicable")
|
|
390
|
+
is_live: bool = Field(description="Whether signal is currently active on this destination")
|
|
391
|
+
activation_key: ActivationKey | None = Field(None, description="The key to use for targeting. Only present if is_live=true AND requester has access to this destination.")
|
|
392
|
+
estimated_activation_duration_minutes: float | None = Field(None, description="Estimated time to activate if not live, or to complete activation if in progress")
|
|
393
|
+
deployed_at: str | None = Field(None, description="Timestamp when activation completed (if is_live=true)")
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
# Union type for Deployment
|
|
397
|
+
Deployment = PlatformDeployment | AgentDeployment
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
# 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.
|
|
401
|
+
|
|
402
|
+
class Segment_idActivationKey(BaseModel):
|
|
403
|
+
model_config = ConfigDict(extra="forbid")
|
|
404
|
+
|
|
405
|
+
type: Literal["segment_id"] = Field(description="Segment ID based targeting")
|
|
406
|
+
segment_id: str = Field(description="The platform-specific segment identifier to use in campaign targeting")
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class Key_valueActivationKey(BaseModel):
|
|
410
|
+
model_config = ConfigDict(extra="forbid")
|
|
411
|
+
|
|
412
|
+
type: Literal["key_value"] = Field(description="Key-value pair based targeting")
|
|
413
|
+
key: str = Field(description="The targeting parameter key")
|
|
414
|
+
value: str = Field(description="The targeting parameter value")
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
# Union type for Activation Key
|
|
418
|
+
ActivationKey = Segment_idActivationKey | Key_valueActivationKey
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class PushNotificationConfig(BaseModel):
|
|
422
|
+
"""Webhook configuration for asynchronous task notifications. Uses A2A-compatible PushNotificationConfig structure. Supports Bearer tokens (simple) or HMAC signatures (production-recommended)."""
|
|
423
|
+
|
|
424
|
+
url: str = Field(description="Webhook endpoint URL for task status notifications")
|
|
425
|
+
token: str | None = Field(None, description="Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.")
|
|
426
|
+
authentication: dict[str, Any] = Field(description="Authentication configuration for webhook delivery (A2A-compatible)")
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
class ReportingCapabilities(BaseModel):
|
|
430
|
+
"""Reporting capabilities available for a product"""
|
|
431
|
+
|
|
432
|
+
available_reporting_frequencies: list[Literal["hourly", "daily", "monthly"]] = Field(description="Supported reporting frequency options")
|
|
433
|
+
expected_delay_minutes: int = Field(description="Expected delay in minutes before reporting data becomes available (e.g., 240 for 4-hour delay)")
|
|
434
|
+
timezone: str = Field(description="Timezone for reporting periods. Use 'UTC' or IANA timezone (e.g., 'America/New_York'). Critical for daily/monthly frequency alignment.")
|
|
435
|
+
supports_webhooks: bool = Field(description="Whether this product supports webhook-based reporting notifications")
|
|
436
|
+
available_metrics: list[Literal["impressions", "spend", "clicks", "ctr", "video_completions", "completion_rate", "conversions", "viewability", "engagement_rate"]] = Field(description="Metrics available in reporting. Impressions and spend are always implicitly included.")
|
|
437
|
+
|
|
438
|
+
|
|
317
439
|
# Type alias for Advertising Channels
|
|
318
440
|
# Standard advertising channels supported by AdCP
|
|
319
441
|
Channels = Literal["display", "video", "audio", "native", "dooh", "ctv", "podcast", "retail", "social"]
|
|
@@ -354,9 +476,46 @@ TaskStatus = Literal["submitted", "working", "input-required", "completed", "can
|
|
|
354
476
|
PricingModel = Literal["cpm", "vcpm", "cpc", "cpcv", "cpv", "cpp", "flat_rate"]
|
|
355
477
|
|
|
356
478
|
|
|
357
|
-
# Type alias for Pricing Option
|
|
358
479
|
# A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.
|
|
359
|
-
|
|
480
|
+
|
|
481
|
+
class PricingOptionVariant1(BaseModel):
|
|
482
|
+
pass
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class PricingOptionVariant2(BaseModel):
|
|
486
|
+
pass
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
class PricingOptionVariant3(BaseModel):
|
|
490
|
+
pass
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
class PricingOptionVariant4(BaseModel):
|
|
494
|
+
pass
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class PricingOptionVariant5(BaseModel):
|
|
498
|
+
pass
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class PricingOptionVariant6(BaseModel):
|
|
502
|
+
pass
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
class PricingOptionVariant7(BaseModel):
|
|
506
|
+
pass
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
class PricingOptionVariant8(BaseModel):
|
|
510
|
+
pass
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
class PricingOptionVariant9(BaseModel):
|
|
514
|
+
pass
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
# Union type for Pricing Option
|
|
518
|
+
PricingOption = PricingOptionVariant1 | PricingOptionVariant2 | PricingOptionVariant3 | PricingOptionVariant4 | PricingOptionVariant5 | PricingOptionVariant6 | PricingOptionVariant7 | PricingOptionVariant8 | PricingOptionVariant9
|
|
360
519
|
|
|
361
520
|
|
|
362
521
|
# Type alias for Standard Format IDs
|
|
@@ -364,17 +523,118 @@ PricingOption = Any
|
|
|
364
523
|
StandardFormatIds = Literal["display_300x250", "display_728x90", "display_320x50", "display_160x600", "display_970x250", "display_336x280", "display_expandable_300x250", "display_expandable_728x90", "display_interstitial_320x480", "display_interstitial_desktop", "display_dynamic_300x250", "display_responsive", "native_in_feed", "native_content_recommendation", "native_product", "video_skippable_15s", "video_skippable_30s", "video_non_skippable_15s", "video_non_skippable_30s", "video_outstream_autoplay", "video_vertical_story", "video_rewarded_30s", "video_pause_ad", "video_ctv_non_skippable_30s", "audio_standard_15s", "audio_standard_30s", "audio_podcast_host_read", "audio_programmatic", "universal_carousel", "universal_canvas", "universal_takeover", "universal_gallery", "universal_reveal", "dooh_landscape_static", "dooh_portrait_video"]
|
|
365
524
|
|
|
366
525
|
|
|
526
|
+
# VAST (Video Ad Serving Template) tag for third-party video ad serving
|
|
527
|
+
|
|
528
|
+
class UrlVastAsset(BaseModel):
|
|
529
|
+
model_config = ConfigDict(extra="forbid")
|
|
530
|
+
|
|
531
|
+
delivery_type: Literal["url"] = Field(description="Discriminator indicating VAST is delivered via URL endpoint")
|
|
532
|
+
url: str = Field(description="URL endpoint that returns VAST XML")
|
|
533
|
+
vast_version: Literal["2.0", "3.0", "4.0", "4.1", "4.2"] | None = Field(None, description="VAST specification version")
|
|
534
|
+
vpaid_enabled: bool | None = Field(None, description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
|
|
535
|
+
duration_ms: int | None = Field(None, description="Expected video duration in milliseconds (if known)")
|
|
536
|
+
tracking_events: list[Literal["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "impression", "click", "pause", "resume", "skip", "mute", "unmute", "fullscreen", "exitFullscreen", "playerExpand", "playerCollapse"]] | None = Field(None, description="Tracking events supported by this VAST tag")
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
class InlineVastAsset(BaseModel):
|
|
540
|
+
model_config = ConfigDict(extra="forbid")
|
|
541
|
+
|
|
542
|
+
delivery_type: Literal["inline"] = Field(description="Discriminator indicating VAST is delivered as inline XML content")
|
|
543
|
+
content: str = Field(description="Inline VAST XML content")
|
|
544
|
+
vast_version: Literal["2.0", "3.0", "4.0", "4.1", "4.2"] | None = Field(None, description="VAST specification version")
|
|
545
|
+
vpaid_enabled: bool | None = Field(None, description="Whether VPAID (Video Player-Ad Interface Definition) is supported")
|
|
546
|
+
duration_ms: int | None = Field(None, description="Expected video duration in milliseconds (if known)")
|
|
547
|
+
tracking_events: list[Literal["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "impression", "click", "pause", "resume", "skip", "mute", "unmute", "fullscreen", "exitFullscreen", "playerExpand", "playerCollapse"]] | None = Field(None, description="Tracking events supported by this VAST tag")
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
# Union type for VAST Asset
|
|
551
|
+
VastAsset = UrlVastAsset | InlineVastAsset
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
# DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving
|
|
555
|
+
|
|
556
|
+
class UrlDaastAsset(BaseModel):
|
|
557
|
+
model_config = ConfigDict(extra="forbid")
|
|
558
|
+
|
|
559
|
+
delivery_type: Literal["url"] = Field(description="Discriminator indicating DAAST is delivered via URL endpoint")
|
|
560
|
+
url: str = Field(description="URL endpoint that returns DAAST XML")
|
|
561
|
+
daast_version: Literal["1.0", "1.1"] | None = Field(None, description="DAAST specification version")
|
|
562
|
+
duration_ms: int | None = Field(None, description="Expected audio duration in milliseconds (if known)")
|
|
563
|
+
tracking_events: list[Literal["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "impression", "pause", "resume", "skip", "mute", "unmute"]] | None = Field(None, description="Tracking events supported by this DAAST tag")
|
|
564
|
+
companion_ads: bool | None = Field(None, description="Whether companion display ads are included")
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
class InlineDaastAsset(BaseModel):
|
|
568
|
+
model_config = ConfigDict(extra="forbid")
|
|
569
|
+
|
|
570
|
+
delivery_type: Literal["inline"] = Field(description="Discriminator indicating DAAST is delivered as inline XML content")
|
|
571
|
+
content: str = Field(description="Inline DAAST XML content")
|
|
572
|
+
daast_version: Literal["1.0", "1.1"] | None = Field(None, description="DAAST specification version")
|
|
573
|
+
duration_ms: int | None = Field(None, description="Expected audio duration in milliseconds (if known)")
|
|
574
|
+
tracking_events: list[Literal["start", "firstQuartile", "midpoint", "thirdQuartile", "complete", "impression", "pause", "resume", "skip", "mute", "unmute"]] | None = Field(None, description="Tracking events supported by this DAAST tag")
|
|
575
|
+
companion_ads: bool | None = Field(None, description="Whether companion display ads are included")
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
# Union type for DAAST Asset
|
|
579
|
+
DaastAsset = UrlDaastAsset | InlineDaastAsset
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
# A single rendered piece of a creative preview with discriminated output format
|
|
583
|
+
|
|
584
|
+
class UrlPreviewRender(BaseModel):
|
|
585
|
+
"""URL-only preview format"""
|
|
586
|
+
|
|
587
|
+
model_config = ConfigDict(extra="forbid")
|
|
588
|
+
|
|
589
|
+
render_id: str = Field(description="Unique identifier for this rendered piece within the variant")
|
|
590
|
+
output_format: Literal["url"] = Field(description="Discriminator indicating preview_url is provided")
|
|
591
|
+
preview_url: str = Field(description="URL to an HTML page that renders this piece. Can be embedded in an iframe.")
|
|
592
|
+
role: str = Field(description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.")
|
|
593
|
+
dimensions: dict[str, Any] | None = Field(None, description="Dimensions for this rendered piece")
|
|
594
|
+
embedding: dict[str, Any] | None = Field(None, description="Optional security and embedding metadata for safe iframe integration")
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class HtmlPreviewRender(BaseModel):
|
|
598
|
+
"""HTML-only preview format"""
|
|
599
|
+
|
|
600
|
+
model_config = ConfigDict(extra="forbid")
|
|
601
|
+
|
|
602
|
+
render_id: str = Field(description="Unique identifier for this rendered piece within the variant")
|
|
603
|
+
output_format: Literal["html"] = Field(description="Discriminator indicating preview_html is provided")
|
|
604
|
+
preview_html: str = Field(description="Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.")
|
|
605
|
+
role: str = Field(description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.")
|
|
606
|
+
dimensions: dict[str, Any] | None = Field(None, description="Dimensions for this rendered piece")
|
|
607
|
+
embedding: dict[str, Any] | None = Field(None, description="Optional security and embedding metadata")
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
class BothPreviewRender(BaseModel):
|
|
611
|
+
"""Both URL and HTML preview format"""
|
|
612
|
+
|
|
613
|
+
model_config = ConfigDict(extra="forbid")
|
|
614
|
+
|
|
615
|
+
render_id: str = Field(description="Unique identifier for this rendered piece within the variant")
|
|
616
|
+
output_format: Literal["both"] = Field(description="Discriminator indicating both preview_url and preview_html are provided")
|
|
617
|
+
preview_url: str = Field(description="URL to an HTML page that renders this piece. Can be embedded in an iframe.")
|
|
618
|
+
preview_html: str = Field(description="Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.")
|
|
619
|
+
role: str = Field(description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.")
|
|
620
|
+
dimensions: dict[str, Any] | None = Field(None, description="Dimensions for this rendered piece")
|
|
621
|
+
embedding: dict[str, Any] | None = Field(None, description="Optional security and embedding metadata for safe iframe integration")
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
# Union type for Preview Render
|
|
625
|
+
PreviewRender = UrlPreviewRender | HtmlPreviewRender | BothPreviewRender
|
|
626
|
+
|
|
627
|
+
|
|
367
628
|
|
|
368
629
|
# ============================================================================
|
|
369
630
|
# TASK REQUEST/RESPONSE TYPES
|
|
370
631
|
# ============================================================================
|
|
371
632
|
|
|
372
633
|
class ActivateSignalRequest(BaseModel):
|
|
373
|
-
"""Request parameters for activating a signal on a specific
|
|
634
|
+
"""Request parameters for activating a signal on a specific destination"""
|
|
374
635
|
|
|
375
636
|
signal_agent_segment_id: str = Field(description="The universal identifier for the signal to activate")
|
|
376
|
-
|
|
377
|
-
account: str | None = Field(None, description="Account identifier (required for account-specific activation)")
|
|
637
|
+
destinations: list[Destination] = Field(description="Target destination(s) for activation. If the authenticated caller matches one of these destinations, activation keys will be included in the response.")
|
|
378
638
|
|
|
379
639
|
|
|
380
640
|
class BuildCreativeRequest(BaseModel):
|
|
@@ -419,7 +679,7 @@ class GetSignalsRequest(BaseModel):
|
|
|
419
679
|
"""Request parameters for discovering signals based on description"""
|
|
420
680
|
|
|
421
681
|
signal_spec: str = Field(description="Natural language description of the desired signals")
|
|
422
|
-
deliver_to: dict[str, Any] = Field(description="
|
|
682
|
+
deliver_to: dict[str, Any] = Field(description="Destination platforms where signals need to be activated")
|
|
423
683
|
filters: dict[str, Any] | None = Field(None, description="Filters to refine results")
|
|
424
684
|
max_results: int | None = Field(None, description="Maximum number of results to return")
|
|
425
685
|
|
|
@@ -456,6 +716,21 @@ class ListCreativesRequest(BaseModel):
|
|
|
456
716
|
fields: list[Literal["creative_id", "name", "format", "status", "created_date", "updated_date", "tags", "assignments", "performance", "sub_assets"]] | None = Field(None, description="Specific fields to include in response (omit for all fields)")
|
|
457
717
|
|
|
458
718
|
|
|
719
|
+
class PackageRequest(BaseModel):
|
|
720
|
+
"""Package configuration for media buy creation"""
|
|
721
|
+
|
|
722
|
+
buyer_ref: str = Field(description="Buyer's reference identifier for this package")
|
|
723
|
+
product_id: str = Field(description="Product ID for this package")
|
|
724
|
+
format_ids: list[FormatId] | None = Field(None, description="Array of format IDs that will be used for this package - must be supported by the product. If omitted, defaults to all formats supported by the product.")
|
|
725
|
+
budget: float = Field(description="Budget allocation for this package in the media buy's currency")
|
|
726
|
+
pacing: Pacing | None = None
|
|
727
|
+
pricing_option_id: str = Field(description="ID of the selected pricing option from the product's pricing_options array")
|
|
728
|
+
bid_price: float | None = Field(None, description="Bid price for auction-based CPM pricing (required if using cpm-auction-option)")
|
|
729
|
+
targeting_overlay: Targeting | None = None
|
|
730
|
+
creative_ids: list[str] | None = Field(None, description="Creative IDs to assign to this package at creation time (references existing library creatives)")
|
|
731
|
+
creatives: list[CreativeAsset] | None = Field(None, description="Full creative objects to upload and assign to this package at creation time (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.")
|
|
732
|
+
|
|
733
|
+
|
|
459
734
|
class ProvidePerformanceFeedbackRequest(BaseModel):
|
|
460
735
|
"""Request payload for provide_performance_feedback task"""
|
|
461
736
|
|
|
@@ -480,6 +755,22 @@ class SyncCreativesRequest(BaseModel):
|
|
|
480
755
|
push_notification_config: PushNotificationConfig | None = Field(None, description="Optional webhook configuration for async sync notifications. Publisher will send webhook when sync completes if operation takes longer than immediate response time (typically for large bulk operations or manual approval/HITL).")
|
|
481
756
|
|
|
482
757
|
|
|
758
|
+
class TasksGetRequest(BaseModel):
|
|
759
|
+
"""Request parameters for retrieving a specific task by ID with optional conversation history across all AdCP domains"""
|
|
760
|
+
|
|
761
|
+
task_id: str = Field(description="Unique identifier of the task to retrieve")
|
|
762
|
+
include_history: bool | None = Field(None, description="Include full conversation history for this task (may increase response size)")
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
class TasksListRequest(BaseModel):
|
|
766
|
+
"""Request parameters for listing and filtering async tasks across all AdCP domains with state reconciliation capabilities"""
|
|
767
|
+
|
|
768
|
+
filters: dict[str, Any] | None = Field(None, description="Filter criteria for querying tasks")
|
|
769
|
+
sort: dict[str, Any] | None = Field(None, description="Sorting parameters")
|
|
770
|
+
pagination: dict[str, Any] | None = Field(None, description="Pagination parameters")
|
|
771
|
+
include_history: bool | None = Field(None, description="Include full conversation history for each task (may significantly increase response size)")
|
|
772
|
+
|
|
773
|
+
|
|
483
774
|
class UpdateMediaBuyRequest(BaseModel):
|
|
484
775
|
"""Request parameters for updating campaign and package settings"""
|
|
485
776
|
|
|
@@ -492,30 +783,26 @@ class UpdateMediaBuyRequest(BaseModel):
|
|
|
492
783
|
push_notification_config: PushNotificationConfig | None = Field(None, description="Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time.")
|
|
493
784
|
|
|
494
785
|
|
|
495
|
-
|
|
496
|
-
"""Response payload for activate_signal task"""
|
|
786
|
+
# 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.
|
|
497
787
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
deployed_at: str | None = Field(None, description="Timestamp when activation completed (optional)")
|
|
501
|
-
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., activation failures, platform issues)")
|
|
788
|
+
class BuildCreativeResponseVariant1(BaseModel):
|
|
789
|
+
"""Success response - creative manifest generated successfully"""
|
|
502
790
|
|
|
503
|
-
|
|
504
|
-
class BuildCreativeResponse(BaseModel):
|
|
505
|
-
"""Response containing the transformed or generated creative manifest, ready for use with preview_creative or sync_creatives"""
|
|
791
|
+
model_config = ConfigDict(extra="forbid")
|
|
506
792
|
|
|
507
793
|
creative_manifest: CreativeManifest = Field(description="The generated or transformed creative manifest")
|
|
508
|
-
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings")
|
|
509
794
|
|
|
510
795
|
|
|
511
|
-
class
|
|
512
|
-
"""
|
|
796
|
+
class BuildCreativeResponseVariant2(BaseModel):
|
|
797
|
+
"""Error response - creative generation failed"""
|
|
513
798
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
799
|
+
model_config = ConfigDict(extra="forbid")
|
|
800
|
+
|
|
801
|
+
errors: list[Error] = Field(description="Array of errors explaining why creative generation failed")
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
# Union type for Build Creative Response
|
|
805
|
+
BuildCreativeResponse = BuildCreativeResponseVariant1 | BuildCreativeResponseVariant2
|
|
519
806
|
|
|
520
807
|
|
|
521
808
|
class GetMediaBuyDeliveryResponse(BaseModel):
|
|
@@ -577,28 +864,50 @@ class ListCreativesResponse(BaseModel):
|
|
|
577
864
|
status_summary: dict[str, Any] | None = Field(None, description="Breakdown of creatives by status")
|
|
578
865
|
|
|
579
866
|
|
|
580
|
-
|
|
581
|
-
|
|
867
|
+
# Response payload for provide_performance_feedback task. Returns either success confirmation OR error information, never both.
|
|
868
|
+
|
|
869
|
+
class ProvidePerformanceFeedbackResponseVariant1(BaseModel):
|
|
870
|
+
"""Success response - feedback received and processed"""
|
|
871
|
+
|
|
872
|
+
model_config = ConfigDict(extra="forbid")
|
|
873
|
+
|
|
874
|
+
success: Literal[True] = Field(description="Whether the performance feedback was successfully received")
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
class ProvidePerformanceFeedbackResponseVariant2(BaseModel):
|
|
878
|
+
"""Error response - feedback rejected or could not be processed"""
|
|
879
|
+
|
|
880
|
+
model_config = ConfigDict(extra="forbid")
|
|
881
|
+
|
|
882
|
+
errors: list[Error] = Field(description="Array of errors explaining why feedback was rejected (e.g., invalid measurement period, missing campaign data)")
|
|
582
883
|
|
|
583
|
-
success: bool = Field(description="Whether the performance feedback was successfully received")
|
|
584
|
-
errors: list[Error] | None = Field(None, description="Task-specific errors and warnings (e.g., invalid measurement period, missing campaign data)")
|
|
585
884
|
|
|
885
|
+
# Union type for Provide Performance Feedback Response
|
|
886
|
+
ProvidePerformanceFeedbackResponse = ProvidePerformanceFeedbackResponseVariant1 | ProvidePerformanceFeedbackResponseVariant2
|
|
586
887
|
|
|
587
|
-
class SyncCreativesResponse(BaseModel):
|
|
588
|
-
"""Response from creative sync operation with results for each creative"""
|
|
589
888
|
|
|
590
|
-
|
|
591
|
-
|
|
889
|
+
class TasksGetResponse(BaseModel):
|
|
890
|
+
"""Response containing detailed information about a specific task including status and optional conversation history across all AdCP domains"""
|
|
592
891
|
|
|
892
|
+
task_id: str = Field(description="Unique identifier for this task")
|
|
893
|
+
task_type: TaskType = Field(description="Type of AdCP operation")
|
|
894
|
+
domain: Literal["media-buy", "signals"] = Field(description="AdCP domain this task belongs to")
|
|
895
|
+
status: TaskStatus = Field(description="Current task status")
|
|
896
|
+
created_at: str = Field(description="When the task was initially created (ISO 8601)")
|
|
897
|
+
updated_at: str = Field(description="When the task was last updated (ISO 8601)")
|
|
898
|
+
completed_at: str | None = Field(None, description="When the task completed (ISO 8601, only for completed/failed/canceled tasks)")
|
|
899
|
+
has_webhook: bool | None = Field(None, description="Whether this task has webhook configuration")
|
|
900
|
+
progress: dict[str, Any] | None = Field(None, description="Progress information for long-running tasks")
|
|
901
|
+
error: dict[str, Any] | None = Field(None, description="Error details for failed tasks")
|
|
902
|
+
history: list[dict[str, Any]] | None = Field(None, description="Complete conversation history for this task (only included if include_history was true in request)")
|
|
593
903
|
|
|
594
|
-
class UpdateMediaBuyResponse(BaseModel):
|
|
595
|
-
"""Response payload for update_media_buy task"""
|
|
596
904
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
905
|
+
class TasksListResponse(BaseModel):
|
|
906
|
+
"""Response from task listing query with filtered results and state reconciliation data across all AdCP domains"""
|
|
907
|
+
|
|
908
|
+
query_summary: dict[str, Any] = Field(description="Summary of the query that was executed")
|
|
909
|
+
tasks: list[dict[str, Any]] = Field(description="Array of tasks matching the query criteria")
|
|
910
|
+
pagination: dict[str, Any] = Field(description="Pagination information")
|
|
602
911
|
|
|
603
912
|
|
|
604
913
|
|
|
@@ -653,3 +962,211 @@ class PreviewCreativeResponse(BaseModel):
|
|
|
653
962
|
|
|
654
963
|
# Batch mode field
|
|
655
964
|
results: list[dict[str, Any]] | None = Field(default=None, description="Array of preview results for batch processing")
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
# ============================================================================
|
|
968
|
+
# ONEOF DISCRIMINATED UNIONS FOR RESPONSE TYPES
|
|
969
|
+
# ============================================================================
|
|
970
|
+
# These response types use oneOf semantics: success XOR error, never both.
|
|
971
|
+
# Implemented as Union types with distinct Success/Error variants.
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
class ActivateSignalSuccess(BaseModel):
|
|
975
|
+
"""Successful signal activation response"""
|
|
976
|
+
|
|
977
|
+
decisioning_platform_segment_id: str = Field(
|
|
978
|
+
description="The platform-specific ID to use once activated"
|
|
979
|
+
)
|
|
980
|
+
estimated_activation_duration_minutes: float | None = None
|
|
981
|
+
deployed_at: str | None = None
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
class ActivateSignalError(BaseModel):
|
|
985
|
+
"""Failed signal activation response"""
|
|
986
|
+
|
|
987
|
+
errors: list[Error] = Field(description="Task-specific errors and warnings")
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
# Override the generated ActivateSignalResponse type alias
|
|
991
|
+
ActivateSignalResponse = ActivateSignalSuccess | ActivateSignalError
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
class CreateMediaBuySuccess(BaseModel):
|
|
995
|
+
"""Successful media buy creation response"""
|
|
996
|
+
|
|
997
|
+
media_buy_id: str = Field(description="The unique ID for the media buy")
|
|
998
|
+
buyer_ref: str = Field(description="The buyer's reference ID for this media buy")
|
|
999
|
+
packages: list[Package] = Field(
|
|
1000
|
+
description="Array of approved packages. Each package is ready for creative assignment."
|
|
1001
|
+
)
|
|
1002
|
+
creative_deadline: str | None = Field(
|
|
1003
|
+
None,
|
|
1004
|
+
description="ISO 8601 date when creatives must be provided for launch",
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
class CreateMediaBuyError(BaseModel):
|
|
1009
|
+
"""Failed media buy creation response"""
|
|
1010
|
+
|
|
1011
|
+
errors: list[Error] = Field(description="Task-specific errors and warnings")
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
# Override the generated CreateMediaBuyResponse type alias
|
|
1015
|
+
CreateMediaBuyResponse = CreateMediaBuySuccess | CreateMediaBuyError
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
class UpdateMediaBuySuccess(BaseModel):
|
|
1019
|
+
"""Successful media buy update response"""
|
|
1020
|
+
|
|
1021
|
+
media_buy_id: str = Field(description="The unique ID for the media buy")
|
|
1022
|
+
buyer_ref: str = Field(description="The buyer's reference ID for this media buy")
|
|
1023
|
+
packages: list[Package] = Field(
|
|
1024
|
+
description="Array of updated packages reflecting the changes"
|
|
1025
|
+
)
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
class UpdateMediaBuyError(BaseModel):
|
|
1029
|
+
"""Failed media buy update response"""
|
|
1030
|
+
|
|
1031
|
+
errors: list[Error] = Field(description="Task-specific errors and warnings")
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
# Override the generated UpdateMediaBuyResponse type alias
|
|
1035
|
+
UpdateMediaBuyResponse = UpdateMediaBuySuccess | UpdateMediaBuyError
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
class SyncCreativesSuccess(BaseModel):
|
|
1039
|
+
"""Successful creative sync response"""
|
|
1040
|
+
|
|
1041
|
+
assignments: list[CreativeAssignment] = Field(
|
|
1042
|
+
description="Array of creative assignments with updated status"
|
|
1043
|
+
)
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
class SyncCreativesError(BaseModel):
|
|
1047
|
+
"""Failed creative sync response"""
|
|
1048
|
+
|
|
1049
|
+
errors: list[Error] = Field(description="Task-specific errors and warnings")
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
# Override the generated SyncCreativesResponse type alias
|
|
1053
|
+
SyncCreativesResponse = SyncCreativesSuccess | SyncCreativesError
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
# Explicit exports for module interface
|
|
1057
|
+
__all__ = [
|
|
1058
|
+
"ActivateSignalError",
|
|
1059
|
+
"ActivateSignalRequest",
|
|
1060
|
+
"ActivateSignalResponse",
|
|
1061
|
+
"ActivateSignalSuccess",
|
|
1062
|
+
"ActivationKey",
|
|
1063
|
+
"AgentDeployment",
|
|
1064
|
+
"AgentDestination",
|
|
1065
|
+
"BothPreviewRender",
|
|
1066
|
+
"BrandManifest",
|
|
1067
|
+
"BrandManifestRef",
|
|
1068
|
+
"BrandManifestRefVariant1",
|
|
1069
|
+
"BrandManifestRefVariant2",
|
|
1070
|
+
"BuildCreativeRequest",
|
|
1071
|
+
"BuildCreativeResponse",
|
|
1072
|
+
"BuildCreativeResponseVariant1",
|
|
1073
|
+
"BuildCreativeResponseVariant2",
|
|
1074
|
+
"Channels",
|
|
1075
|
+
"CreateMediaBuyError",
|
|
1076
|
+
"CreateMediaBuyRequest",
|
|
1077
|
+
"CreateMediaBuyResponse",
|
|
1078
|
+
"CreateMediaBuySuccess",
|
|
1079
|
+
"CreativeAsset",
|
|
1080
|
+
"CreativeAssignment",
|
|
1081
|
+
"CreativeManifest",
|
|
1082
|
+
"CreativePolicy",
|
|
1083
|
+
"DaastAsset",
|
|
1084
|
+
"DeliveryMetrics",
|
|
1085
|
+
"DeliveryType",
|
|
1086
|
+
"Deployment",
|
|
1087
|
+
"Destination",
|
|
1088
|
+
"Error",
|
|
1089
|
+
"Format",
|
|
1090
|
+
"FormatId",
|
|
1091
|
+
"FrequencyCap",
|
|
1092
|
+
"GetMediaBuyDeliveryRequest",
|
|
1093
|
+
"GetMediaBuyDeliveryResponse",
|
|
1094
|
+
"GetProductsRequest",
|
|
1095
|
+
"GetProductsResponse",
|
|
1096
|
+
"GetSignalsRequest",
|
|
1097
|
+
"GetSignalsResponse",
|
|
1098
|
+
"HtmlPreviewRender",
|
|
1099
|
+
"InlineDaastAsset",
|
|
1100
|
+
"InlineVastAsset",
|
|
1101
|
+
"Key_valueActivationKey",
|
|
1102
|
+
"ListAuthorizedPropertiesRequest",
|
|
1103
|
+
"ListAuthorizedPropertiesResponse",
|
|
1104
|
+
"ListCreativeFormatsRequest",
|
|
1105
|
+
"ListCreativeFormatsResponse",
|
|
1106
|
+
"ListCreativesRequest",
|
|
1107
|
+
"ListCreativesResponse",
|
|
1108
|
+
"Measurement",
|
|
1109
|
+
"MediaBuy",
|
|
1110
|
+
"MediaBuyStatus",
|
|
1111
|
+
"MediaSubAsset",
|
|
1112
|
+
"Pacing",
|
|
1113
|
+
"Package",
|
|
1114
|
+
"PackageRequest",
|
|
1115
|
+
"PackageStatus",
|
|
1116
|
+
"PerformanceFeedback",
|
|
1117
|
+
"Placement",
|
|
1118
|
+
"PlatformDeployment",
|
|
1119
|
+
"PlatformDestination",
|
|
1120
|
+
"PreviewCreativeRequest",
|
|
1121
|
+
"PreviewCreativeResponse",
|
|
1122
|
+
"PreviewRender",
|
|
1123
|
+
"PricingModel",
|
|
1124
|
+
"PricingOption",
|
|
1125
|
+
"PricingOptionVariant1",
|
|
1126
|
+
"PricingOptionVariant2",
|
|
1127
|
+
"PricingOptionVariant3",
|
|
1128
|
+
"PricingOptionVariant4",
|
|
1129
|
+
"PricingOptionVariant5",
|
|
1130
|
+
"PricingOptionVariant6",
|
|
1131
|
+
"PricingOptionVariant7",
|
|
1132
|
+
"PricingOptionVariant8",
|
|
1133
|
+
"PricingOptionVariant9",
|
|
1134
|
+
"Product",
|
|
1135
|
+
"PromotedProducts",
|
|
1136
|
+
"Property",
|
|
1137
|
+
"ProtocolEnvelope",
|
|
1138
|
+
"ProvidePerformanceFeedbackRequest",
|
|
1139
|
+
"ProvidePerformanceFeedbackResponse",
|
|
1140
|
+
"ProvidePerformanceFeedbackResponseVariant1",
|
|
1141
|
+
"ProvidePerformanceFeedbackResponseVariant2",
|
|
1142
|
+
"PushNotificationConfig",
|
|
1143
|
+
"ReportingCapabilities",
|
|
1144
|
+
"Response",
|
|
1145
|
+
"Segment_idActivationKey",
|
|
1146
|
+
"StandardFormatIds",
|
|
1147
|
+
"StartTiming",
|
|
1148
|
+
"StartTimingVariant1",
|
|
1149
|
+
"StartTimingVariant2",
|
|
1150
|
+
"SubAsset",
|
|
1151
|
+
"SyncCreativesError",
|
|
1152
|
+
"SyncCreativesRequest",
|
|
1153
|
+
"SyncCreativesResponse",
|
|
1154
|
+
"SyncCreativesSuccess",
|
|
1155
|
+
"Targeting",
|
|
1156
|
+
"TaskStatus",
|
|
1157
|
+
"TaskType",
|
|
1158
|
+
"TasksGetRequest",
|
|
1159
|
+
"TasksGetResponse",
|
|
1160
|
+
"TasksListRequest",
|
|
1161
|
+
"TasksListResponse",
|
|
1162
|
+
"TextSubAsset",
|
|
1163
|
+
"UpdateMediaBuyError",
|
|
1164
|
+
"UpdateMediaBuyRequest",
|
|
1165
|
+
"UpdateMediaBuyResponse",
|
|
1166
|
+
"UpdateMediaBuySuccess",
|
|
1167
|
+
"UrlDaastAsset",
|
|
1168
|
+
"UrlPreviewRender",
|
|
1169
|
+
"UrlVastAsset",
|
|
1170
|
+
"VastAsset",
|
|
1171
|
+
"WebhookPayload",
|
|
1172
|
+
]
|
adcp/utils/response_parser.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
-
from typing import Any, TypeVar
|
|
7
|
+
from typing import Any, TypeVar, Union, cast, get_args, get_origin
|
|
8
8
|
|
|
9
9
|
from pydantic import BaseModel, ValidationError
|
|
10
10
|
|
|
@@ -13,6 +13,56 @@ logger = logging.getLogger(__name__)
|
|
|
13
13
|
T = TypeVar("T", bound=BaseModel)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
def _validate_union_type(data: dict[str, Any], response_type: type[T]) -> T:
|
|
17
|
+
"""
|
|
18
|
+
Validate data against a Union type by trying each variant.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
data: Data to validate
|
|
22
|
+
response_type: Union type to validate against
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Validated model instance
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
ValidationError: If data doesn't match any Union variant
|
|
29
|
+
"""
|
|
30
|
+
# Check if this is a Union type (handles both typing.Union and types.UnionType)
|
|
31
|
+
origin = get_origin(response_type)
|
|
32
|
+
|
|
33
|
+
# In Python 3.10+, X | Y creates a types.UnionType, not typing.Union
|
|
34
|
+
# We need to check both the origin and the type itself
|
|
35
|
+
is_union = origin is Union or str(type(response_type).__name__) == "UnionType"
|
|
36
|
+
|
|
37
|
+
if is_union:
|
|
38
|
+
# Get union args - works for both typing.Union and types.UnionType
|
|
39
|
+
args = get_args(response_type)
|
|
40
|
+
if not args: # types.UnionType case
|
|
41
|
+
# For types.UnionType, we need to access __args__ directly
|
|
42
|
+
args = getattr(response_type, "__args__", ())
|
|
43
|
+
|
|
44
|
+
errors = []
|
|
45
|
+
for variant in args:
|
|
46
|
+
try:
|
|
47
|
+
return cast(T, variant.model_validate(data))
|
|
48
|
+
except ValidationError as e:
|
|
49
|
+
errors.append((variant.__name__, e))
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
# If we get here, none of the variants worked
|
|
53
|
+
error_msgs = [f"{name}: {str(e)}" for name, e in errors]
|
|
54
|
+
# Raise a ValueError instead of ValidationError for better error messages
|
|
55
|
+
raise ValueError(
|
|
56
|
+
f"Data doesn't match any Union variant. "
|
|
57
|
+
f"Attempted variants: {', '.join([e[0] for e in errors])}. "
|
|
58
|
+
f"Errors: {'; '.join(error_msgs)}"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Not a Union type, use regular validation
|
|
62
|
+
# Cast is needed because response_type is typed as type[T] | Any
|
|
63
|
+
return cast(T, response_type.model_validate(data)) # type: ignore[redundant-cast]
|
|
64
|
+
|
|
65
|
+
|
|
16
66
|
def parse_mcp_content(content: list[dict[str, Any]], response_type: type[T]) -> T:
|
|
17
67
|
"""
|
|
18
68
|
Parse MCP content array into structured response type.
|
|
@@ -48,8 +98,8 @@ def parse_mcp_content(content: list[dict[str, Any]], response_type: type[T]) ->
|
|
|
48
98
|
try:
|
|
49
99
|
# Try parsing as JSON
|
|
50
100
|
data = json.loads(text)
|
|
51
|
-
# Validate against expected schema
|
|
52
|
-
return
|
|
101
|
+
# Validate against expected schema (handles Union types)
|
|
102
|
+
return _validate_union_type(data, response_type)
|
|
53
103
|
except json.JSONDecodeError:
|
|
54
104
|
# Not JSON, try next item
|
|
55
105
|
continue
|
|
@@ -61,7 +111,7 @@ def parse_mcp_content(content: list[dict[str, Any]], response_type: type[T]) ->
|
|
|
61
111
|
elif item.get("type") == "resource":
|
|
62
112
|
# Resource content might have structured data
|
|
63
113
|
try:
|
|
64
|
-
return
|
|
114
|
+
return _validate_union_type(item, response_type)
|
|
65
115
|
except ValidationError:
|
|
66
116
|
# Try next item
|
|
67
117
|
continue
|
|
@@ -98,25 +148,24 @@ def parse_json_or_text(data: Any, response_type: type[T]) -> T:
|
|
|
98
148
|
# If already a dict, try direct validation
|
|
99
149
|
if isinstance(data, dict):
|
|
100
150
|
try:
|
|
101
|
-
return
|
|
151
|
+
return _validate_union_type(data, response_type)
|
|
102
152
|
except ValidationError as e:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
) from e
|
|
153
|
+
# Get the type name, handling Union types
|
|
154
|
+
type_name = getattr(response_type, "__name__", str(response_type))
|
|
155
|
+
raise ValueError(f"Response doesn't match expected schema {type_name}: {e}") from e
|
|
106
156
|
|
|
107
157
|
# If string, try JSON parsing
|
|
108
158
|
if isinstance(data, str):
|
|
109
159
|
try:
|
|
110
160
|
parsed = json.loads(data)
|
|
111
|
-
return
|
|
161
|
+
return _validate_union_type(parsed, response_type)
|
|
112
162
|
except json.JSONDecodeError as e:
|
|
113
163
|
raise ValueError(f"Response is not valid JSON: {e}") from e
|
|
114
164
|
except ValidationError as e:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
) from e
|
|
165
|
+
# Get the type name, handling Union types
|
|
166
|
+
type_name = getattr(response_type, "__name__", str(response_type))
|
|
167
|
+
raise ValueError(f"Response doesn't match expected schema {type_name}: {e}") from e
|
|
118
168
|
|
|
119
169
|
# Unsupported type
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
170
|
+
type_name = getattr(response_type, "__name__", str(response_type))
|
|
171
|
+
raise ValueError(f"Cannot parse response of type {type(data).__name__} into {type_name}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adcp
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Official Python client for the Ad Context Protocol (AdCP)
|
|
5
5
|
Author-email: AdCP Community <maintainers@adcontextprotocol.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -59,6 +59,8 @@ AdCP operations are **distributed and asynchronous by default**. An agent might:
|
|
|
59
59
|
pip install adcp
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
> **Note**: This client requires Python 3.10 or later and supports both synchronous and asynchronous workflows.
|
|
63
|
+
|
|
62
64
|
## Quick Start: Distributed Operations
|
|
63
65
|
|
|
64
66
|
```python
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
adcp/__init__.py,sha256=
|
|
1
|
+
adcp/__init__.py,sha256=3UpoB71XItkSZ_r1QuzE2GZIQsgVjt50ZawxQUO2-qs,6232
|
|
2
2
|
adcp/__main__.py,sha256=Avy_C71rruh2lOuojvuXDj09tkFOaek74nJ-dbx25Sw,12838
|
|
3
|
-
adcp/client.py,sha256=
|
|
3
|
+
adcp/client.py,sha256=co4tKdkjDrqZltCUPcYwVRr8LQfbBbG-DLjapLjcVuo,28246
|
|
4
4
|
adcp/config.py,sha256=Vsy7ZPOI8G3fB_i5Nk-CHbC7wdasCUWuKlos0fwA0kY,2017
|
|
5
5
|
adcp/exceptions.py,sha256=dNRMKV23DlkGKyB9Xmt6MtlhvDu1crjzD_en4nAEwDY,4399
|
|
6
6
|
adcp/protocols/__init__.py,sha256=6UFwACQ0QadBUzy17wUROHqsJDp8ztPW2jzyl53Zh_g,262
|
|
7
7
|
adcp/protocols/a2a.py,sha256=FHgc6G_eU2qD0vH7_RyS1eZvUFSb2j3-EsceoHPi384,12467
|
|
8
|
-
adcp/protocols/base.py,sha256=
|
|
8
|
+
adcp/protocols/base.py,sha256=vBHD23Fzl_CCk_Gy9nvSbBYopcJlYkYyzoz-rhI8wHg,5214
|
|
9
9
|
adcp/protocols/mcp.py,sha256=eIk8snCinZm-ZjdarGVMt5nEYJ4_8POM9Fa5Mkw7xxU,15902
|
|
10
10
|
adcp/types/__init__.py,sha256=3E_TJUXqQQFcjmSZZSPLwqBP3s_ijsH2LDeuOU-MP30,402
|
|
11
11
|
adcp/types/core.py,sha256=RXkKCWCXS9BVJTNpe3Opm5O1I_LaQPMUuVwa-ipvS1Q,4839
|
|
12
|
-
adcp/types/generated.py,sha256=
|
|
12
|
+
adcp/types/generated.py,sha256=Ig4ucbJzKRuHlwYzsqvMF9M3w2KghhQQqsXuOnBqVMM,74993
|
|
13
13
|
adcp/types/tasks.py,sha256=Ae9TSwG2F7oWXTcl4TvLhAzinbQkHNGF1Pc0q8RMNNM,23424
|
|
14
14
|
adcp/utils/__init__.py,sha256=uetvSJB19CjQbtwEYZiTnumJG11GsafQmXm5eR3hL7E,153
|
|
15
15
|
adcp/utils/operation_id.py,sha256=wQX9Bb5epXzRq23xoeYPTqzu5yLuhshg7lKJZihcM2k,294
|
|
16
16
|
adcp/utils/preview_cache.py,sha256=8_2qs5CgrHv1_WOnD4bs43VWueu-rcZRu5PZMQ_lyuE,17573
|
|
17
|
-
adcp/utils/response_parser.py,sha256=
|
|
18
|
-
adcp-1.1.
|
|
19
|
-
adcp-1.1.
|
|
20
|
-
adcp-1.1.
|
|
21
|
-
adcp-1.1.
|
|
22
|
-
adcp-1.1.
|
|
23
|
-
adcp-1.1.
|
|
17
|
+
adcp/utils/response_parser.py,sha256=uPk2vIH-RYZmq7y3i8lC4HTMQ3FfKdlgXKTjgJ1955M,6253
|
|
18
|
+
adcp-1.2.1.dist-info/licenses/LICENSE,sha256=PF39NR3Ae8PLgBhg3Uxw6ju7iGVIf8hfv9LRWQdii_U,629
|
|
19
|
+
adcp-1.2.1.dist-info/METADATA,sha256=mDI2lRdXxOluUZ9vgRE3fyoGSnj8DQ8nqBU30Tuphjg,14568
|
|
20
|
+
adcp-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
adcp-1.2.1.dist-info/entry_points.txt,sha256=DQKpcGsJX8DtVI_SGApQ7tNvqUB4zkTLaTAEpFgmi3U,44
|
|
22
|
+
adcp-1.2.1.dist-info/top_level.txt,sha256=T1_NF0GefncFU9v_k56oDwKSJREyCqIM8lAwNZf0EOs,5
|
|
23
|
+
adcp-1.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|