adcp 1.2.0__tar.gz → 1.3.0__tar.gz
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-1.2.0/src/adcp.egg-info → adcp-1.3.0}/PKG-INFO +138 -1
- {adcp-1.2.0 → adcp-1.3.0}/README.md +137 -0
- {adcp-1.2.0 → adcp-1.3.0}/pyproject.toml +1 -1
- adcp-1.3.0/src/adcp/__init__.py +289 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/client.py +12 -5
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/protocols/base.py +5 -2
- adcp-1.3.0/src/adcp/testing/__init__.py +38 -0
- adcp-1.3.0/src/adcp/testing/test_helpers.py +311 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/types/generated.py +464 -55
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/utils/response_parser.py +64 -15
- {adcp-1.2.0 → adcp-1.3.0/src/adcp.egg-info}/PKG-INFO +138 -1
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp.egg-info/SOURCES.txt +4 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_client.py +4 -1
- adcp-1.3.0/tests/test_discriminated_unions.py +404 -0
- adcp-1.3.0/tests/test_helpers.py +239 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_preview_html.py +38 -13
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_protocols.py +0 -1
- adcp-1.2.0/src/adcp/__init__.py +0 -96
- {adcp-1.2.0 → adcp-1.3.0}/LICENSE +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/setup.cfg +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/__main__.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/config.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/exceptions.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/protocols/__init__.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/protocols/a2a.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/protocols/mcp.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/types/__init__.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/types/core.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/types/tasks.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/utils/__init__.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/utils/operation_id.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp/utils/preview_cache.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp.egg-info/dependency_links.txt +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp.egg-info/entry_points.txt +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp.egg-info/requires.txt +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/src/adcp.egg-info/top_level.txt +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_cli.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_code_generation.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_format_id_validation.py +0 -0
- {adcp-1.2.0 → adcp-1.3.0}/tests/test_response_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adcp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
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,8 +59,45 @@ 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
|
+
|
|
64
|
+
## Quick Start: Test Helpers
|
|
65
|
+
|
|
66
|
+
The fastest way to get started is using the pre-configured test agents:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from adcp.testing import test_agent
|
|
70
|
+
from adcp.types.generated import GetProductsRequest
|
|
71
|
+
|
|
72
|
+
# Zero configuration - just import and use!
|
|
73
|
+
result = await test_agent.get_products(
|
|
74
|
+
GetProductsRequest(
|
|
75
|
+
brief="Coffee subscription service",
|
|
76
|
+
promoted_offering="Premium coffee deliveries"
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if result.success:
|
|
81
|
+
print(f"Found {len(result.data.products)} products")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Test helpers include:
|
|
85
|
+
- **`test_agent`**: Pre-configured MCP test agent with authentication
|
|
86
|
+
- **`test_agent_a2a`**: Pre-configured A2A test agent with authentication
|
|
87
|
+
- **`test_agent_no_auth`**: Pre-configured MCP test agent WITHOUT authentication
|
|
88
|
+
- **`test_agent_a2a_no_auth`**: Pre-configured A2A test agent WITHOUT authentication
|
|
89
|
+
- **`creative_agent`**: Reference creative agent for preview functionality
|
|
90
|
+
- **`test_agent_client`**: Multi-agent client with both protocols
|
|
91
|
+
- **`create_test_agent()`**: Factory for custom test configurations
|
|
92
|
+
|
|
93
|
+
> **Note**: Test agents are rate-limited and for testing/examples only. DO NOT use in production.
|
|
94
|
+
|
|
95
|
+
See [examples/test_helpers_demo.py](examples/test_helpers_demo.py) for more examples.
|
|
96
|
+
|
|
62
97
|
## Quick Start: Distributed Operations
|
|
63
98
|
|
|
99
|
+
For production use, configure your own agents:
|
|
100
|
+
|
|
64
101
|
```python
|
|
65
102
|
from adcp import ADCPMultiAgentClient, AgentConfig, GetProductsRequest
|
|
66
103
|
|
|
@@ -110,6 +147,66 @@ async with ADCPMultiAgentClient(
|
|
|
110
147
|
|
|
111
148
|
## Features
|
|
112
149
|
|
|
150
|
+
### Test Helpers
|
|
151
|
+
|
|
152
|
+
Pre-configured test agents for instant prototyping and testing:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from adcp.testing import (
|
|
156
|
+
test_agent, test_agent_a2a,
|
|
157
|
+
test_agent_no_auth, test_agent_a2a_no_auth,
|
|
158
|
+
creative_agent, test_agent_client, create_test_agent
|
|
159
|
+
)
|
|
160
|
+
from adcp.types.generated import GetProductsRequest, PreviewCreativeRequest
|
|
161
|
+
|
|
162
|
+
# 1. Single agent with authentication (MCP)
|
|
163
|
+
result = await test_agent.get_products(
|
|
164
|
+
GetProductsRequest(brief="Coffee brands")
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# 2. Single agent with authentication (A2A)
|
|
168
|
+
result = await test_agent_a2a.get_products(
|
|
169
|
+
GetProductsRequest(brief="Coffee brands")
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# 3. Single agent WITHOUT authentication (MCP)
|
|
173
|
+
# Useful for testing unauthenticated behavior
|
|
174
|
+
result = await test_agent_no_auth.get_products(
|
|
175
|
+
GetProductsRequest(brief="Coffee brands")
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# 4. Single agent WITHOUT authentication (A2A)
|
|
179
|
+
result = await test_agent_a2a_no_auth.get_products(
|
|
180
|
+
GetProductsRequest(brief="Coffee brands")
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# 5. Creative agent (preview functionality, no auth required)
|
|
184
|
+
result = await creative_agent.preview_creative(
|
|
185
|
+
PreviewCreativeRequest(
|
|
186
|
+
manifest={"format_id": "banner_300x250", "assets": {...}}
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# 6. Multi-agent (parallel execution with both protocols)
|
|
191
|
+
results = await test_agent_client.get_products(
|
|
192
|
+
GetProductsRequest(brief="Coffee brands")
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 7. Custom configuration
|
|
196
|
+
from adcp.client import ADCPClient
|
|
197
|
+
config = create_test_agent(id="my-test", timeout=60.0)
|
|
198
|
+
client = ADCPClient(config)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Use cases:**
|
|
202
|
+
- Quick prototyping and experimentation
|
|
203
|
+
- Example code and documentation
|
|
204
|
+
- Integration testing without mock servers
|
|
205
|
+
- Testing authentication behavior (comparing auth vs no-auth results)
|
|
206
|
+
- Learning AdCP concepts
|
|
207
|
+
|
|
208
|
+
**Important:** Test agents are public, rate-limited, and for testing only. Never use in production.
|
|
209
|
+
|
|
113
210
|
### Full Protocol Support
|
|
114
211
|
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
115
212
|
- **MCP Protocol**: Native support for Model Context Protocol
|
|
@@ -375,6 +472,46 @@ uvx adcp --json myagent get_products '{"brief":"TV ads"}'
|
|
|
375
472
|
uvx adcp --debug myagent get_products '{"brief":"TV ads"}'
|
|
376
473
|
```
|
|
377
474
|
|
|
475
|
+
### Using Test Agents from CLI
|
|
476
|
+
|
|
477
|
+
The CLI provides easy access to public test agents without configuration:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# Use test agent with authentication (MCP)
|
|
481
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
482
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
483
|
+
get_products '{"brief":"Coffee brands"}'
|
|
484
|
+
|
|
485
|
+
# Use test agent WITHOUT authentication (MCP)
|
|
486
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
487
|
+
get_products '{"brief":"Coffee brands"}'
|
|
488
|
+
|
|
489
|
+
# Use test agent with authentication (A2A)
|
|
490
|
+
uvx adcp --protocol a2a \
|
|
491
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
492
|
+
https://test-agent.adcontextprotocol.org \
|
|
493
|
+
get_products '{"brief":"Coffee brands"}'
|
|
494
|
+
|
|
495
|
+
# Save test agent for easier access
|
|
496
|
+
uvx adcp --save-auth test-agent https://test-agent.adcontextprotocol.org/mcp/ mcp
|
|
497
|
+
# Enter token when prompted: 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ
|
|
498
|
+
|
|
499
|
+
# Now use saved config
|
|
500
|
+
uvx adcp test-agent get_products '{"brief":"Coffee brands"}'
|
|
501
|
+
|
|
502
|
+
# Use creative agent (no auth required)
|
|
503
|
+
uvx adcp https://creative.adcontextprotocol.org/mcp \
|
|
504
|
+
preview_creative @creative_manifest.json
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**Test Agent Details:**
|
|
508
|
+
- **URL (MCP)**: `https://test-agent.adcontextprotocol.org/mcp/`
|
|
509
|
+
- **URL (A2A)**: `https://test-agent.adcontextprotocol.org`
|
|
510
|
+
- **Auth Token**: `1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ` (optional, public token)
|
|
511
|
+
- **Rate Limited**: For testing only, not for production
|
|
512
|
+
- **No Auth Mode**: Omit `--auth` flag to test unauthenticated behavior
|
|
513
|
+
```
|
|
514
|
+
|
|
378
515
|
### Configuration Management
|
|
379
516
|
|
|
380
517
|
```bash
|
|
@@ -22,8 +22,45 @@ AdCP operations are **distributed and asynchronous by default**. An agent might:
|
|
|
22
22
|
pip install adcp
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
> **Note**: This client requires Python 3.10 or later and supports both synchronous and asynchronous workflows.
|
|
26
|
+
|
|
27
|
+
## Quick Start: Test Helpers
|
|
28
|
+
|
|
29
|
+
The fastest way to get started is using the pre-configured test agents:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from adcp.testing import test_agent
|
|
33
|
+
from adcp.types.generated import GetProductsRequest
|
|
34
|
+
|
|
35
|
+
# Zero configuration - just import and use!
|
|
36
|
+
result = await test_agent.get_products(
|
|
37
|
+
GetProductsRequest(
|
|
38
|
+
brief="Coffee subscription service",
|
|
39
|
+
promoted_offering="Premium coffee deliveries"
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if result.success:
|
|
44
|
+
print(f"Found {len(result.data.products)} products")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Test helpers include:
|
|
48
|
+
- **`test_agent`**: Pre-configured MCP test agent with authentication
|
|
49
|
+
- **`test_agent_a2a`**: Pre-configured A2A test agent with authentication
|
|
50
|
+
- **`test_agent_no_auth`**: Pre-configured MCP test agent WITHOUT authentication
|
|
51
|
+
- **`test_agent_a2a_no_auth`**: Pre-configured A2A test agent WITHOUT authentication
|
|
52
|
+
- **`creative_agent`**: Reference creative agent for preview functionality
|
|
53
|
+
- **`test_agent_client`**: Multi-agent client with both protocols
|
|
54
|
+
- **`create_test_agent()`**: Factory for custom test configurations
|
|
55
|
+
|
|
56
|
+
> **Note**: Test agents are rate-limited and for testing/examples only. DO NOT use in production.
|
|
57
|
+
|
|
58
|
+
See [examples/test_helpers_demo.py](examples/test_helpers_demo.py) for more examples.
|
|
59
|
+
|
|
25
60
|
## Quick Start: Distributed Operations
|
|
26
61
|
|
|
62
|
+
For production use, configure your own agents:
|
|
63
|
+
|
|
27
64
|
```python
|
|
28
65
|
from adcp import ADCPMultiAgentClient, AgentConfig, GetProductsRequest
|
|
29
66
|
|
|
@@ -73,6 +110,66 @@ async with ADCPMultiAgentClient(
|
|
|
73
110
|
|
|
74
111
|
## Features
|
|
75
112
|
|
|
113
|
+
### Test Helpers
|
|
114
|
+
|
|
115
|
+
Pre-configured test agents for instant prototyping and testing:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from adcp.testing import (
|
|
119
|
+
test_agent, test_agent_a2a,
|
|
120
|
+
test_agent_no_auth, test_agent_a2a_no_auth,
|
|
121
|
+
creative_agent, test_agent_client, create_test_agent
|
|
122
|
+
)
|
|
123
|
+
from adcp.types.generated import GetProductsRequest, PreviewCreativeRequest
|
|
124
|
+
|
|
125
|
+
# 1. Single agent with authentication (MCP)
|
|
126
|
+
result = await test_agent.get_products(
|
|
127
|
+
GetProductsRequest(brief="Coffee brands")
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# 2. Single agent with authentication (A2A)
|
|
131
|
+
result = await test_agent_a2a.get_products(
|
|
132
|
+
GetProductsRequest(brief="Coffee brands")
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# 3. Single agent WITHOUT authentication (MCP)
|
|
136
|
+
# Useful for testing unauthenticated behavior
|
|
137
|
+
result = await test_agent_no_auth.get_products(
|
|
138
|
+
GetProductsRequest(brief="Coffee brands")
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# 4. Single agent WITHOUT authentication (A2A)
|
|
142
|
+
result = await test_agent_a2a_no_auth.get_products(
|
|
143
|
+
GetProductsRequest(brief="Coffee brands")
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# 5. Creative agent (preview functionality, no auth required)
|
|
147
|
+
result = await creative_agent.preview_creative(
|
|
148
|
+
PreviewCreativeRequest(
|
|
149
|
+
manifest={"format_id": "banner_300x250", "assets": {...}}
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# 6. Multi-agent (parallel execution with both protocols)
|
|
154
|
+
results = await test_agent_client.get_products(
|
|
155
|
+
GetProductsRequest(brief="Coffee brands")
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# 7. Custom configuration
|
|
159
|
+
from adcp.client import ADCPClient
|
|
160
|
+
config = create_test_agent(id="my-test", timeout=60.0)
|
|
161
|
+
client = ADCPClient(config)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Use cases:**
|
|
165
|
+
- Quick prototyping and experimentation
|
|
166
|
+
- Example code and documentation
|
|
167
|
+
- Integration testing without mock servers
|
|
168
|
+
- Testing authentication behavior (comparing auth vs no-auth results)
|
|
169
|
+
- Learning AdCP concepts
|
|
170
|
+
|
|
171
|
+
**Important:** Test agents are public, rate-limited, and for testing only. Never use in production.
|
|
172
|
+
|
|
76
173
|
### Full Protocol Support
|
|
77
174
|
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
78
175
|
- **MCP Protocol**: Native support for Model Context Protocol
|
|
@@ -338,6 +435,46 @@ uvx adcp --json myagent get_products '{"brief":"TV ads"}'
|
|
|
338
435
|
uvx adcp --debug myagent get_products '{"brief":"TV ads"}'
|
|
339
436
|
```
|
|
340
437
|
|
|
438
|
+
### Using Test Agents from CLI
|
|
439
|
+
|
|
440
|
+
The CLI provides easy access to public test agents without configuration:
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
# Use test agent with authentication (MCP)
|
|
444
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
445
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
446
|
+
get_products '{"brief":"Coffee brands"}'
|
|
447
|
+
|
|
448
|
+
# Use test agent WITHOUT authentication (MCP)
|
|
449
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
450
|
+
get_products '{"brief":"Coffee brands"}'
|
|
451
|
+
|
|
452
|
+
# Use test agent with authentication (A2A)
|
|
453
|
+
uvx adcp --protocol a2a \
|
|
454
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
455
|
+
https://test-agent.adcontextprotocol.org \
|
|
456
|
+
get_products '{"brief":"Coffee brands"}'
|
|
457
|
+
|
|
458
|
+
# Save test agent for easier access
|
|
459
|
+
uvx adcp --save-auth test-agent https://test-agent.adcontextprotocol.org/mcp/ mcp
|
|
460
|
+
# Enter token when prompted: 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ
|
|
461
|
+
|
|
462
|
+
# Now use saved config
|
|
463
|
+
uvx adcp test-agent get_products '{"brief":"Coffee brands"}'
|
|
464
|
+
|
|
465
|
+
# Use creative agent (no auth required)
|
|
466
|
+
uvx adcp https://creative.adcontextprotocol.org/mcp \
|
|
467
|
+
preview_creative @creative_manifest.json
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Test Agent Details:**
|
|
471
|
+
- **URL (MCP)**: `https://test-agent.adcontextprotocol.org/mcp/`
|
|
472
|
+
- **URL (A2A)**: `https://test-agent.adcontextprotocol.org`
|
|
473
|
+
- **Auth Token**: `1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ` (optional, public token)
|
|
474
|
+
- **Rate Limited**: For testing only, not for production
|
|
475
|
+
- **No Auth Mode**: Omit `--auth` flag to test unauthenticated behavior
|
|
476
|
+
```
|
|
477
|
+
|
|
341
478
|
### Configuration Management
|
|
342
479
|
|
|
343
480
|
```bash
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "adcp"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Official Python client for the Ad Context Protocol (AdCP)"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "AdCP Community", email = "maintainers@adcontextprotocol.org"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
AdCP Python Client Library
|
|
5
|
+
|
|
6
|
+
Official Python client for the Ad Context Protocol (AdCP).
|
|
7
|
+
Supports both A2A and MCP protocols with full type safety.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from adcp.client import ADCPClient, ADCPMultiAgentClient
|
|
11
|
+
from adcp.exceptions import (
|
|
12
|
+
ADCPAuthenticationError,
|
|
13
|
+
ADCPConnectionError,
|
|
14
|
+
ADCPError,
|
|
15
|
+
ADCPProtocolError,
|
|
16
|
+
ADCPTimeoutError,
|
|
17
|
+
ADCPToolNotFoundError,
|
|
18
|
+
ADCPWebhookError,
|
|
19
|
+
ADCPWebhookSignatureError,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Test helpers
|
|
23
|
+
from adcp.testing import (
|
|
24
|
+
CREATIVE_AGENT_CONFIG,
|
|
25
|
+
TEST_AGENT_A2A_CONFIG,
|
|
26
|
+
TEST_AGENT_MCP_CONFIG,
|
|
27
|
+
TEST_AGENT_TOKEN,
|
|
28
|
+
create_test_agent,
|
|
29
|
+
creative_agent,
|
|
30
|
+
test_agent,
|
|
31
|
+
test_agent_a2a,
|
|
32
|
+
test_agent_client,
|
|
33
|
+
)
|
|
34
|
+
from adcp.types.core import AgentConfig, Protocol, TaskResult, TaskStatus, WebhookMetadata
|
|
35
|
+
from adcp.types.generated import (
|
|
36
|
+
ActivateSignalError,
|
|
37
|
+
# Request/Response types
|
|
38
|
+
ActivateSignalRequest,
|
|
39
|
+
ActivateSignalResponse,
|
|
40
|
+
ActivateSignalSuccess,
|
|
41
|
+
ActivationKey,
|
|
42
|
+
AgentDeployment,
|
|
43
|
+
AgentDestination,
|
|
44
|
+
BothPreviewRender,
|
|
45
|
+
# Brand types
|
|
46
|
+
BrandManifest,
|
|
47
|
+
BrandManifestRef,
|
|
48
|
+
BuildCreativeRequest,
|
|
49
|
+
BuildCreativeResponse,
|
|
50
|
+
# Channel types
|
|
51
|
+
Channels,
|
|
52
|
+
CreateMediaBuyError,
|
|
53
|
+
CreateMediaBuyRequest,
|
|
54
|
+
CreateMediaBuyResponse,
|
|
55
|
+
CreateMediaBuySuccess,
|
|
56
|
+
# Creative types
|
|
57
|
+
CreativeAsset,
|
|
58
|
+
CreativeAssignment,
|
|
59
|
+
CreativeManifest,
|
|
60
|
+
CreativePolicy,
|
|
61
|
+
DaastAsset,
|
|
62
|
+
# Metrics types
|
|
63
|
+
DeliveryMetrics,
|
|
64
|
+
# Delivery types
|
|
65
|
+
DeliveryType,
|
|
66
|
+
Deployment,
|
|
67
|
+
# Deployment types
|
|
68
|
+
Destination,
|
|
69
|
+
Error,
|
|
70
|
+
Format,
|
|
71
|
+
FormatId,
|
|
72
|
+
FrequencyCap,
|
|
73
|
+
GetMediaBuyDeliveryRequest,
|
|
74
|
+
GetMediaBuyDeliveryResponse,
|
|
75
|
+
GetProductsRequest,
|
|
76
|
+
GetProductsResponse,
|
|
77
|
+
GetSignalsRequest,
|
|
78
|
+
GetSignalsResponse,
|
|
79
|
+
HtmlPreviewRender,
|
|
80
|
+
InlineDaastAsset,
|
|
81
|
+
InlineVastAsset,
|
|
82
|
+
Key_valueActivationKey,
|
|
83
|
+
ListAuthorizedPropertiesRequest,
|
|
84
|
+
ListAuthorizedPropertiesResponse,
|
|
85
|
+
ListCreativeFormatsRequest,
|
|
86
|
+
ListCreativeFormatsResponse,
|
|
87
|
+
ListCreativesRequest,
|
|
88
|
+
ListCreativesResponse,
|
|
89
|
+
Measurement,
|
|
90
|
+
# Core domain types
|
|
91
|
+
MediaBuy,
|
|
92
|
+
# Status enums
|
|
93
|
+
MediaBuyStatus,
|
|
94
|
+
# Sub-asset types
|
|
95
|
+
MediaSubAsset,
|
|
96
|
+
Pacing,
|
|
97
|
+
Package,
|
|
98
|
+
PackageStatus,
|
|
99
|
+
PerformanceFeedback,
|
|
100
|
+
Placement,
|
|
101
|
+
PlatformDeployment,
|
|
102
|
+
PlatformDestination,
|
|
103
|
+
PreviewCreativeRequest,
|
|
104
|
+
PreviewCreativeResponse,
|
|
105
|
+
# Preview render types
|
|
106
|
+
PreviewRender,
|
|
107
|
+
PricingModel,
|
|
108
|
+
# Pricing types
|
|
109
|
+
PricingOption,
|
|
110
|
+
Product,
|
|
111
|
+
PromotedProducts,
|
|
112
|
+
# Property and placement types
|
|
113
|
+
Property,
|
|
114
|
+
ProtocolEnvelope,
|
|
115
|
+
ProvidePerformanceFeedbackRequest,
|
|
116
|
+
ProvidePerformanceFeedbackResponse,
|
|
117
|
+
PushNotificationConfig,
|
|
118
|
+
ReportingCapabilities,
|
|
119
|
+
Response,
|
|
120
|
+
Segment_idActivationKey,
|
|
121
|
+
StandardFormatIds,
|
|
122
|
+
StartTiming,
|
|
123
|
+
SubAsset,
|
|
124
|
+
SyncCreativesError,
|
|
125
|
+
SyncCreativesRequest,
|
|
126
|
+
SyncCreativesResponse,
|
|
127
|
+
SyncCreativesSuccess,
|
|
128
|
+
# Targeting types
|
|
129
|
+
Targeting,
|
|
130
|
+
# Task types
|
|
131
|
+
TaskType,
|
|
132
|
+
TextSubAsset,
|
|
133
|
+
UpdateMediaBuyError,
|
|
134
|
+
UpdateMediaBuyRequest,
|
|
135
|
+
UpdateMediaBuyResponse,
|
|
136
|
+
UpdateMediaBuySuccess,
|
|
137
|
+
UrlDaastAsset,
|
|
138
|
+
UrlPreviewRender,
|
|
139
|
+
UrlVastAsset,
|
|
140
|
+
# Asset delivery types (VAST/DAAST)
|
|
141
|
+
VastAsset,
|
|
142
|
+
# Protocol types
|
|
143
|
+
WebhookPayload,
|
|
144
|
+
)
|
|
145
|
+
from adcp.types.generated import (
|
|
146
|
+
TaskStatus as GeneratedTaskStatus,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
__version__ = "1.3.0"
|
|
150
|
+
|
|
151
|
+
__all__ = [
|
|
152
|
+
# Client classes
|
|
153
|
+
"ADCPClient",
|
|
154
|
+
"ADCPMultiAgentClient",
|
|
155
|
+
# Core types
|
|
156
|
+
"AgentConfig",
|
|
157
|
+
"Protocol",
|
|
158
|
+
"TaskResult",
|
|
159
|
+
"TaskStatus",
|
|
160
|
+
"WebhookMetadata",
|
|
161
|
+
# Test helpers
|
|
162
|
+
"test_agent",
|
|
163
|
+
"test_agent_a2a",
|
|
164
|
+
"creative_agent",
|
|
165
|
+
"test_agent_client",
|
|
166
|
+
"create_test_agent",
|
|
167
|
+
"TEST_AGENT_TOKEN",
|
|
168
|
+
"TEST_AGENT_MCP_CONFIG",
|
|
169
|
+
"TEST_AGENT_A2A_CONFIG",
|
|
170
|
+
"CREATIVE_AGENT_CONFIG",
|
|
171
|
+
# Exceptions
|
|
172
|
+
"ADCPError",
|
|
173
|
+
"ADCPConnectionError",
|
|
174
|
+
"ADCPAuthenticationError",
|
|
175
|
+
"ADCPTimeoutError",
|
|
176
|
+
"ADCPProtocolError",
|
|
177
|
+
"ADCPToolNotFoundError",
|
|
178
|
+
"ADCPWebhookError",
|
|
179
|
+
"ADCPWebhookSignatureError",
|
|
180
|
+
# Request/Response types
|
|
181
|
+
"ActivateSignalRequest",
|
|
182
|
+
"ActivateSignalResponse",
|
|
183
|
+
"ActivateSignalSuccess",
|
|
184
|
+
"ActivateSignalError",
|
|
185
|
+
"ActivationKey",
|
|
186
|
+
"Segment_idActivationKey",
|
|
187
|
+
"Key_valueActivationKey",
|
|
188
|
+
"BuildCreativeRequest",
|
|
189
|
+
"BuildCreativeResponse",
|
|
190
|
+
"CreateMediaBuyRequest",
|
|
191
|
+
"CreateMediaBuyResponse",
|
|
192
|
+
"CreateMediaBuySuccess",
|
|
193
|
+
"CreateMediaBuyError",
|
|
194
|
+
"GetMediaBuyDeliveryRequest",
|
|
195
|
+
"GetMediaBuyDeliveryResponse",
|
|
196
|
+
"GetProductsRequest",
|
|
197
|
+
"GetProductsResponse",
|
|
198
|
+
"GetSignalsRequest",
|
|
199
|
+
"GetSignalsResponse",
|
|
200
|
+
"ListAuthorizedPropertiesRequest",
|
|
201
|
+
"ListAuthorizedPropertiesResponse",
|
|
202
|
+
"ListCreativeFormatsRequest",
|
|
203
|
+
"ListCreativeFormatsResponse",
|
|
204
|
+
"ListCreativesRequest",
|
|
205
|
+
"ListCreativesResponse",
|
|
206
|
+
"PreviewCreativeRequest",
|
|
207
|
+
"PreviewCreativeResponse",
|
|
208
|
+
"ProvidePerformanceFeedbackRequest",
|
|
209
|
+
"ProvidePerformanceFeedbackResponse",
|
|
210
|
+
"SyncCreativesRequest",
|
|
211
|
+
"SyncCreativesResponse",
|
|
212
|
+
"SyncCreativesSuccess",
|
|
213
|
+
"SyncCreativesError",
|
|
214
|
+
"UpdateMediaBuyRequest",
|
|
215
|
+
"UpdateMediaBuyResponse",
|
|
216
|
+
"UpdateMediaBuySuccess",
|
|
217
|
+
"UpdateMediaBuyError",
|
|
218
|
+
# Core domain types
|
|
219
|
+
"MediaBuy",
|
|
220
|
+
"Product",
|
|
221
|
+
"Package",
|
|
222
|
+
"Error",
|
|
223
|
+
# Creative types
|
|
224
|
+
"CreativeAsset",
|
|
225
|
+
"CreativeManifest",
|
|
226
|
+
"CreativeAssignment",
|
|
227
|
+
"CreativePolicy",
|
|
228
|
+
"Format",
|
|
229
|
+
"FormatId",
|
|
230
|
+
# Property and placement types
|
|
231
|
+
"Property",
|
|
232
|
+
"Placement",
|
|
233
|
+
# Targeting types
|
|
234
|
+
"Targeting",
|
|
235
|
+
"FrequencyCap",
|
|
236
|
+
"Pacing",
|
|
237
|
+
# Brand types
|
|
238
|
+
"BrandManifest",
|
|
239
|
+
"BrandManifestRef",
|
|
240
|
+
# Metrics types
|
|
241
|
+
"DeliveryMetrics",
|
|
242
|
+
"Measurement",
|
|
243
|
+
"PerformanceFeedback",
|
|
244
|
+
# Status enums
|
|
245
|
+
"MediaBuyStatus",
|
|
246
|
+
"PackageStatus",
|
|
247
|
+
# Pricing types
|
|
248
|
+
"PricingOption",
|
|
249
|
+
"PricingModel",
|
|
250
|
+
# Delivery types
|
|
251
|
+
"DeliveryType",
|
|
252
|
+
"StartTiming",
|
|
253
|
+
# Channel types
|
|
254
|
+
"Channels",
|
|
255
|
+
"StandardFormatIds",
|
|
256
|
+
# Protocol types
|
|
257
|
+
"WebhookPayload",
|
|
258
|
+
"ProtocolEnvelope",
|
|
259
|
+
"Response",
|
|
260
|
+
"PromotedProducts",
|
|
261
|
+
"PushNotificationConfig",
|
|
262
|
+
"ReportingCapabilities",
|
|
263
|
+
# Deployment types
|
|
264
|
+
"Destination",
|
|
265
|
+
"Deployment",
|
|
266
|
+
"PlatformDestination",
|
|
267
|
+
"AgentDestination",
|
|
268
|
+
"PlatformDeployment",
|
|
269
|
+
"AgentDeployment",
|
|
270
|
+
# Sub-asset types
|
|
271
|
+
"MediaSubAsset",
|
|
272
|
+
"SubAsset",
|
|
273
|
+
"TextSubAsset",
|
|
274
|
+
# Asset delivery types (VAST/DAAST)
|
|
275
|
+
"VastAsset",
|
|
276
|
+
"UrlVastAsset",
|
|
277
|
+
"InlineVastAsset",
|
|
278
|
+
"DaastAsset",
|
|
279
|
+
"UrlDaastAsset",
|
|
280
|
+
"InlineDaastAsset",
|
|
281
|
+
# Preview render types
|
|
282
|
+
"PreviewRender",
|
|
283
|
+
"UrlPreviewRender",
|
|
284
|
+
"HtmlPreviewRender",
|
|
285
|
+
"BothPreviewRender",
|
|
286
|
+
# Task types
|
|
287
|
+
"TaskType",
|
|
288
|
+
"GeneratedTaskStatus",
|
|
289
|
+
]
|
|
@@ -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
|
|
|
@@ -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
|