adcp 1.6.0__tar.gz → 2.0.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.6.0/src/adcp.egg-info → adcp-2.0.0}/PKG-INFO +3 -1
- {adcp-1.6.0 → adcp-2.0.0}/pyproject.toml +14 -2
- adcp-2.0.0/src/adcp/__init__.py +120 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/adagents.py +11 -12
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/client.py +16 -11
- adcp-2.0.0/src/adcp/types/generated.py +614 -0
- adcp-2.0.0/src/adcp/types/generated_poc/__init__.py +3 -0
- adcp-2.0.0/src/adcp/types/generated_poc/activate_signal_request.py +34 -0
- adcp-2.0.0/src/adcp/types/generated_poc/activate_signal_response.py +57 -0
- adcp-2.0.0/src/adcp/types/generated_poc/activation_key.py +30 -0
- adcp-2.0.0/src/adcp/types/generated_poc/adagents.py +266 -0
- adcp-2.0.0/src/adcp/types/generated_poc/asset_type.py +100 -0
- adcp-2.0.0/src/adcp/types/generated_poc/audio_asset.py +26 -0
- adcp-2.0.0/src/adcp/types/generated_poc/brand_manifest.py +260 -0
- adcp-2.0.0/src/adcp/types/generated_poc/brand_manifest_ref.py +361 -0
- adcp-2.0.0/src/adcp/types/generated_poc/build_creative_request.py +43 -0
- adcp-2.0.0/src/adcp/types/generated_poc/build_creative_response.py +57 -0
- adcp-2.0.0/src/adcp/types/generated_poc/channels.py +19 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpc_option.py +39 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpcv_option.py +41 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpm_auction_option.py +54 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpm_fixed_option.py +39 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpp_option.py +60 -0
- adcp-2.0.0/src/adcp/types/generated_poc/cpv_option.py +73 -0
- adcp-2.0.0/src/adcp/types/generated_poc/create_media_buy_request.py +96 -0
- adcp-2.0.0/src/adcp/types/generated_poc/create_media_buy_response.py +66 -0
- adcp-2.0.0/src/adcp/types/generated_poc/creative_asset.py +83 -0
- adcp-2.0.0/src/adcp/types/generated_poc/creative_assignment.py +27 -0
- adcp-2.0.0/src/adcp/types/generated_poc/creative_manifest.py +61 -0
- adcp-2.0.0/src/adcp/types/generated_poc/creative_policy.py +34 -0
- adcp-2.0.0/src/adcp/types/generated_poc/creative_status.py +14 -0
- adcp-2.0.0/src/adcp/types/generated_poc/css_asset.py +20 -0
- adcp-2.0.0/src/adcp/types/generated_poc/daast_asset.py +76 -0
- adcp-2.0.0/src/adcp/types/generated_poc/delivery_metrics.py +111 -0
- adcp-2.0.0/src/adcp/types/generated_poc/delivery_type.py +12 -0
- adcp-2.0.0/src/adcp/types/generated_poc/deployment.py +78 -0
- adcp-2.0.0/src/adcp/types/generated_poc/destination.py +43 -0
- adcp-2.0.0/src/adcp/types/generated_poc/error.py +29 -0
- adcp-2.0.0/src/adcp/types/generated_poc/flat_rate_option.py +93 -0
- adcp-2.0.0/src/adcp/types/generated_poc/format.py +260 -0
- adcp-2.0.0/src/adcp/types/generated_poc/format_id.py +29 -0
- adcp-2.0.0/src/adcp/types/generated_poc/frequency_cap.py +19 -0
- adcp-2.0.0/src/adcp/types/generated_poc/frequency_cap_scope.py +16 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_media_buy_delivery_request.py +65 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_media_buy_delivery_response.py +220 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_products_request.py +83 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_products_response.py +29 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_signals_request.py +77 -0
- adcp-2.0.0/src/adcp/types/generated_poc/get_signals_response.py +65 -0
- adcp-2.0.0/src/adcp/types/generated_poc/html_asset.py +18 -0
- adcp-2.0.0/src/adcp/types/generated_poc/identifier_types.py +29 -0
- adcp-2.0.0/src/adcp/types/generated_poc/image_asset.py +23 -0
- adcp-2.0.0/src/adcp/types/generated_poc/index.py +17 -0
- adcp-2.0.0/src/adcp/types/generated_poc/javascript_asset.py +25 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_authorized_properties_request.py +39 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_authorized_properties_response.py +85 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_creative_formats_request.py +93 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_creative_formats_response.py +63 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_creatives_request.py +154 -0
- adcp-2.0.0/src/adcp/types/generated_poc/list_creatives_response.py +234 -0
- adcp-2.0.0/src/adcp/types/generated_poc/markdown_asset.py +43 -0
- adcp-2.0.0/src/adcp/types/generated_poc/measurement.py +40 -0
- adcp-2.0.0/src/adcp/types/generated_poc/media_buy.py +37 -0
- adcp-2.0.0/src/adcp/types/generated_poc/media_buy_status.py +14 -0
- adcp-2.0.0/src/adcp/types/generated_poc/pacing.py +13 -0
- adcp-2.0.0/src/adcp/types/generated_poc/package.py +61 -0
- adcp-2.0.0/src/adcp/types/generated_poc/package_request.py +61 -0
- adcp-2.0.0/src/adcp/types/generated_poc/package_status.py +14 -0
- adcp-2.0.0/src/adcp/types/generated_poc/performance_feedback.py +89 -0
- adcp-2.0.0/src/adcp/types/generated_poc/placement.py +37 -0
- adcp-2.0.0/src/adcp/types/generated_poc/preview_creative_request.py +163 -0
- adcp-2.0.0/src/adcp/types/generated_poc/preview_creative_response.py +175 -0
- adcp-2.0.0/src/adcp/types/generated_poc/preview_render.py +144 -0
- adcp-2.0.0/src/adcp/types/generated_poc/pricing_model.py +17 -0
- adcp-2.0.0/src/adcp/types/generated_poc/pricing_option.py +365 -0
- adcp-2.0.0/src/adcp/types/generated_poc/product.py +211 -0
- adcp-2.0.0/src/adcp/types/generated_poc/promoted_offerings.py +102 -0
- adcp-2.0.0/src/adcp/types/generated_poc/promoted_products.py +38 -0
- adcp-2.0.0/src/adcp/types/generated_poc/property.py +79 -0
- adcp-2.0.0/src/adcp/types/generated_poc/protocol_envelope.py +61 -0
- adcp-2.0.0/src/adcp/types/generated_poc/provide_performance_feedback_request.py +85 -0
- adcp-2.0.0/src/adcp/types/generated_poc/provide_performance_feedback_response.py +59 -0
- adcp-2.0.0/src/adcp/types/generated_poc/publisher_identifier_types.py +15 -0
- adcp-2.0.0/src/adcp/types/generated_poc/push_notification_config.py +55 -0
- adcp-2.0.0/src/adcp/types/generated_poc/reporting_capabilities.py +68 -0
- adcp-2.0.0/src/adcp/types/generated_poc/response.py +24 -0
- adcp-2.0.0/src/adcp/types/generated_poc/standard_format_ids.py +45 -0
- adcp-2.0.0/src/adcp/types/generated_poc/start_timing.py +13 -0
- adcp-2.0.0/src/adcp/types/generated_poc/sub_asset.py +55 -0
- adcp-2.0.0/src/adcp/types/generated_poc/sync_creatives_request.py +69 -0
- adcp-2.0.0/src/adcp/types/generated_poc/sync_creatives_response.py +117 -0
- adcp-2.0.0/src/adcp/types/generated_poc/targeting.py +53 -0
- adcp-2.0.0/src/adcp/types/generated_poc/task_status.py +19 -0
- adcp-2.0.0/src/adcp/types/generated_poc/task_type.py +15 -0
- adcp-2.0.0/src/adcp/types/generated_poc/tasks_get_request.py +29 -0
- adcp-2.0.0/src/adcp/types/generated_poc/tasks_get_response.py +112 -0
- adcp-2.0.0/src/adcp/types/generated_poc/tasks_list_request.py +121 -0
- adcp-2.0.0/src/adcp/types/generated_poc/tasks_list_response.py +122 -0
- adcp-2.0.0/src/adcp/types/generated_poc/text_asset.py +20 -0
- adcp-2.0.0/src/adcp/types/generated_poc/update_media_buy_request.py +160 -0
- adcp-2.0.0/src/adcp/types/generated_poc/update_media_buy_response.py +67 -0
- adcp-2.0.0/src/adcp/types/generated_poc/url_asset.py +33 -0
- adcp-2.0.0/src/adcp/types/generated_poc/vast_asset.py +86 -0
- adcp-2.0.0/src/adcp/types/generated_poc/vcpm_auction_option.py +57 -0
- adcp-2.0.0/src/adcp/types/generated_poc/vcpm_fixed_option.py +43 -0
- adcp-2.0.0/src/adcp/types/generated_poc/video_asset.py +28 -0
- adcp-2.0.0/src/adcp/types/generated_poc/webhook_asset.py +65 -0
- adcp-2.0.0/src/adcp/types/generated_poc/webhook_payload.py +102 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/utils/preview_cache.py +57 -39
- adcp-2.0.0/src/adcp/validation.py +172 -0
- {adcp-1.6.0 → adcp-2.0.0/src/adcp.egg-info}/PKG-INFO +3 -1
- adcp-2.0.0/src/adcp.egg-info/SOURCES.txt +144 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp.egg-info/requires.txt +2 -0
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_adagents.py +58 -18
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_client.py +19 -2
- adcp-2.0.0/tests/test_code_generation.py +64 -0
- adcp-2.0.0/tests/test_discriminated_unions.py +444 -0
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_format_id_validation.py +5 -6
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_preview_html.py +123 -56
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_protocols.py +3 -1
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_simple_api.py +30 -7
- adcp-1.6.0/src/adcp/__init__.py +0 -322
- adcp-1.6.0/src/adcp/types/generated.py +0 -1203
- adcp-1.6.0/src/adcp/types/tasks.py +0 -511
- adcp-1.6.0/src/adcp.egg-info/SOURCES.txt +0 -42
- adcp-1.6.0/tests/test_code_generation.py +0 -400
- adcp-1.6.0/tests/test_discriminated_unions.py +0 -404
- {adcp-1.6.0 → adcp-2.0.0}/LICENSE +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/README.md +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/setup.cfg +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/__main__.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/config.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/exceptions.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/protocols/__init__.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/protocols/a2a.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/protocols/base.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/protocols/mcp.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/simple.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/testing/__init__.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/testing/test_helpers.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/types/__init__.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/types/base.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/types/core.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/utils/__init__.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/utils/operation_id.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp/utils/response_parser.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp.egg-info/dependency_links.txt +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp.egg-info/entry_points.txt +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/src/adcp.egg-info/top_level.txt +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_cli.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_helpers.py +0 -0
- {adcp-1.6.0 → adcp-2.0.0}/tests/test_response_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adcp
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.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
|
|
@@ -33,6 +33,8 @@ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
|
33
33
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
34
34
|
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
35
35
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: datamodel-code-generator[http]>=0.35.0; extra == "dev"
|
|
37
|
+
Requires-Dist: email-validator>=2.0.0; extra == "dev"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
38
40
|
# adcp - Python Client for Ad Context Protocol
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "adcp"
|
|
7
|
-
version = "
|
|
7
|
+
version = "2.0.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"}
|
|
@@ -44,6 +44,8 @@ dev = [
|
|
|
44
44
|
"mypy>=1.0.0",
|
|
45
45
|
"black>=23.0.0",
|
|
46
46
|
"ruff>=0.1.0",
|
|
47
|
+
"datamodel-code-generator[http]>=0.35.0",
|
|
48
|
+
"email-validator>=2.0.0",
|
|
47
49
|
]
|
|
48
50
|
|
|
49
51
|
[project.urls]
|
|
@@ -63,7 +65,11 @@ extend-exclude = "/(generated|tasks)\\.py$"
|
|
|
63
65
|
[tool.ruff]
|
|
64
66
|
line-length = 100
|
|
65
67
|
target-version = "py310"
|
|
66
|
-
extend-exclude = [
|
|
68
|
+
extend-exclude = [
|
|
69
|
+
"src/adcp/types/generated.py",
|
|
70
|
+
"src/adcp/types/tasks.py",
|
|
71
|
+
"src/adcp/types/generated_poc/",
|
|
72
|
+
]
|
|
67
73
|
|
|
68
74
|
[tool.ruff.lint]
|
|
69
75
|
select = ["E", "F", "I", "N", "W", "UP"]
|
|
@@ -86,3 +92,9 @@ ignore_errors = true
|
|
|
86
92
|
[tool.pytest.ini_options]
|
|
87
93
|
testpaths = ["tests"]
|
|
88
94
|
asyncio_mode = "auto"
|
|
95
|
+
|
|
96
|
+
[dependency-groups]
|
|
97
|
+
dev = [
|
|
98
|
+
"datamodel-code-generator>=0.35.0",
|
|
99
|
+
"pre-commit>=4.4.0",
|
|
100
|
+
]
|
|
@@ -0,0 +1,120 @@
|
|
|
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.adagents import (
|
|
11
|
+
domain_matches,
|
|
12
|
+
fetch_adagents,
|
|
13
|
+
get_all_properties,
|
|
14
|
+
get_all_tags,
|
|
15
|
+
get_properties_by_agent,
|
|
16
|
+
identifiers_match,
|
|
17
|
+
verify_agent_authorization,
|
|
18
|
+
verify_agent_for_property,
|
|
19
|
+
)
|
|
20
|
+
from adcp.client import ADCPClient, ADCPMultiAgentClient
|
|
21
|
+
from adcp.exceptions import (
|
|
22
|
+
AdagentsNotFoundError,
|
|
23
|
+
AdagentsTimeoutError,
|
|
24
|
+
AdagentsValidationError,
|
|
25
|
+
ADCPAuthenticationError,
|
|
26
|
+
ADCPConnectionError,
|
|
27
|
+
ADCPError,
|
|
28
|
+
ADCPProtocolError,
|
|
29
|
+
ADCPTimeoutError,
|
|
30
|
+
ADCPToolNotFoundError,
|
|
31
|
+
ADCPWebhookError,
|
|
32
|
+
ADCPWebhookSignatureError,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Test helpers
|
|
36
|
+
from adcp.testing import (
|
|
37
|
+
CREATIVE_AGENT_CONFIG,
|
|
38
|
+
TEST_AGENT_A2A_CONFIG,
|
|
39
|
+
TEST_AGENT_A2A_NO_AUTH_CONFIG,
|
|
40
|
+
TEST_AGENT_MCP_CONFIG,
|
|
41
|
+
TEST_AGENT_MCP_NO_AUTH_CONFIG,
|
|
42
|
+
TEST_AGENT_TOKEN,
|
|
43
|
+
create_test_agent,
|
|
44
|
+
creative_agent,
|
|
45
|
+
test_agent,
|
|
46
|
+
test_agent_a2a,
|
|
47
|
+
test_agent_a2a_no_auth,
|
|
48
|
+
test_agent_client,
|
|
49
|
+
test_agent_no_auth,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Import all generated types - users can import what they need from adcp.types.generated
|
|
53
|
+
from adcp.types import generated
|
|
54
|
+
from adcp.types.core import AgentConfig, Protocol, TaskResult, TaskStatus, WebhookMetadata
|
|
55
|
+
from adcp.types.generated import TaskStatus as GeneratedTaskStatus
|
|
56
|
+
from adcp.validation import (
|
|
57
|
+
ValidationError,
|
|
58
|
+
validate_adagents,
|
|
59
|
+
validate_agent_authorization,
|
|
60
|
+
validate_product,
|
|
61
|
+
validate_publisher_properties_item,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
__version__ = "2.0.0"
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
# Client classes
|
|
68
|
+
"ADCPClient",
|
|
69
|
+
"ADCPMultiAgentClient",
|
|
70
|
+
# Core types
|
|
71
|
+
"AgentConfig",
|
|
72
|
+
"Protocol",
|
|
73
|
+
"TaskResult",
|
|
74
|
+
"TaskStatus",
|
|
75
|
+
"WebhookMetadata",
|
|
76
|
+
# Adagents validation
|
|
77
|
+
"fetch_adagents",
|
|
78
|
+
"verify_agent_authorization",
|
|
79
|
+
"verify_agent_for_property",
|
|
80
|
+
"domain_matches",
|
|
81
|
+
"identifiers_match",
|
|
82
|
+
"get_all_properties",
|
|
83
|
+
"get_all_tags",
|
|
84
|
+
"get_properties_by_agent",
|
|
85
|
+
# Test helpers
|
|
86
|
+
"test_agent",
|
|
87
|
+
"test_agent_a2a",
|
|
88
|
+
"test_agent_no_auth",
|
|
89
|
+
"test_agent_a2a_no_auth",
|
|
90
|
+
"creative_agent",
|
|
91
|
+
"test_agent_client",
|
|
92
|
+
"create_test_agent",
|
|
93
|
+
"TEST_AGENT_TOKEN",
|
|
94
|
+
"TEST_AGENT_MCP_CONFIG",
|
|
95
|
+
"TEST_AGENT_A2A_CONFIG",
|
|
96
|
+
"TEST_AGENT_MCP_NO_AUTH_CONFIG",
|
|
97
|
+
"TEST_AGENT_A2A_NO_AUTH_CONFIG",
|
|
98
|
+
"CREATIVE_AGENT_CONFIG",
|
|
99
|
+
# Exceptions
|
|
100
|
+
"ADCPError",
|
|
101
|
+
"ADCPConnectionError",
|
|
102
|
+
"ADCPAuthenticationError",
|
|
103
|
+
"ADCPTimeoutError",
|
|
104
|
+
"ADCPProtocolError",
|
|
105
|
+
"ADCPToolNotFoundError",
|
|
106
|
+
"ADCPWebhookError",
|
|
107
|
+
"ADCPWebhookSignatureError",
|
|
108
|
+
"AdagentsValidationError",
|
|
109
|
+
"AdagentsNotFoundError",
|
|
110
|
+
"AdagentsTimeoutError",
|
|
111
|
+
# Validation utilities
|
|
112
|
+
"ValidationError",
|
|
113
|
+
"validate_adagents",
|
|
114
|
+
"validate_agent_authorization",
|
|
115
|
+
"validate_product",
|
|
116
|
+
"validate_publisher_properties_item",
|
|
117
|
+
# Generated types module
|
|
118
|
+
"generated",
|
|
119
|
+
"GeneratedTaskStatus",
|
|
120
|
+
]
|
|
@@ -14,6 +14,7 @@ from urllib.parse import urlparse
|
|
|
14
14
|
import httpx
|
|
15
15
|
|
|
16
16
|
from adcp.exceptions import AdagentsNotFoundError, AdagentsTimeoutError, AdagentsValidationError
|
|
17
|
+
from adcp.validation import ValidationError, validate_adagents
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def _normalize_domain(domain: str) -> str:
|
|
@@ -56,9 +57,7 @@ def _validate_publisher_domain(domain: str) -> str:
|
|
|
56
57
|
suspicious_chars = ["\\", "@", "\n", "\r", "\t"]
|
|
57
58
|
for char in suspicious_chars:
|
|
58
59
|
if char in domain:
|
|
59
|
-
raise AdagentsValidationError(
|
|
60
|
-
f"Invalid character in publisher domain: {char!r}"
|
|
61
|
-
)
|
|
60
|
+
raise AdagentsValidationError(f"Invalid character in publisher domain: {char!r}")
|
|
62
61
|
|
|
63
62
|
domain = domain.strip()
|
|
64
63
|
|
|
@@ -70,9 +69,7 @@ def _validate_publisher_domain(domain: str) -> str:
|
|
|
70
69
|
|
|
71
70
|
# Check for spaces after stripping leading/trailing whitespace
|
|
72
71
|
if " " in domain:
|
|
73
|
-
raise AdagentsValidationError(
|
|
74
|
-
"Invalid character in publisher domain: ' '"
|
|
75
|
-
)
|
|
72
|
+
raise AdagentsValidationError("Invalid character in publisher domain: ' '")
|
|
76
73
|
|
|
77
74
|
# Remove protocol if present (common user error) - do this BEFORE checking for slashes
|
|
78
75
|
if "://" in domain:
|
|
@@ -87,9 +84,7 @@ def _validate_publisher_domain(domain: str) -> str:
|
|
|
87
84
|
|
|
88
85
|
# Final validation - must look like a domain
|
|
89
86
|
if "." not in domain:
|
|
90
|
-
raise AdagentsValidationError(
|
|
91
|
-
f"Publisher domain must contain at least one dot: {domain!r}"
|
|
92
|
-
)
|
|
87
|
+
raise AdagentsValidationError(f"Publisher domain must contain at least one dot: {domain!r}")
|
|
93
88
|
|
|
94
89
|
return domain
|
|
95
90
|
|
|
@@ -359,13 +354,17 @@ async def fetch_adagents(
|
|
|
359
354
|
raise AdagentsValidationError("adagents.json must be a JSON object")
|
|
360
355
|
|
|
361
356
|
if "authorized_agents" not in data:
|
|
362
|
-
raise AdagentsValidationError(
|
|
363
|
-
"adagents.json must have 'authorized_agents' field"
|
|
364
|
-
)
|
|
357
|
+
raise AdagentsValidationError("adagents.json must have 'authorized_agents' field")
|
|
365
358
|
|
|
366
359
|
if not isinstance(data["authorized_agents"], list):
|
|
367
360
|
raise AdagentsValidationError("'authorized_agents' must be an array")
|
|
368
361
|
|
|
362
|
+
# Validate mutual exclusivity constraints
|
|
363
|
+
try:
|
|
364
|
+
validate_adagents(data)
|
|
365
|
+
except ValidationError as e:
|
|
366
|
+
raise AdagentsValidationError(f"Invalid adagents.json structure: {e}") from e
|
|
367
|
+
|
|
369
368
|
return data
|
|
370
369
|
|
|
371
370
|
except httpx.TimeoutException as e:
|
|
@@ -23,6 +23,7 @@ from adcp.types.core import (
|
|
|
23
23
|
AgentConfig,
|
|
24
24
|
Protocol,
|
|
25
25
|
TaskResult,
|
|
26
|
+
TaskStatus,
|
|
26
27
|
)
|
|
27
28
|
from adcp.types.generated import (
|
|
28
29
|
ActivateSignalRequest,
|
|
@@ -47,6 +48,7 @@ from adcp.types.generated import (
|
|
|
47
48
|
SyncCreativesResponse,
|
|
48
49
|
WebhookPayload,
|
|
49
50
|
)
|
|
51
|
+
from adcp.types.generated_poc.task_status import TaskStatus as GeneratedTaskStatus
|
|
50
52
|
from adcp.utils.operation_id import create_operation_id
|
|
51
53
|
|
|
52
54
|
logger = logging.getLogger(__name__)
|
|
@@ -624,7 +626,6 @@ class ADCPClient:
|
|
|
624
626
|
Returns:
|
|
625
627
|
TaskResult with task-specific typed response data
|
|
626
628
|
"""
|
|
627
|
-
from adcp.types.core import TaskStatus
|
|
628
629
|
from adcp.utils.response_parser import parse_json_or_text
|
|
629
630
|
|
|
630
631
|
# Map task types to their response types (using string literals, not enum)
|
|
@@ -643,8 +644,8 @@ class ADCPClient:
|
|
|
643
644
|
|
|
644
645
|
# Handle completed tasks with result parsing
|
|
645
646
|
|
|
646
|
-
if webhook.status ==
|
|
647
|
-
response_type = response_type_map.get(webhook.task_type)
|
|
647
|
+
if webhook.status == GeneratedTaskStatus.completed and webhook.result is not None:
|
|
648
|
+
response_type = response_type_map.get(webhook.task_type.value)
|
|
648
649
|
if response_type:
|
|
649
650
|
try:
|
|
650
651
|
parsed_result: Any = parse_json_or_text(webhook.result, response_type)
|
|
@@ -664,17 +665,21 @@ class ADCPClient:
|
|
|
664
665
|
# Fall through to untyped result
|
|
665
666
|
|
|
666
667
|
# Handle failed, input-required, or unparseable results
|
|
667
|
-
# Convert webhook status
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
668
|
+
# Convert webhook status to core TaskStatus enum
|
|
669
|
+
# Map generated enum values to core enum values
|
|
670
|
+
status_map = {
|
|
671
|
+
GeneratedTaskStatus.completed: TaskStatus.COMPLETED,
|
|
672
|
+
GeneratedTaskStatus.submitted: TaskStatus.SUBMITTED,
|
|
673
|
+
GeneratedTaskStatus.working: TaskStatus.WORKING,
|
|
674
|
+
GeneratedTaskStatus.failed: TaskStatus.FAILED,
|
|
675
|
+
GeneratedTaskStatus.input_required: TaskStatus.NEEDS_INPUT,
|
|
676
|
+
}
|
|
677
|
+
task_status = status_map.get(webhook.status, TaskStatus.FAILED)
|
|
673
678
|
|
|
674
679
|
return TaskResult[Any](
|
|
675
680
|
status=task_status,
|
|
676
681
|
data=webhook.result,
|
|
677
|
-
success=webhook.status ==
|
|
682
|
+
success=webhook.status == GeneratedTaskStatus.completed,
|
|
678
683
|
error=webhook.error if isinstance(webhook.error, str) else None,
|
|
679
684
|
metadata={
|
|
680
685
|
"task_id": webhook.task_id,
|
|
@@ -732,7 +737,7 @@ class ADCPClient:
|
|
|
732
737
|
type=ActivityType.WEBHOOK_RECEIVED,
|
|
733
738
|
operation_id=webhook.operation_id or "unknown",
|
|
734
739
|
agent_id=self.agent_config.id,
|
|
735
|
-
task_type=webhook.task_type,
|
|
740
|
+
task_type=webhook.task_type.value,
|
|
736
741
|
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
737
742
|
metadata={"payload": payload},
|
|
738
743
|
)
|