adcp 2.12.2__py3-none-any.whl → 2.13.0__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 +1 -1
- adcp/types/base.py +193 -0
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/METADATA +1 -1
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/RECORD +8 -8
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/WHEEL +0 -0
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/entry_points.txt +0 -0
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {adcp-2.12.2.dist-info → adcp-2.13.0.dist-info}/top_level.txt +0 -0
adcp/__init__.py
CHANGED
adcp/types/base.py
CHANGED
|
@@ -2,10 +2,189 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
"""Base model for AdCP types with spec-compliant serialization."""
|
|
4
4
|
|
|
5
|
+
from collections.abc import Callable
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from pydantic import BaseModel
|
|
8
9
|
|
|
10
|
+
# Type alias to shorten long type annotations
|
|
11
|
+
MessageFormatter = Callable[[Any], str]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _pluralize(count: int, singular: str, plural: str | None = None) -> str:
|
|
15
|
+
"""Return singular or plural form based on count."""
|
|
16
|
+
if count == 1:
|
|
17
|
+
return singular
|
|
18
|
+
return plural if plural else f"{singular}s"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Registry of human-readable message formatters for response types.
|
|
22
|
+
# Key is the class name, value is a callable that takes the instance and returns a message.
|
|
23
|
+
_RESPONSE_MESSAGE_REGISTRY: dict[str, MessageFormatter] = {}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _register_response_message(cls_name: str) -> Callable[[MessageFormatter], MessageFormatter]:
|
|
27
|
+
"""Decorator to register a message formatter for a response type."""
|
|
28
|
+
|
|
29
|
+
def decorator(func: MessageFormatter) -> MessageFormatter:
|
|
30
|
+
_RESPONSE_MESSAGE_REGISTRY[cls_name] = func
|
|
31
|
+
return func
|
|
32
|
+
|
|
33
|
+
return decorator
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Response message formatters
|
|
37
|
+
@_register_response_message("GetProductsResponse")
|
|
38
|
+
def _get_products_message(self: Any) -> str:
|
|
39
|
+
products = getattr(self, "products", None)
|
|
40
|
+
if products is None or len(products) == 0:
|
|
41
|
+
return "No products matched your requirements."
|
|
42
|
+
count = len(products)
|
|
43
|
+
return f"Found {count} {_pluralize(count, 'product')} matching your requirements."
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@_register_response_message("ListCreativeFormatsResponse")
|
|
47
|
+
def _list_creative_formats_message(self: Any) -> str:
|
|
48
|
+
formats = getattr(self, "formats", None)
|
|
49
|
+
if formats is None:
|
|
50
|
+
return "No creative formats found."
|
|
51
|
+
count = len(formats)
|
|
52
|
+
return f"Found {count} supported creative {_pluralize(count, 'format')}."
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@_register_response_message("GetSignalsResponse")
|
|
56
|
+
def _get_signals_message(self: Any) -> str:
|
|
57
|
+
signals = getattr(self, "signals", None)
|
|
58
|
+
if signals is None:
|
|
59
|
+
return "No signals found."
|
|
60
|
+
count = len(signals)
|
|
61
|
+
return f"Found {count} {_pluralize(count, 'signal')} available for targeting."
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@_register_response_message("ListAuthorizedPropertiesResponse")
|
|
65
|
+
def _list_authorized_properties_message(self: Any) -> str:
|
|
66
|
+
domains = getattr(self, "publisher_domains", None)
|
|
67
|
+
if domains is None:
|
|
68
|
+
return "No authorized properties found."
|
|
69
|
+
count = len(domains)
|
|
70
|
+
return f"Authorized to represent {count} publisher {_pluralize(count, 'domain')}."
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@_register_response_message("ListCreativesResponse")
|
|
74
|
+
def _list_creatives_message(self: Any) -> str:
|
|
75
|
+
creatives = getattr(self, "creatives", None)
|
|
76
|
+
if creatives is None:
|
|
77
|
+
return "No creatives found."
|
|
78
|
+
count = len(creatives)
|
|
79
|
+
return f"Found {count} {_pluralize(count, 'creative')} in the system."
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@_register_response_message("CreateMediaBuyResponse1")
|
|
83
|
+
def _create_media_buy_success_message(self: Any) -> str:
|
|
84
|
+
media_buy_id = getattr(self, "media_buy_id", None)
|
|
85
|
+
packages = getattr(self, "packages", None)
|
|
86
|
+
package_count = len(packages) if packages else 0
|
|
87
|
+
return (
|
|
88
|
+
f"Media buy {media_buy_id} created with "
|
|
89
|
+
f"{package_count} {_pluralize(package_count, 'package')}."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@_register_response_message("CreateMediaBuyResponse2")
|
|
94
|
+
def _create_media_buy_error_message(self: Any) -> str:
|
|
95
|
+
errors = getattr(self, "errors", None)
|
|
96
|
+
error_count = len(errors) if errors else 0
|
|
97
|
+
return f"Media buy creation failed with {error_count} {_pluralize(error_count, 'error')}."
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@_register_response_message("UpdateMediaBuyResponse1")
|
|
101
|
+
def _update_media_buy_success_message(self: Any) -> str:
|
|
102
|
+
media_buy_id = getattr(self, "media_buy_id", None)
|
|
103
|
+
return f"Media buy {media_buy_id} updated successfully."
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@_register_response_message("UpdateMediaBuyResponse2")
|
|
107
|
+
def _update_media_buy_error_message(self: Any) -> str:
|
|
108
|
+
errors = getattr(self, "errors", None)
|
|
109
|
+
error_count = len(errors) if errors else 0
|
|
110
|
+
return f"Media buy update failed with {error_count} {_pluralize(error_count, 'error')}."
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@_register_response_message("SyncCreativesResponse1")
|
|
114
|
+
def _sync_creatives_success_message(self: Any) -> str:
|
|
115
|
+
creatives = getattr(self, "creatives", None)
|
|
116
|
+
creative_count = len(creatives) if creatives else 0
|
|
117
|
+
return f"Synced {creative_count} {_pluralize(creative_count, 'creative')} successfully."
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@_register_response_message("SyncCreativesResponse2")
|
|
121
|
+
def _sync_creatives_error_message(self: Any) -> str:
|
|
122
|
+
errors = getattr(self, "errors", None)
|
|
123
|
+
error_count = len(errors) if errors else 0
|
|
124
|
+
return f"Creative sync failed with {error_count} {_pluralize(error_count, 'error')}."
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@_register_response_message("ActivateSignalResponse1")
|
|
128
|
+
def _activate_signal_success_message(self: Any) -> str:
|
|
129
|
+
return "Signal activated successfully."
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@_register_response_message("ActivateSignalResponse2")
|
|
133
|
+
def _activate_signal_error_message(self: Any) -> str:
|
|
134
|
+
errors = getattr(self, "errors", None)
|
|
135
|
+
error_count = len(errors) if errors else 0
|
|
136
|
+
return f"Signal activation failed with {error_count} {_pluralize(error_count, 'error')}."
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@_register_response_message("PreviewCreativeResponse1")
|
|
140
|
+
def _preview_creative_single_message(self: Any) -> str:
|
|
141
|
+
previews = getattr(self, "previews", None)
|
|
142
|
+
preview_count = len(previews) if previews else 0
|
|
143
|
+
return f"Generated {preview_count} {_pluralize(preview_count, 'preview')}."
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@_register_response_message("PreviewCreativeResponse2")
|
|
147
|
+
def _preview_creative_batch_message(self: Any) -> str:
|
|
148
|
+
results = getattr(self, "results", None)
|
|
149
|
+
result_count = len(results) if results else 0
|
|
150
|
+
return f"Generated previews for {result_count} {_pluralize(result_count, 'manifest')}."
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@_register_response_message("BuildCreativeResponse1")
|
|
154
|
+
def _build_creative_success_message(self: Any) -> str:
|
|
155
|
+
return "Creative built successfully."
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@_register_response_message("BuildCreativeResponse2")
|
|
159
|
+
def _build_creative_error_message(self: Any) -> str:
|
|
160
|
+
errors = getattr(self, "errors", None)
|
|
161
|
+
error_count = len(errors) if errors else 0
|
|
162
|
+
return f"Creative build failed with {error_count} {_pluralize(error_count, 'error')}."
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@_register_response_message("GetMediaBuyDeliveryResponse")
|
|
166
|
+
def _get_media_buy_delivery_message(self: Any) -> str:
|
|
167
|
+
deliveries = getattr(self, "media_buy_deliveries", None)
|
|
168
|
+
if deliveries is None:
|
|
169
|
+
return "No delivery data available."
|
|
170
|
+
count = len(deliveries)
|
|
171
|
+
return f"Retrieved delivery data for {count} media {_pluralize(count, 'buy', 'buys')}."
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@_register_response_message("ProvidePerformanceFeedbackResponse1")
|
|
175
|
+
def _provide_performance_feedback_success_message(self: Any) -> str:
|
|
176
|
+
return "Performance feedback recorded successfully."
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@_register_response_message("ProvidePerformanceFeedbackResponse2")
|
|
180
|
+
def _provide_performance_feedback_error_message(self: Any) -> str:
|
|
181
|
+
errors = getattr(self, "errors", None)
|
|
182
|
+
error_count = len(errors) if errors else 0
|
|
183
|
+
return (
|
|
184
|
+
f"Performance feedback recording failed with "
|
|
185
|
+
f"{error_count} {_pluralize(error_count, 'error')}."
|
|
186
|
+
)
|
|
187
|
+
|
|
9
188
|
|
|
10
189
|
class AdCPBaseModel(BaseModel):
|
|
11
190
|
"""Base model for AdCP types with spec-compliant serialization.
|
|
@@ -24,3 +203,17 @@ class AdCPBaseModel(BaseModel):
|
|
|
24
203
|
if "exclude_none" not in kwargs:
|
|
25
204
|
kwargs["exclude_none"] = True
|
|
26
205
|
return super().model_dump_json(**kwargs)
|
|
206
|
+
|
|
207
|
+
def summary(self) -> str:
|
|
208
|
+
"""Human-readable summary for protocol responses.
|
|
209
|
+
|
|
210
|
+
Returns a standardized human-readable message suitable for MCP tool
|
|
211
|
+
results, A2A task communications, and REST API responses.
|
|
212
|
+
|
|
213
|
+
For types without a registered formatter, returns a generic message
|
|
214
|
+
with the class name.
|
|
215
|
+
"""
|
|
216
|
+
formatter = _RESPONSE_MESSAGE_REGISTRY.get(self.__class__.__name__)
|
|
217
|
+
if formatter:
|
|
218
|
+
return formatter(self)
|
|
219
|
+
return f"{self.__class__.__name__} response"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
adcp/ADCP_VERSION,sha256=cy9k2HT5B4jAGZsMGb_Zs7ZDbhQBFOU-RigyUy10xhw,6
|
|
2
|
-
adcp/__init__.py,sha256=
|
|
2
|
+
adcp/__init__.py,sha256=bc6VcbIXmZzfjXFmMV13x-5-5F9rFkir6B51hQsj34U,9933
|
|
3
3
|
adcp/__main__.py,sha256=8v-j_W9IIWDIcvhaR1yuZAhBCDRfehUyN0tusstzyfQ,15139
|
|
4
4
|
adcp/adagents.py,sha256=o-vTBmdZvu9aER-TAlLLL3s-WGYY8N67jnrAH24lST8,22333
|
|
5
5
|
adcp/client.py,sha256=PQsmfpL-j2msTbWZkOcH0ZFGzPP9hh0QOPZ2fFrm8Q8,37149
|
|
@@ -17,7 +17,7 @@ adcp/testing/test_helpers.py,sha256=-UKuxxyKQald5EvXxguQH34b3J0JdsxKH_nRT6GTjkQ,
|
|
|
17
17
|
adcp/types/__init__.py,sha256=bTEGjtbSbcCDYM2Y2f8bXdfJWS47FIw9UJJL5T7-wn4,13563
|
|
18
18
|
adcp/types/_generated.py,sha256=eJg4J0TLOuFKrl32vI-fNFZ6vEhB2gBP6753VlA1PRE,20816
|
|
19
19
|
adcp/types/aliases.py,sha256=PPBaWr-UMzfqVbg-592btdaqF1ATJWljtu8iiyV3RYQ,25142
|
|
20
|
-
adcp/types/base.py,sha256=
|
|
20
|
+
adcp/types/base.py,sha256=Xr0cwbjG4tRPLbDTX9lucGty6_Y_S0a5C_ve0n7umc8,8227
|
|
21
21
|
adcp/types/core.py,sha256=RXkKCWCXS9BVJTNpe3Opm5O1I_LaQPMUuVwa-ipvS1Q,4839
|
|
22
22
|
adcp/types/generated_poc/__init__.py,sha256=bgFFvPK1-e04eOnyw0qmtVMzoA2V7GeAMPDVrx-VIwA,103
|
|
23
23
|
adcp/types/generated_poc/adagents.py,sha256=lftHANcpBRj83vZn1wHUUO7zJjkXhWpWZ32CjlwbtnI,16438
|
|
@@ -168,9 +168,9 @@ adcp/utils/__init__.py,sha256=uetvSJB19CjQbtwEYZiTnumJG11GsafQmXm5eR3hL7E,153
|
|
|
168
168
|
adcp/utils/operation_id.py,sha256=wQX9Bb5epXzRq23xoeYPTqzu5yLuhshg7lKJZihcM2k,294
|
|
169
169
|
adcp/utils/preview_cache.py,sha256=rZTZfrN2MOvIWsvyyiNhrc2iVxoaFV_QaB1DlfsUH-Y,18668
|
|
170
170
|
adcp/utils/response_parser.py,sha256=uPk2vIH-RYZmq7y3i8lC4HTMQ3FfKdlgXKTjgJ1955M,6253
|
|
171
|
-
adcp-2.
|
|
172
|
-
adcp-2.
|
|
173
|
-
adcp-2.
|
|
174
|
-
adcp-2.
|
|
175
|
-
adcp-2.
|
|
176
|
-
adcp-2.
|
|
171
|
+
adcp-2.13.0.dist-info/licenses/LICENSE,sha256=PF39NR3Ae8PLgBhg3Uxw6ju7iGVIf8hfv9LRWQdii_U,629
|
|
172
|
+
adcp-2.13.0.dist-info/METADATA,sha256=eiKsacoPkxO4J41f0-smMmz9CIkAXIRx7oYwzcjbxvg,31358
|
|
173
|
+
adcp-2.13.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
174
|
+
adcp-2.13.0.dist-info/entry_points.txt,sha256=DQKpcGsJX8DtVI_SGApQ7tNvqUB4zkTLaTAEpFgmi3U,44
|
|
175
|
+
adcp-2.13.0.dist-info/top_level.txt,sha256=T1_NF0GefncFU9v_k56oDwKSJREyCqIM8lAwNZf0EOs,5
|
|
176
|
+
adcp-2.13.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|