stls-a2a 0.1.6__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.
- stls_a2a/__init__.py +53 -0
- stls_a2a/stls_a2a_adapters.py +143 -0
- stls_a2a/stls_a2a_adapters_model.py +759 -0
- stls_a2a/stls_a2a_agent_registry.py +425 -0
- stls_a2a/stls_a2a_card_model.py +151 -0
- stls_a2a/stls_a2a_client.py +263 -0
- stls_a2a/stls_a2a_custom_adapter.py +128 -0
- stls_a2a/stls_a2a_google_adapter.py +773 -0
- stls_a2a/stls_a2a_integration.py +2188 -0
- stls_a2a/stls_a2a_lc_adapter.py +498 -0
- stls_a2a/stls_a2a_remote.py +231 -0
- stls_a2a/stls_a2a_secure_remote.py +798 -0
- stls_a2a/stls_a2a_sk_adapter.py +475 -0
- stls_a2a/stls_a2a_task.py +956 -0
- stls_a2a/stls_a2a_transport.py +275 -0
- stls_a2a/stls_a2a_utils.py +434 -0
- stls_a2a-0.1.6.dist-info/METADATA +934 -0
- stls_a2a-0.1.6.dist-info/RECORD +22 -0
- stls_a2a-0.1.6.dist-info/WHEEL +5 -0
- stls_a2a-0.1.6.dist-info/licenses/LICENSE +661 -0
- stls_a2a-0.1.6.dist-info/licenses/LICENSE-COMMERCIAL.md +16 -0
- stls_a2a-0.1.6.dist-info/top_level.txt +1 -0
stls_a2a/__init__.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from .stls_a2a_transport import SecureA2ATransport, A2AMessage
|
|
2
|
+
from .stls_a2a_adapters_model import AgentResponse
|
|
3
|
+
from .stls_a2a_integration import (
|
|
4
|
+
SecureA2ATransportAdapter,
|
|
5
|
+
create_secure_a2a_endpoint,
|
|
6
|
+
create_pqc_a2a_transport,
|
|
7
|
+
AuthConfig)
|
|
8
|
+
|
|
9
|
+
# Providers — now live in stls_core (shared with stls-mcp).
|
|
10
|
+
# Only "base" and "arqit_py" are supported (JVM/simple removed).
|
|
11
|
+
from stls_core import (
|
|
12
|
+
KeyProviderFactory,
|
|
13
|
+
KeyProvider,
|
|
14
|
+
KeyProviderClient,
|
|
15
|
+
KeyProviderServer,
|
|
16
|
+
KeySessionProvider,
|
|
17
|
+
KeySessionProviderFactory,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .stls_a2a_card_model import AgentCard
|
|
21
|
+
from .stls_a2a_utils import (
|
|
22
|
+
to_a2a,
|
|
23
|
+
start_task_store_cleanup,
|
|
24
|
+
extract_a2a_text,
|
|
25
|
+
extract_a2a_result,
|
|
26
|
+
extract_a2a_artifacts)
|
|
27
|
+
from .stls_a2a_client import A2AClient
|
|
28
|
+
|
|
29
|
+
# Auth — now lives in stls_core (shared with stls-mcp).
|
|
30
|
+
from stls_core import (
|
|
31
|
+
ApiKeyManager,
|
|
32
|
+
ApiKeyManagerGroup,
|
|
33
|
+
default_audit_hook,
|
|
34
|
+
AuditEntry,
|
|
35
|
+
generate_api_key,
|
|
36
|
+
hash_key,
|
|
37
|
+
RedisKeyCache,
|
|
38
|
+
)
|
|
39
|
+
from stls_core.auth.stls_core_auth_loaders import (
|
|
40
|
+
ApiKeyLoader,
|
|
41
|
+
StaticLoader,
|
|
42
|
+
FileLoader,
|
|
43
|
+
PostgresLoader,
|
|
44
|
+
create_loader,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
from .stls_a2a_agent_registry import AgentRegistry, make_agent_id
|
|
48
|
+
from .stls_a2a_remote import ContextualRemoteA2aAgent
|
|
49
|
+
from .stls_a2a_secure_remote import (
|
|
50
|
+
SecureSessionManager,
|
|
51
|
+
STLSHttpxTransport,
|
|
52
|
+
ContextualSecureRemoteA2aAgent,
|
|
53
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent Adapters for A2A Secure Transport
|
|
3
|
+
========================================
|
|
4
|
+
|
|
5
|
+
Common interface and adapters for different AI/Agent frameworks,
|
|
6
|
+
enabling secure A2A communication independent of the framework.
|
|
7
|
+
|
|
8
|
+
Supported frameworks:
|
|
9
|
+
- Google ADK
|
|
10
|
+
- LangChain
|
|
11
|
+
- Semantic Kernel
|
|
12
|
+
- Custom agents
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Dict, Any, Optional
|
|
17
|
+
|
|
18
|
+
from .stls_a2a_adapters_model import AgentAdapter,AgentRequest,AgentResponse
|
|
19
|
+
|
|
20
|
+
from .stls_a2a_google_adapter import GoogleADKAdapter
|
|
21
|
+
from .stls_a2a_lc_adapter import LangChainAdapter
|
|
22
|
+
from .stls_a2a_sk_adapter import SemanticKernelAdapter
|
|
23
|
+
from .stls_a2a_custom_adapter import CustomFunctionAdapter
|
|
24
|
+
|
|
25
|
+
import logging
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ============================================================================
|
|
30
|
+
# FACTORY TO CREATE ADAPTERS
|
|
31
|
+
# ============================================================================
|
|
32
|
+
|
|
33
|
+
def create_adapter(
|
|
34
|
+
agent,
|
|
35
|
+
framework: str = 'auto',
|
|
36
|
+
**kwargs
|
|
37
|
+
) -> AgentAdapter:
|
|
38
|
+
"""
|
|
39
|
+
Factory to create the appropriate adapter
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
agent: Agent instance
|
|
43
|
+
framework: 'google-adk', 'langchain', 'semantic-kernel', 'custom', or 'auto'
|
|
44
|
+
**kwargs: Additional parameters for the adapter
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
The appropriate AgentAdapter
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
if framework == 'auto':
|
|
51
|
+
# Framework auto-detection
|
|
52
|
+
agent_class = agent.__class__.__name__
|
|
53
|
+
module = agent.__class__.__module__
|
|
54
|
+
|
|
55
|
+
if 'google.adk' in module or 'genai.adk' in module:
|
|
56
|
+
framework = 'google-adk'
|
|
57
|
+
elif 'langchain' in module:
|
|
58
|
+
framework = 'langchain'
|
|
59
|
+
elif 'semantic_kernel' in module:
|
|
60
|
+
framework = 'semantic-kernel'
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Cannot auto-detect framework for {agent_class}. "
|
|
64
|
+
"Please specify framework explicitly."
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Create the appropriate adapter
|
|
68
|
+
if framework == 'google-adk':
|
|
69
|
+
return GoogleADKAdapter(agent, **kwargs)
|
|
70
|
+
elif framework == 'langchain':
|
|
71
|
+
return LangChainAdapter(agent, **kwargs)
|
|
72
|
+
elif framework == 'semantic-kernel':
|
|
73
|
+
return SemanticKernelAdapter(agent, **kwargs)
|
|
74
|
+
elif framework == 'custom':
|
|
75
|
+
return CustomFunctionAdapter(agent, **kwargs)
|
|
76
|
+
else:
|
|
77
|
+
raise ValueError(f"Unknown framework: {framework}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ============================================================================
|
|
81
|
+
# UTILITIES FOR A2A <-> AgentRequest/Response CONVERSION
|
|
82
|
+
# ============================================================================
|
|
83
|
+
|
|
84
|
+
def a2a_to_agent_request(a2a_message: Dict[str, Any]) -> AgentRequest:
|
|
85
|
+
"""
|
|
86
|
+
Converts an A2A (JSON-RPC) message into an AgentRequest
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
a2a_message: A2A JSON-RPC message
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Standardized AgentRequest
|
|
93
|
+
"""
|
|
94
|
+
return AgentRequest(
|
|
95
|
+
method=a2a_message.get('method', 'invoke'),
|
|
96
|
+
params=a2a_message.get('params', {}),
|
|
97
|
+
id=a2a_message.get('id'),
|
|
98
|
+
context=a2a_message.get('context')
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def agent_response_to_a2a(response: Optional[AgentResponse]) -> Dict[str, Any]:
|
|
103
|
+
"""
|
|
104
|
+
Converts an AgentResponse into an A2A (JSON-RPC) message.
|
|
105
|
+
|
|
106
|
+
Handles the response=None case (adapter that doesn't explicitly return
|
|
107
|
+
for unsupported methods) by returning a -32603 error instead of
|
|
108
|
+
raising an AttributeError.
|
|
109
|
+
"""
|
|
110
|
+
if response is None:
|
|
111
|
+
logger.error(
|
|
112
|
+
"agent_response_to_a2a: received None — adapter invoke() returned no value. "
|
|
113
|
+
"Check that all code paths in the adapter return an AgentResponse."
|
|
114
|
+
)
|
|
115
|
+
return {
|
|
116
|
+
'jsonrpc': '2.0',
|
|
117
|
+
'error': {
|
|
118
|
+
'code': -32603,
|
|
119
|
+
'message': 'Internal error: adapter returned no response. '
|
|
120
|
+
'Possible missing else-branch for unsupported method.',
|
|
121
|
+
},
|
|
122
|
+
'id': None,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
a2a_response: Dict[str, Any] = {
|
|
126
|
+
'jsonrpc': '2.0',
|
|
127
|
+
'id': response.id,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if response.error:
|
|
131
|
+
a2a_response['error'] = response.error
|
|
132
|
+
else:
|
|
133
|
+
# The result is passed as-is: normalization into A2A format
|
|
134
|
+
# (parts[]) already happens in CustomFunctionAdapter.invoke() for custom
|
|
135
|
+
# agents, and in _handle_messages_send() for all the others.
|
|
136
|
+
# DO NOT normalize here: Task dicts (tasks/get, tasks/cancel, messages/send)
|
|
137
|
+
# don't have "parts" by design and must not be transformed.
|
|
138
|
+
a2a_response['result'] = response.result
|
|
139
|
+
|
|
140
|
+
if response.metadata:
|
|
141
|
+
a2a_response['metadata'] = response.metadata
|
|
142
|
+
|
|
143
|
+
return a2a_response
|