traia-iatp 0.1.2__py3-none-any.whl → 0.1.67__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.
- traia_iatp/__init__.py +105 -8
- traia_iatp/cli/main.py +85 -1
- traia_iatp/client/__init__.py +28 -3
- traia_iatp/client/crewai_a2a_tools.py +32 -12
- traia_iatp/client/d402_a2a_client.py +348 -0
- traia_iatp/contracts/__init__.py +11 -0
- traia_iatp/contracts/data/abis/contract-abis-localhost.json +4091 -0
- traia_iatp/contracts/data/abis/contract-abis-sepolia.json +4890 -0
- traia_iatp/contracts/data/addresses/contract-addresses.json +17 -0
- traia_iatp/contracts/data/addresses/contract-proxies.json +12 -0
- traia_iatp/contracts/iatp_contracts_config.py +263 -0
- traia_iatp/contracts/wallet_creator.py +369 -0
- traia_iatp/core/models.py +17 -3
- traia_iatp/d402/MIDDLEWARE_ARCHITECTURE.md +205 -0
- traia_iatp/d402/PRICE_BUILDER_USAGE.md +249 -0
- traia_iatp/d402/README.md +489 -0
- traia_iatp/d402/__init__.py +54 -0
- traia_iatp/d402/asgi_wrapper.py +469 -0
- traia_iatp/d402/chains.py +102 -0
- traia_iatp/d402/client.py +150 -0
- traia_iatp/d402/clients/__init__.py +7 -0
- traia_iatp/d402/clients/base.py +218 -0
- traia_iatp/d402/clients/httpx.py +266 -0
- traia_iatp/d402/common.py +114 -0
- traia_iatp/d402/encoding.py +28 -0
- traia_iatp/d402/examples/client_example.py +197 -0
- traia_iatp/d402/examples/server_example.py +171 -0
- traia_iatp/d402/facilitator.py +481 -0
- traia_iatp/d402/mcp_middleware.py +296 -0
- traia_iatp/d402/models.py +116 -0
- traia_iatp/d402/networks.py +98 -0
- traia_iatp/d402/path.py +43 -0
- traia_iatp/d402/payment_introspection.py +126 -0
- traia_iatp/d402/payment_signing.py +183 -0
- traia_iatp/d402/price_builder.py +164 -0
- traia_iatp/d402/servers/__init__.py +61 -0
- traia_iatp/d402/servers/base.py +139 -0
- traia_iatp/d402/servers/example_general_server.py +140 -0
- traia_iatp/d402/servers/fastapi.py +253 -0
- traia_iatp/d402/servers/mcp.py +304 -0
- traia_iatp/d402/servers/starlette.py +878 -0
- traia_iatp/d402/starlette_middleware.py +529 -0
- traia_iatp/d402/types.py +300 -0
- traia_iatp/mcp/D402_MCP_ADAPTER_FLOW.md +357 -0
- traia_iatp/mcp/__init__.py +3 -0
- traia_iatp/mcp/d402_mcp_tool_adapter.py +526 -0
- traia_iatp/mcp/mcp_agent_template.py +78 -13
- traia_iatp/mcp/templates/Dockerfile.j2 +27 -4
- traia_iatp/mcp/templates/README.md.j2 +104 -8
- traia_iatp/mcp/templates/cursor-rules.md.j2 +194 -0
- traia_iatp/mcp/templates/deployment_params.json.j2 +1 -2
- traia_iatp/mcp/templates/docker-compose.yml.j2 +13 -3
- traia_iatp/mcp/templates/env.example.j2 +60 -0
- traia_iatp/mcp/templates/mcp_health_check.py.j2 +2 -2
- traia_iatp/mcp/templates/pyproject.toml.j2 +11 -5
- traia_iatp/mcp/templates/pyrightconfig.json.j2 +22 -0
- traia_iatp/mcp/templates/run_local_docker.sh.j2 +320 -10
- traia_iatp/mcp/templates/server.py.j2 +174 -197
- traia_iatp/mcp/traia_mcp_adapter.py +182 -20
- traia_iatp/registry/__init__.py +47 -12
- traia_iatp/registry/atlas_search_indexes.json +108 -54
- traia_iatp/registry/iatp_search_api.py +169 -39
- traia_iatp/registry/mongodb_registry.py +241 -69
- traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +1 -1
- traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +8 -8
- traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +1 -1
- traia_iatp/registry/readmes/README.md +3 -3
- traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +6 -6
- traia_iatp/scripts/__init__.py +2 -0
- traia_iatp/scripts/create_wallet.py +244 -0
- traia_iatp/server/a2a_server.py +22 -7
- traia_iatp/server/iatp_server_template_generator.py +23 -0
- traia_iatp/server/templates/.dockerignore.j2 +48 -0
- traia_iatp/server/templates/Dockerfile.j2 +23 -1
- traia_iatp/server/templates/README.md +2 -2
- traia_iatp/server/templates/README.md.j2 +5 -5
- traia_iatp/server/templates/__main__.py.j2 +374 -66
- traia_iatp/server/templates/agent.py.j2 +12 -11
- traia_iatp/server/templates/agent_config.json.j2 +3 -3
- traia_iatp/server/templates/agent_executor.py.j2 +45 -27
- traia_iatp/server/templates/env.example.j2 +32 -4
- traia_iatp/server/templates/gitignore.j2 +7 -0
- traia_iatp/server/templates/pyproject.toml.j2 +13 -12
- traia_iatp/server/templates/run_local_docker.sh.j2 +143 -11
- traia_iatp/server/templates/server.py.j2 +197 -10
- traia_iatp/special_agencies/registry_search_agency.py +1 -1
- traia_iatp/utils/iatp_utils.py +6 -6
- traia_iatp-0.1.67.dist-info/METADATA +320 -0
- traia_iatp-0.1.67.dist-info/RECORD +117 -0
- traia_iatp-0.1.2.dist-info/METADATA +0 -414
- traia_iatp-0.1.2.dist-info/RECORD +0 -72
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/WHEEL +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/entry_points.txt +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/licenses/LICENSE +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/top_level.txt +0 -0
traia_iatp/__init__.py
CHANGED
|
@@ -1,13 +1,76 @@
|
|
|
1
|
-
"""Traia IATP - Inter Agent Transfer Protocol package."""
|
|
1
|
+
"""Traia IATP - Inter Agent Transfer Protocol package with lazy loading for performance."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from .server.iatp_server_agent_generator import IATPServerAgentGenerator
|
|
5
|
-
from .registry.mongodb_registry import UtilityAgentRegistry, MCPServerRegistry
|
|
6
|
-
from .registry.iatp_search_api import find_utility_agent
|
|
7
|
-
from .client.a2a_client import UtilityAgencyTool, create_utility_agency_tools
|
|
8
|
-
from .utils.docker_utils import LocalDockerRunner, run_generated_agent_locally, use_run_local_docker_script
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
# Read version dynamically from pyproject.toml to avoid version mismatches
|
|
6
|
+
def _get_version():
|
|
7
|
+
"""Read version from pyproject.toml."""
|
|
8
|
+
try:
|
|
9
|
+
import tomli
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml"
|
|
12
|
+
with open(pyproject_path, "rb") as f:
|
|
13
|
+
pyproject = tomli.load(f)
|
|
14
|
+
return pyproject["project"]["version"]
|
|
15
|
+
except Exception:
|
|
16
|
+
# Fallback for installed packages where pyproject.toml isn't available
|
|
17
|
+
return "0.1.47"
|
|
18
|
+
|
|
19
|
+
__version__ = _get_version()
|
|
20
|
+
|
|
21
|
+
# Type hints for IDEs and type checkers (not loaded at runtime)
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from .core.models import UtilityAgent, MCPServer, AgentCard
|
|
24
|
+
from .server.iatp_server_agent_generator import IATPServerAgentGenerator
|
|
25
|
+
from .registry.mongodb_registry import UtilityAgentRegistry, MCPServerRegistry
|
|
26
|
+
from .registry.iatp_search_api import find_utility_agent
|
|
27
|
+
from .client.a2a_client import UtilityAgencyTool, create_utility_agency_tools
|
|
28
|
+
from .utils.docker_utils import LocalDockerRunner, run_generated_agent_locally, use_run_local_docker_script
|
|
29
|
+
from .d402 import (
|
|
30
|
+
D402Config,
|
|
31
|
+
D402PaymentInfo,
|
|
32
|
+
D402ServicePrice,
|
|
33
|
+
PaymentScheme,
|
|
34
|
+
D402IATPClient,
|
|
35
|
+
IATPSettlementFacilitator,
|
|
36
|
+
require_payment,
|
|
37
|
+
)
|
|
38
|
+
from .client.d402_a2a_client import D402A2AClient, create_d402_a2a_client
|
|
39
|
+
|
|
40
|
+
# Lazy imports - these will only load when accessed
|
|
41
|
+
_LAZY_IMPORTS = {
|
|
42
|
+
# Core models (lightweight)
|
|
43
|
+
"UtilityAgent": ".core.models",
|
|
44
|
+
"MCPServer": ".core.models",
|
|
45
|
+
"AgentCard": ".core.models",
|
|
46
|
+
# Server components
|
|
47
|
+
"IATPServerAgentGenerator": ".server.iatp_server_agent_generator",
|
|
48
|
+
# Registry (lightweight, no CrewAI dependency)
|
|
49
|
+
"UtilityAgentRegistry": ".registry.mongodb_registry",
|
|
50
|
+
"MCPServerRegistry": ".registry.mongodb_registry",
|
|
51
|
+
"find_utility_agent": ".registry.iatp_search_api",
|
|
52
|
+
# Client (HEAVY - imports CrewAI)
|
|
53
|
+
"UtilityAgencyTool": ".client.a2a_client",
|
|
54
|
+
"create_utility_agency_tools": ".client.a2a_client",
|
|
55
|
+
# Docker utilities
|
|
56
|
+
"LocalDockerRunner": ".utils.docker_utils",
|
|
57
|
+
"run_generated_agent_locally": ".utils.docker_utils",
|
|
58
|
+
"use_run_local_docker_script": ".utils.docker_utils",
|
|
59
|
+
# D402 payment integration (HEAVY - imports CrewAI indirectly)
|
|
60
|
+
"D402A2AClient": ".client.d402_a2a_client",
|
|
61
|
+
"create_d402_a2a_client": ".client.d402_a2a_client",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# D402 imports need special handling as they come from a submodule
|
|
65
|
+
_D402_IMPORTS = [
|
|
66
|
+
"D402Config",
|
|
67
|
+
"D402PaymentInfo",
|
|
68
|
+
"D402ServicePrice",
|
|
69
|
+
"PaymentScheme",
|
|
70
|
+
"D402IATPClient",
|
|
71
|
+
"IATPSettlementFacilitator",
|
|
72
|
+
"require_payment",
|
|
73
|
+
]
|
|
11
74
|
|
|
12
75
|
__all__ = [
|
|
13
76
|
# Core models
|
|
@@ -27,4 +90,38 @@ __all__ = [
|
|
|
27
90
|
"LocalDockerRunner",
|
|
28
91
|
"run_generated_agent_locally",
|
|
29
92
|
"use_run_local_docker_script",
|
|
93
|
+
# D402 payment integration
|
|
94
|
+
"D402Config",
|
|
95
|
+
"D402PaymentInfo",
|
|
96
|
+
"D402ServicePrice",
|
|
97
|
+
"PaymentScheme",
|
|
98
|
+
"D402IATPClient",
|
|
99
|
+
"IATPSettlementFacilitator",
|
|
100
|
+
"require_payment",
|
|
101
|
+
"D402A2AClient",
|
|
102
|
+
"create_d402_a2a_client",
|
|
30
103
|
]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def __getattr__(name: str):
|
|
107
|
+
"""Lazy import mechanism to load modules only when accessed."""
|
|
108
|
+
# Handle regular lazy imports
|
|
109
|
+
if name in _LAZY_IMPORTS:
|
|
110
|
+
from importlib import import_module
|
|
111
|
+
module_path = _LAZY_IMPORTS[name]
|
|
112
|
+
module = import_module(module_path, package=__package__)
|
|
113
|
+
attr = getattr(module, name)
|
|
114
|
+
# Cache the imported attribute
|
|
115
|
+
globals()[name] = attr
|
|
116
|
+
return attr
|
|
117
|
+
|
|
118
|
+
# Handle D402 imports
|
|
119
|
+
if name in _D402_IMPORTS:
|
|
120
|
+
from importlib import import_module
|
|
121
|
+
d402_module = import_module(".d402", package=__package__)
|
|
122
|
+
attr = getattr(d402_module, name)
|
|
123
|
+
# Cache the imported attribute
|
|
124
|
+
globals()[name] = attr
|
|
125
|
+
return attr
|
|
126
|
+
|
|
127
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
traia_iatp/cli/main.py
CHANGED
|
@@ -16,6 +16,7 @@ from ..registry.mongodb_registry import UtilityAgentRegistry, MCPServerRegistry
|
|
|
16
16
|
from ..utils.docker_utils import use_run_local_docker_script, LocalDockerRunner
|
|
17
17
|
from ..client.a2a_client import create_utility_agency_tools
|
|
18
18
|
from ..mcp.mcp_agent_template import MCPServerConfig
|
|
19
|
+
from ..contracts.wallet_creator import create_iatp_wallet
|
|
19
20
|
|
|
20
21
|
app = typer.Typer(
|
|
21
22
|
name="iatp",
|
|
@@ -24,6 +25,89 @@ app = typer.Typer(
|
|
|
24
25
|
console = Console()
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
@app.command(name="create-iatp-wallet")
|
|
29
|
+
def create_wallet_cli(
|
|
30
|
+
owner_key: str = typer.Option(..., "--owner-key", help="Owner's private key (REQUIRED INPUT)"),
|
|
31
|
+
operator_address: Optional[str] = typer.Option(None, "--operator-address", help="Operator address (or use --create-operator)"),
|
|
32
|
+
create_operator: bool = typer.Option(False, "--create-operator", help="Generate new operator keypair"),
|
|
33
|
+
wallet_name: str = typer.Option("", "--wallet-name", help="Name for the wallet"),
|
|
34
|
+
wallet_type: str = typer.Option("MCP_SERVER", "--wallet-type", help="Type: CLIENT, HUMAN, MCP_SERVER, WEB_SERVER, AGENT"),
|
|
35
|
+
wallet_description: str = typer.Option("", "--wallet-description", help="Description of the wallet/service"),
|
|
36
|
+
network: str = typer.Option("sepolia", "--network", help="Network (sepolia, base-mainnet)"),
|
|
37
|
+
rpc_url: Optional[str] = typer.Option(None, "--rpc-url", help="Custom RPC URL"),
|
|
38
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Save wallet info to JSON file")
|
|
39
|
+
):
|
|
40
|
+
"""Create a new IATPWallet contract.
|
|
41
|
+
|
|
42
|
+
The owner creates the wallet themselves (no maintainer key needed).
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
|
|
46
|
+
# Create wallet and generate operator (recommended)
|
|
47
|
+
traia-iatp create-iatp-wallet --owner-key 0x... --create-operator --wallet-name "My Server"
|
|
48
|
+
|
|
49
|
+
# Create wallet with existing operator
|
|
50
|
+
traia-iatp create-iatp-wallet --owner-key 0x... --operator-address 0x... --wallet-type AGENT
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
console.print("\n🔧 Creating IATPWallet...\n", style="bold")
|
|
54
|
+
|
|
55
|
+
result = create_iatp_wallet(
|
|
56
|
+
owner_private_key=owner_key,
|
|
57
|
+
operator_address=operator_address,
|
|
58
|
+
create_operator=create_operator,
|
|
59
|
+
wallet_name=wallet_name,
|
|
60
|
+
wallet_type=wallet_type,
|
|
61
|
+
wallet_description=wallet_description,
|
|
62
|
+
network=network,
|
|
63
|
+
rpc_url=rpc_url,
|
|
64
|
+
maintainer_private_key=None # Regular developers don't have maintainer key
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Display results
|
|
68
|
+
console.print("\n" + "="*80, style="green")
|
|
69
|
+
console.print("✅ IATPWallet Created Successfully!", style="bold green")
|
|
70
|
+
console.print("="*80 + "\n", style="green")
|
|
71
|
+
|
|
72
|
+
# Create table for results
|
|
73
|
+
table = Table(title="Wallet Information", show_header=False)
|
|
74
|
+
table.add_column("Field", style="cyan")
|
|
75
|
+
table.add_column("Value", style="white")
|
|
76
|
+
|
|
77
|
+
table.add_row("Wallet Address", result['wallet_address'])
|
|
78
|
+
table.add_row("Owner", result['owner_address'])
|
|
79
|
+
table.add_row("Operator", result['operator_address'])
|
|
80
|
+
table.add_row("Network", result['network'])
|
|
81
|
+
table.add_row("Transaction", result['transaction_hash'])
|
|
82
|
+
|
|
83
|
+
if 'operator_private_key' in result:
|
|
84
|
+
table.add_row("Operator Private Key", result['operator_private_key'])
|
|
85
|
+
|
|
86
|
+
console.print(table)
|
|
87
|
+
|
|
88
|
+
# Save to file if requested
|
|
89
|
+
if output:
|
|
90
|
+
with open(output, 'w') as f:
|
|
91
|
+
json.dump(result, f, indent=2)
|
|
92
|
+
console.print(f"\n💾 Wallet info saved to: {output}", style="green")
|
|
93
|
+
|
|
94
|
+
# Show next steps
|
|
95
|
+
console.print("\n📝 Next Steps:", style="bold")
|
|
96
|
+
console.print("1. Save your credentials securely (especially operator private key)")
|
|
97
|
+
console.print("2. Fund the wallet with USDC for payments")
|
|
98
|
+
console.print("3. Set environment variables:")
|
|
99
|
+
console.print(f" export IATP_WALLET_ADDRESS={result['wallet_address']}")
|
|
100
|
+
if 'operator_private_key' in result:
|
|
101
|
+
console.print(f" export OPERATOR_PRIVATE_KEY={result['operator_private_key']}")
|
|
102
|
+
console.print("4. Start building with IATP!\n")
|
|
103
|
+
|
|
104
|
+
except Exception as e:
|
|
105
|
+
console.print(f"\n❌ Error: {e}", style="bold red")
|
|
106
|
+
import traceback
|
|
107
|
+
console.print(traceback.format_exc(), style="red")
|
|
108
|
+
raise typer.Exit(code=1)
|
|
109
|
+
|
|
110
|
+
|
|
27
111
|
@app.command()
|
|
28
112
|
def create_agency(
|
|
29
113
|
name: str = typer.Option(..., "--name", "-n", help="Name of the utility agency"),
|
|
@@ -438,7 +522,7 @@ def example_crew():
|
|
|
438
522
|
# Example: Using utility agencies in a CrewAI crew
|
|
439
523
|
|
|
440
524
|
from crewai import Agent, Crew, Task
|
|
441
|
-
from
|
|
525
|
+
from traia_iatp import create_utility_agency_tools
|
|
442
526
|
|
|
443
527
|
# Find and create tools from utility agencies
|
|
444
528
|
tools = create_utility_agency_tools(
|
traia_iatp/client/__init__.py
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
|
-
"""IATP client module for A2A integration."""
|
|
1
|
+
"""IATP client module for A2A integration with lazy loading."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
# Type hints for IDEs and type checkers (not loaded at runtime)
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from .a2a_client import UtilityAgencyTool, create_utility_agency_tools
|
|
8
|
+
from .crewai_a2a_tools import A2AToolSchema
|
|
9
|
+
|
|
10
|
+
# Lazy imports to avoid loading CrewAI unless needed
|
|
11
|
+
_LAZY_IMPORTS = {
|
|
12
|
+
"UtilityAgencyTool": ".a2a_client",
|
|
13
|
+
"create_utility_agency_tools": ".a2a_client",
|
|
14
|
+
"A2AToolSchema": ".crewai_a2a_tools",
|
|
15
|
+
}
|
|
5
16
|
|
|
6
17
|
__all__ = [
|
|
7
18
|
"UtilityAgencyTool",
|
|
8
19
|
"create_utility_agency_tools",
|
|
9
20
|
"A2AToolSchema",
|
|
10
21
|
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def __getattr__(name: str):
|
|
25
|
+
"""Lazy import mechanism to load modules only when accessed."""
|
|
26
|
+
if name in _LAZY_IMPORTS:
|
|
27
|
+
from importlib import import_module
|
|
28
|
+
module_path = _LAZY_IMPORTS[name]
|
|
29
|
+
module = import_module(module_path, package=__package__)
|
|
30
|
+
attr = getattr(module, name)
|
|
31
|
+
# Cache the imported attribute
|
|
32
|
+
globals()[name] = attr
|
|
33
|
+
return attr
|
|
34
|
+
|
|
35
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
@@ -8,6 +8,7 @@ from datetime import datetime
|
|
|
8
8
|
import json
|
|
9
9
|
import httpx
|
|
10
10
|
import uuid
|
|
11
|
+
import os
|
|
11
12
|
from contextlib import asynccontextmanager
|
|
12
13
|
import httpcore
|
|
13
14
|
from enum import Enum
|
|
@@ -32,7 +33,7 @@ _thread_local = threading.local()
|
|
|
32
33
|
|
|
33
34
|
class A2AToolSchema(BaseModel):
|
|
34
35
|
"""Input schema for A2A tools."""
|
|
35
|
-
request: str = Field(description="The request or query to send to the A2A agent")
|
|
36
|
+
request: str = Field(description="The request or query to send to the A2A agent. Send only 'request' key when using this tool")
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
class A2AToolConfig(BaseModel):
|
|
@@ -83,8 +84,28 @@ class A2ATool(BaseTool):
|
|
|
83
84
|
logger.info(f"Tool name: {self.name}, Endpoint: {self.config.endpoint}")
|
|
84
85
|
|
|
85
86
|
try:
|
|
86
|
-
#
|
|
87
|
-
|
|
87
|
+
# Check if D402 payment credentials are available from environment
|
|
88
|
+
# Use D402_CLIENT_OPERATOR_PRIVATE_KEY for client-side payments
|
|
89
|
+
payment_private_key = os.getenv("D402_CLIENT_OPERATOR_PRIVATE_KEY") or os.getenv("EVM_PRIVATE_KEY")
|
|
90
|
+
wallet_address = os.getenv("D402_CLIENT_WALLET_ADDRESS")
|
|
91
|
+
|
|
92
|
+
# Create httpx client with D402 payment support if credentials available
|
|
93
|
+
if payment_private_key:
|
|
94
|
+
from eth_account import Account
|
|
95
|
+
from ..d402.clients.httpx import d402HttpxClient
|
|
96
|
+
|
|
97
|
+
operator_key = payment_private_key if payment_private_key.startswith("0x") else f"0x{payment_private_key}"
|
|
98
|
+
operator_account = Account.from_key(operator_key)
|
|
99
|
+
|
|
100
|
+
logger.info(f"Using D402 payment client for A2A tool")
|
|
101
|
+
httpx_client = d402HttpxClient(
|
|
102
|
+
operator_account,
|
|
103
|
+
wallet_address=wallet_address,
|
|
104
|
+
timeout=self.config.timeout
|
|
105
|
+
)
|
|
106
|
+
else:
|
|
107
|
+
logger.info(f"No D402 credentials, using standard httpx client")
|
|
108
|
+
httpx_client = httpx.AsyncClient(
|
|
88
109
|
timeout=httpx.Timeout(
|
|
89
110
|
connect=5.0,
|
|
90
111
|
read=self.config.timeout,
|
|
@@ -92,7 +113,9 @@ class A2ATool(BaseTool):
|
|
|
92
113
|
pool=5.0
|
|
93
114
|
),
|
|
94
115
|
http2=True
|
|
95
|
-
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
async with httpx_client:
|
|
96
119
|
|
|
97
120
|
# Resolve agent card
|
|
98
121
|
card_resolver = A2ACardResolver(
|
|
@@ -101,20 +124,17 @@ class A2ATool(BaseTool):
|
|
|
101
124
|
)
|
|
102
125
|
agent_card = await card_resolver.get_agent_card()
|
|
103
126
|
logger.info(f"Resolved agent card for: {agent_card.name}")
|
|
127
|
+
logger.info(f"Agent card URL: {agent_card.url if hasattr(agent_card, 'url') else 'N/A'}")
|
|
104
128
|
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
from a2a.types import AgentCard
|
|
108
|
-
agent_card_dict = agent_card.model_dump()
|
|
109
|
-
agent_card_dict['url'] = self.config.endpoint
|
|
110
|
-
agent_card = AgentCard(**agent_card_dict)
|
|
129
|
+
# Use the URL from agent card (don't override it)
|
|
130
|
+
# The agent card knows the correct A2A endpoint
|
|
111
131
|
|
|
112
132
|
# Create A2A client
|
|
113
|
-
iatp_endpoint = self.config.iatp_endpoint or
|
|
133
|
+
iatp_endpoint = self.config.iatp_endpoint or agent_card.url
|
|
114
134
|
a2a_client = A2AClient(
|
|
115
135
|
httpx_client=httpx_client,
|
|
116
136
|
agent_card=agent_card,
|
|
117
|
-
url=
|
|
137
|
+
url=agent_card.url # Use agent card's URL (includes /a2a for utility agents)
|
|
118
138
|
)
|
|
119
139
|
|
|
120
140
|
# Create message
|