agentscope-runtime 1.0.4__py3-none-any.whl → 1.0.4a1__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.
- agentscope_runtime/adapters/agentscope/stream.py +7 -1
- agentscope_runtime/cli/commands/deploy.py +0 -371
- agentscope_runtime/engine/__init__.py +0 -4
- agentscope_runtime/engine/constant.py +0 -1
- agentscope_runtime/engine/deployers/__init__.py +0 -12
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +51 -26
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +10 -19
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +201 -4
- agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +25 -134
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
- agentscope_runtime/engine/runner.py +0 -12
- agentscope_runtime/engine/tracing/wrapper.py +4 -18
- agentscope_runtime/sandbox/__init__.py +6 -14
- agentscope_runtime/sandbox/box/base/__init__.py +2 -2
- agentscope_runtime/sandbox/box/base/base_sandbox.py +1 -51
- agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +2 -198
- agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +2 -99
- agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +1 -117
- agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +100 -247
- agentscope_runtime/sandbox/box/sandbox.py +65 -98
- agentscope_runtime/sandbox/box/shared/routers/generic.py +29 -36
- agentscope_runtime/sandbox/client/__init__.py +1 -6
- agentscope_runtime/sandbox/client/http_client.py +329 -108
- agentscope_runtime/sandbox/enums.py +0 -7
- agentscope_runtime/sandbox/manager/sandbox_manager.py +4 -264
- agentscope_runtime/sandbox/manager/server/app.py +1 -7
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/METADATA +28 -102
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/RECORD +37 -46
- agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
- agentscope_runtime/adapters/ms_agent_framework/message.py +0 -205
- agentscope_runtime/adapters/ms_agent_framework/stream.py +0 -418
- agentscope_runtime/adapters/utils.py +0 -6
- agentscope_runtime/common/container_clients/knative_client.py +0 -466
- agentscope_runtime/engine/deployers/fc_deployer.py +0 -1506
- agentscope_runtime/engine/deployers/knative_deployer.py +0 -290
- agentscope_runtime/sandbox/client/async_http_client.py +0 -339
- agentscope_runtime/sandbox/client/base.py +0 -74
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/WHEEL +0 -0
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/top_level.txt +0 -0
|
@@ -2,20 +2,35 @@
|
|
|
2
2
|
"""
|
|
3
3
|
A2A Registry Extension Point
|
|
4
4
|
|
|
5
|
-
Defines the abstract interface for A2A registry
|
|
6
|
-
Registry implementations are responsible for registering
|
|
7
|
-
to service discovery systems (for example: Nacos).
|
|
5
|
+
Defines the abstract interface and helper utilities for A2A registry
|
|
6
|
+
implementations. Registry implementations are responsible for registering
|
|
7
|
+
agent services to service discovery systems (for example: Nacos).
|
|
8
|
+
|
|
9
|
+
This module focuses on clarity and small helper functions used by the
|
|
10
|
+
runtime to instantiate registry implementations from environment
|
|
11
|
+
configuration or .env files.
|
|
8
12
|
"""
|
|
9
13
|
import logging
|
|
14
|
+
import os
|
|
10
15
|
from abc import ABC, abstractmethod
|
|
11
16
|
from dataclasses import dataclass, field
|
|
12
|
-
from typing import Any, Dict, List, Optional
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
18
|
+
|
|
19
|
+
from dotenv import find_dotenv, load_dotenv
|
|
20
|
+
from pydantic import ConfigDict
|
|
21
|
+
from pydantic_settings import BaseSettings
|
|
13
22
|
|
|
14
23
|
from a2a.types import AgentCard
|
|
15
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from v2.nacos import ClientConfig
|
|
27
|
+
|
|
16
28
|
__all__ = [
|
|
17
29
|
"A2ARegistry",
|
|
18
30
|
"A2ATransportsProperties",
|
|
31
|
+
"A2ARegistrySettings",
|
|
32
|
+
"get_registry_settings",
|
|
33
|
+
"create_registry_from_env",
|
|
19
34
|
]
|
|
20
35
|
|
|
21
36
|
logger = logging.getLogger(__name__)
|
|
@@ -74,3 +89,185 @@ class A2ARegistry(ABC):
|
|
|
74
89
|
depending on their semantics.
|
|
75
90
|
"""
|
|
76
91
|
raise NotImplementedError("Subclasses must implement register()")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class A2ARegistrySettings(BaseSettings):
|
|
95
|
+
"""Settings that control A2A registry behavior.
|
|
96
|
+
|
|
97
|
+
Values are loaded from environment variables or a .env file when
|
|
98
|
+
`get_registry_settings()` is called.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
# Feature toggle
|
|
102
|
+
A2A_REGISTRY_ENABLED: bool = True
|
|
103
|
+
|
|
104
|
+
# Registry type(s). Can be a single value like "nacos" or a comma-separated
|
|
105
|
+
# list of registry types (e.g. "nacos").
|
|
106
|
+
A2A_REGISTRY_TYPE: Optional[str] = None
|
|
107
|
+
|
|
108
|
+
# Nacos specific configuration
|
|
109
|
+
NACOS_SERVER_ADDR: str = "localhost:8848"
|
|
110
|
+
NACOS_USERNAME: Optional[str] = None
|
|
111
|
+
NACOS_PASSWORD: Optional[str] = None
|
|
112
|
+
NACOS_NAMESPACE_ID: Optional[str] = None
|
|
113
|
+
NACOS_ACCESS_KEY: Optional[str] = None
|
|
114
|
+
NACOS_SECRET_KEY: Optional[str] = None
|
|
115
|
+
|
|
116
|
+
model_config = ConfigDict(
|
|
117
|
+
extra="allow",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
_registry_settings: Optional[A2ARegistrySettings] = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_registry_settings() -> A2ARegistrySettings:
|
|
125
|
+
"""Return a singleton settings instance, loading .env files if needed."""
|
|
126
|
+
global _registry_settings
|
|
127
|
+
|
|
128
|
+
if _registry_settings is None:
|
|
129
|
+
# Inline _load_env_files() logic
|
|
130
|
+
# prefer a .env file if present, otherwise fall back to .env.example
|
|
131
|
+
dotenv_path = find_dotenv(raise_error_if_not_found=False)
|
|
132
|
+
if dotenv_path:
|
|
133
|
+
load_dotenv(dotenv_path, override=False)
|
|
134
|
+
else:
|
|
135
|
+
# If find_dotenv didn't find a file, try the explicit fallback name
|
|
136
|
+
if os.path.exists(".env.example"):
|
|
137
|
+
load_dotenv(".env.example", override=False)
|
|
138
|
+
_registry_settings = A2ARegistrySettings()
|
|
139
|
+
|
|
140
|
+
return _registry_settings
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _create_nacos_registry_from_settings(
|
|
144
|
+
settings: A2ARegistrySettings,
|
|
145
|
+
) -> Optional[A2ARegistry]:
|
|
146
|
+
"""Create a NacosRegistry instance from provided settings, or return
|
|
147
|
+
None if the required nacos SDK is not available or construction fails."""
|
|
148
|
+
try:
|
|
149
|
+
# lazy import so package is optional
|
|
150
|
+
from .nacos_a2a_registry import NacosRegistry
|
|
151
|
+
except ImportError:
|
|
152
|
+
logger.warning(
|
|
153
|
+
"[A2A] Nacos registry requested but nacos SDK not available. "
|
|
154
|
+
"Install with: pip install v2-nacos",
|
|
155
|
+
exc_info=False,
|
|
156
|
+
)
|
|
157
|
+
return None
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.warning(
|
|
160
|
+
"[A2A] Unexpected error during Nacos registry import: %s",
|
|
161
|
+
str(e),
|
|
162
|
+
exc_info=True,
|
|
163
|
+
)
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
nacos_client_config = _build_nacos_client_config(settings)
|
|
168
|
+
registry = NacosRegistry(nacos_client_config=nacos_client_config)
|
|
169
|
+
|
|
170
|
+
# Determine authentication status
|
|
171
|
+
auth_methods = []
|
|
172
|
+
if settings.NACOS_USERNAME and settings.NACOS_PASSWORD:
|
|
173
|
+
auth_methods.append("username/password")
|
|
174
|
+
if settings.NACOS_ACCESS_KEY and settings.NACOS_SECRET_KEY:
|
|
175
|
+
auth_methods.append("access_key")
|
|
176
|
+
auth_status = ", ".join(auth_methods) if auth_methods else "disabled"
|
|
177
|
+
|
|
178
|
+
namespace_info = (
|
|
179
|
+
f", namespace={settings.NACOS_NAMESPACE_ID}"
|
|
180
|
+
if settings.NACOS_NAMESPACE_ID
|
|
181
|
+
else ""
|
|
182
|
+
)
|
|
183
|
+
logger.info(
|
|
184
|
+
f"[A2A] Created Nacos registry from environment: "
|
|
185
|
+
f"server={settings.NACOS_SERVER_ADDR}, "
|
|
186
|
+
f"authentication={auth_status}{namespace_info}",
|
|
187
|
+
)
|
|
188
|
+
return registry
|
|
189
|
+
except Exception:
|
|
190
|
+
logger.warning(
|
|
191
|
+
"[A2A] Failed to construct Nacos registry from settings",
|
|
192
|
+
exc_info=True,
|
|
193
|
+
)
|
|
194
|
+
return None
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _build_nacos_client_config(
|
|
198
|
+
settings: A2ARegistrySettings,
|
|
199
|
+
) -> Any:
|
|
200
|
+
"""Build Nacos client configuration from settings.
|
|
201
|
+
|
|
202
|
+
Supports both username/password and access key authentication.
|
|
203
|
+
"""
|
|
204
|
+
from v2.nacos import ClientConfigBuilder
|
|
205
|
+
|
|
206
|
+
builder = ClientConfigBuilder().server_address(settings.NACOS_SERVER_ADDR)
|
|
207
|
+
|
|
208
|
+
if settings.NACOS_NAMESPACE_ID:
|
|
209
|
+
builder.namespace_id(settings.NACOS_NAMESPACE_ID)
|
|
210
|
+
logger.debug(
|
|
211
|
+
"[A2A] Using Nacos namespace: %s",
|
|
212
|
+
settings.NACOS_NAMESPACE_ID,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
if settings.NACOS_USERNAME and settings.NACOS_PASSWORD:
|
|
216
|
+
builder.username(settings.NACOS_USERNAME).password(
|
|
217
|
+
settings.NACOS_PASSWORD,
|
|
218
|
+
)
|
|
219
|
+
logger.debug("[A2A] Using Nacos username/password authentication")
|
|
220
|
+
|
|
221
|
+
if settings.NACOS_ACCESS_KEY and settings.NACOS_SECRET_KEY:
|
|
222
|
+
builder.access_key(settings.NACOS_ACCESS_KEY).secret_key(
|
|
223
|
+
settings.NACOS_SECRET_KEY,
|
|
224
|
+
)
|
|
225
|
+
logger.debug("[A2A] Using Nacos access key authentication")
|
|
226
|
+
|
|
227
|
+
return builder.build()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def create_registry_from_env() -> (
|
|
231
|
+
Optional[Union[A2ARegistry, List[A2ARegistry]]]
|
|
232
|
+
):
|
|
233
|
+
"""Create registry instance(s) from environment settings.
|
|
234
|
+
|
|
235
|
+
Supports single or multiple registry types (comma-separated).
|
|
236
|
+
Returns None if disabled or no valid registry created.
|
|
237
|
+
"""
|
|
238
|
+
settings = get_registry_settings()
|
|
239
|
+
|
|
240
|
+
if not settings.A2A_REGISTRY_ENABLED:
|
|
241
|
+
logger.debug("[A2A] Registry disabled via A2A_REGISTRY_ENABLED")
|
|
242
|
+
return None
|
|
243
|
+
|
|
244
|
+
# Inline _split_registry_types() logic
|
|
245
|
+
raw = settings.A2A_REGISTRY_TYPE
|
|
246
|
+
types = (
|
|
247
|
+
[r.strip().lower() for r in raw.split(",") if r.strip()] if raw else []
|
|
248
|
+
)
|
|
249
|
+
if not types:
|
|
250
|
+
logger.debug("[A2A] No registry type specified in A2A_REGISTRY_TYPE")
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
registry_list: List[A2ARegistry] = []
|
|
254
|
+
|
|
255
|
+
for registry_type in types:
|
|
256
|
+
if registry_type == "nacos":
|
|
257
|
+
registry = _create_nacos_registry_from_settings(settings)
|
|
258
|
+
if registry:
|
|
259
|
+
registry_list.append(registry)
|
|
260
|
+
else:
|
|
261
|
+
logger.debug(
|
|
262
|
+
"[A2A] Skipping nacos registry due to earlier errors",
|
|
263
|
+
)
|
|
264
|
+
else:
|
|
265
|
+
logger.warning(
|
|
266
|
+
f"[A2A] Unknown registry type requested: "
|
|
267
|
+
f"{registry_type}. Supported: nacos",
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
if not registry_list:
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
return registry_list[0] if len(registry_list) == 1 else registry_list
|
|
@@ -8,17 +8,11 @@ for A2A protocol adapters.
|
|
|
8
8
|
"""
|
|
9
9
|
import asyncio
|
|
10
10
|
import logging
|
|
11
|
-
import os
|
|
12
|
-
import threading
|
|
13
11
|
from enum import Enum
|
|
14
|
-
from typing import
|
|
12
|
+
from typing import Optional, TYPE_CHECKING, List
|
|
13
|
+
import threading
|
|
15
14
|
|
|
16
15
|
from a2a.types import AgentCard
|
|
17
|
-
from dotenv import find_dotenv, load_dotenv
|
|
18
|
-
from pydantic import ConfigDict
|
|
19
|
-
from pydantic_settings import BaseSettings
|
|
20
|
-
|
|
21
|
-
logger = logging.getLogger(__name__)
|
|
22
16
|
|
|
23
17
|
# Make the v2.nacos imports optional to avoid hard dependency at
|
|
24
18
|
# module import time.
|
|
@@ -42,10 +36,6 @@ else:
|
|
|
42
36
|
|
|
43
37
|
_NACOS_SDK_AVAILABLE = True
|
|
44
38
|
except Exception:
|
|
45
|
-
logger.warning(
|
|
46
|
-
"[NacosRegistry] Nacos SDK (nacos-sdk-python) is not available. "
|
|
47
|
-
"Install it with: pip install nacos-sdk-python",
|
|
48
|
-
)
|
|
49
39
|
|
|
50
40
|
class ClientConfig:
|
|
51
41
|
pass
|
|
@@ -65,129 +55,12 @@ else:
|
|
|
65
55
|
_NACOS_SDK_AVAILABLE = False
|
|
66
56
|
|
|
67
57
|
# Import after conditional imports to avoid circular dependencies
|
|
68
|
-
# flake8: noqa: E402
|
|
69
58
|
from .a2a_registry import ( # pylint: disable=wrong-import-position
|
|
70
59
|
A2ARegistry,
|
|
71
60
|
A2ATransportsProperties,
|
|
72
61
|
)
|
|
73
62
|
|
|
74
|
-
|
|
75
|
-
class NacosSettings(BaseSettings):
|
|
76
|
-
"""Nacos-specific settings loaded from environment variables."""
|
|
77
|
-
|
|
78
|
-
NACOS_SERVER_ADDR: str = "localhost:8848"
|
|
79
|
-
NACOS_USERNAME: Optional[str] = None
|
|
80
|
-
NACOS_PASSWORD: Optional[str] = None
|
|
81
|
-
NACOS_NAMESPACE_ID: Optional[str] = None
|
|
82
|
-
NACOS_ACCESS_KEY: Optional[str] = None
|
|
83
|
-
NACOS_SECRET_KEY: Optional[str] = None
|
|
84
|
-
|
|
85
|
-
model_config = ConfigDict(
|
|
86
|
-
extra="allow",
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
_nacos_settings: Optional[NacosSettings] = None
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def get_nacos_settings() -> NacosSettings:
|
|
94
|
-
"""Return a singleton Nacos settings instance, loading .env files
|
|
95
|
-
if needed."""
|
|
96
|
-
global _nacos_settings
|
|
97
|
-
|
|
98
|
-
if _nacos_settings is None:
|
|
99
|
-
dotenv_path = find_dotenv(raise_error_if_not_found=False)
|
|
100
|
-
if dotenv_path:
|
|
101
|
-
load_dotenv(dotenv_path, override=False)
|
|
102
|
-
else:
|
|
103
|
-
if os.path.exists(".env.example"):
|
|
104
|
-
load_dotenv(".env.example", override=False)
|
|
105
|
-
_nacos_settings = NacosSettings()
|
|
106
|
-
|
|
107
|
-
return _nacos_settings
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def _build_nacos_client_config(settings: NacosSettings) -> Any:
|
|
111
|
-
"""Build Nacos client configuration from settings.
|
|
112
|
-
|
|
113
|
-
Supports both username/password and access key authentication.
|
|
114
|
-
"""
|
|
115
|
-
try:
|
|
116
|
-
from v2.nacos import ClientConfigBuilder
|
|
117
|
-
except (ImportError, ModuleNotFoundError) as e:
|
|
118
|
-
logger.warning(
|
|
119
|
-
"[A2A] Nacos SDK (nacos-sdk-python) is not available. "
|
|
120
|
-
"Install it with: pip install nacos-sdk-python",
|
|
121
|
-
)
|
|
122
|
-
raise ImportError(
|
|
123
|
-
"Nacos SDK (nacos-sdk-python) is not available. "
|
|
124
|
-
"Install it with: pip install nacos-sdk-python",
|
|
125
|
-
) from e
|
|
126
|
-
|
|
127
|
-
builder = ClientConfigBuilder().server_address(settings.NACOS_SERVER_ADDR)
|
|
128
|
-
|
|
129
|
-
if settings.NACOS_NAMESPACE_ID:
|
|
130
|
-
builder.namespace_id(settings.NACOS_NAMESPACE_ID)
|
|
131
|
-
logger.debug(
|
|
132
|
-
"[A2A] Using Nacos namespace: %s",
|
|
133
|
-
settings.NACOS_NAMESPACE_ID,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
if settings.NACOS_USERNAME and settings.NACOS_PASSWORD:
|
|
137
|
-
builder.username(settings.NACOS_USERNAME).password(
|
|
138
|
-
settings.NACOS_PASSWORD,
|
|
139
|
-
)
|
|
140
|
-
logger.debug("[A2A] Using Nacos username/password authentication")
|
|
141
|
-
|
|
142
|
-
if settings.NACOS_ACCESS_KEY and settings.NACOS_SECRET_KEY:
|
|
143
|
-
builder.access_key(settings.NACOS_ACCESS_KEY).secret_key(
|
|
144
|
-
settings.NACOS_SECRET_KEY,
|
|
145
|
-
)
|
|
146
|
-
logger.debug("[A2A] Using Nacos access key authentication")
|
|
147
|
-
|
|
148
|
-
return builder.build()
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def create_nacos_registry_from_env() -> Optional[A2ARegistry]:
|
|
152
|
-
"""Create a NacosRegistry instance from environment settings.
|
|
153
|
-
|
|
154
|
-
Returns None if the required nacos SDK is not available or
|
|
155
|
-
construction fails.
|
|
156
|
-
"""
|
|
157
|
-
if not _NACOS_SDK_AVAILABLE:
|
|
158
|
-
return None
|
|
159
|
-
|
|
160
|
-
try:
|
|
161
|
-
nacos_settings = get_nacos_settings()
|
|
162
|
-
nacos_client_config = _build_nacos_client_config(nacos_settings)
|
|
163
|
-
registry = NacosRegistry(nacos_client_config=nacos_client_config)
|
|
164
|
-
|
|
165
|
-
auth_methods = []
|
|
166
|
-
if nacos_settings.NACOS_USERNAME and nacos_settings.NACOS_PASSWORD:
|
|
167
|
-
auth_methods.append("username/password")
|
|
168
|
-
if nacos_settings.NACOS_ACCESS_KEY and nacos_settings.NACOS_SECRET_KEY:
|
|
169
|
-
auth_methods.append("access_key")
|
|
170
|
-
auth_status = ", ".join(auth_methods) if auth_methods else "disabled"
|
|
171
|
-
|
|
172
|
-
namespace_info = (
|
|
173
|
-
f", namespace={nacos_settings.NACOS_NAMESPACE_ID}"
|
|
174
|
-
if nacos_settings.NACOS_NAMESPACE_ID
|
|
175
|
-
else ""
|
|
176
|
-
)
|
|
177
|
-
logger.info(
|
|
178
|
-
f"[A2A] Created Nacos registry from environment: "
|
|
179
|
-
f"server={nacos_settings.NACOS_SERVER_ADDR}, "
|
|
180
|
-
f"authentication={auth_status}{namespace_info}",
|
|
181
|
-
)
|
|
182
|
-
return registry
|
|
183
|
-
except (ImportError, ModuleNotFoundError):
|
|
184
|
-
return None
|
|
185
|
-
except Exception:
|
|
186
|
-
logger.warning(
|
|
187
|
-
"[A2A] Failed to construct Nacos registry from settings",
|
|
188
|
-
exc_info=True,
|
|
189
|
-
)
|
|
190
|
-
return None
|
|
63
|
+
logger = logging.getLogger(__name__)
|
|
191
64
|
|
|
192
65
|
|
|
193
66
|
class RegistrationStatus(Enum):
|
|
@@ -254,10 +127,11 @@ class NacosRegistry(A2ARegistry):
|
|
|
254
127
|
a2a_transports_properties: List of transport configurations.
|
|
255
128
|
Each transport will be registered separately.
|
|
256
129
|
"""
|
|
130
|
+
# If Nacos SDK is not available, log and return
|
|
257
131
|
if not _NACOS_SDK_AVAILABLE:
|
|
258
|
-
logger.
|
|
259
|
-
"[NacosRegistry] Nacos SDK
|
|
260
|
-
"
|
|
132
|
+
logger.debug(
|
|
133
|
+
"[NacosRegistry] Nacos SDK is not available; "
|
|
134
|
+
"skipping registration",
|
|
261
135
|
)
|
|
262
136
|
return
|
|
263
137
|
|
|
@@ -280,7 +154,11 @@ class NacosRegistry(A2ARegistry):
|
|
|
280
154
|
thread and run the registration using asyncio.run so
|
|
281
155
|
registration still occurs in synchronous contexts.
|
|
282
156
|
"""
|
|
157
|
+
# All status checks and updates must be within the lock to
|
|
158
|
+
# ensure atomicity
|
|
283
159
|
with self._registration_lock:
|
|
160
|
+
# Check if shutdown was already requested (inside lock
|
|
161
|
+
# for atomicity)
|
|
284
162
|
if self._shutdown_event.is_set():
|
|
285
163
|
logger.info(
|
|
286
164
|
"[NacosRegistry] Shutdown already requested, "
|
|
@@ -289,6 +167,7 @@ class NacosRegistry(A2ARegistry):
|
|
|
289
167
|
self._registration_status = RegistrationStatus.CANCELLED
|
|
290
168
|
return
|
|
291
169
|
|
|
170
|
+
# Check if registration is already in progress or completed
|
|
292
171
|
if self._registration_status in (
|
|
293
172
|
RegistrationStatus.IN_PROGRESS,
|
|
294
173
|
RegistrationStatus.COMPLETED,
|
|
@@ -305,6 +184,8 @@ class NacosRegistry(A2ARegistry):
|
|
|
305
184
|
try:
|
|
306
185
|
loop = asyncio.get_running_loop()
|
|
307
186
|
except RuntimeError:
|
|
187
|
+
# No running loop in this thread; we'll fall back to a
|
|
188
|
+
# background thread
|
|
308
189
|
loop = None
|
|
309
190
|
|
|
310
191
|
if loop is not None:
|
|
@@ -322,6 +203,7 @@ class NacosRegistry(A2ARegistry):
|
|
|
322
203
|
)
|
|
323
204
|
return
|
|
324
205
|
|
|
206
|
+
# No running loop: use a background thread to run asyncio.run
|
|
325
207
|
def _thread_runner():
|
|
326
208
|
try:
|
|
327
209
|
with self._registration_lock:
|
|
@@ -375,6 +257,8 @@ class NacosRegistry(A2ARegistry):
|
|
|
375
257
|
daemon=True,
|
|
376
258
|
)
|
|
377
259
|
thread.start()
|
|
260
|
+
# Store thread reference after successful start for
|
|
261
|
+
# proper tracking and cleanup
|
|
378
262
|
with self._registration_lock:
|
|
379
263
|
self._register_thread = thread
|
|
380
264
|
logger.info(
|
|
@@ -398,7 +282,14 @@ class NacosRegistry(A2ARegistry):
|
|
|
398
282
|
if self._nacos_client_config is not None:
|
|
399
283
|
return self._nacos_client_config
|
|
400
284
|
|
|
401
|
-
|
|
285
|
+
# Use centralized config builder from a2a_registry module
|
|
286
|
+
# This ensures consistent behavior with env-based registry creation
|
|
287
|
+
from .a2a_registry import (
|
|
288
|
+
get_registry_settings,
|
|
289
|
+
_build_nacos_client_config,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
settings = get_registry_settings()
|
|
402
293
|
return _build_nacos_client_config(settings)
|
|
403
294
|
|
|
404
295
|
# pylint: disable=too-many-branches,too-many-statements
|
|
@@ -7,7 +7,7 @@ import logging
|
|
|
7
7
|
import os
|
|
8
8
|
import time
|
|
9
9
|
from dataclasses import dataclass
|
|
10
|
-
from datetime import datetime
|
|
10
|
+
from datetime import datetime
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Dict, Optional, List, Any, Union, Tuple
|
|
13
13
|
|
|
@@ -1011,7 +1011,7 @@ ls -lh /output/{zip_filename}
|
|
|
1011
1011
|
try:
|
|
1012
1012
|
presign_result = oss_client.presign(
|
|
1013
1013
|
GetObjectRequest(bucket=bucket_name, key=object_key),
|
|
1014
|
-
expires=timedelta(hours=3),
|
|
1014
|
+
expires=datetime.timedelta(hours=3),
|
|
1015
1015
|
)
|
|
1016
1016
|
presigned_url = presign_result.url
|
|
1017
1017
|
logger.info("Presigned URL generated (valid for 3 hours)")
|
|
@@ -272,18 +272,6 @@ class Runner:
|
|
|
272
272
|
kwargs.update(
|
|
273
273
|
{"msgs": await message_to_agno_message(request.input)},
|
|
274
274
|
)
|
|
275
|
-
elif self.framework_type == "ms_agent_framework":
|
|
276
|
-
from ..adapters.ms_agent_framework.stream import (
|
|
277
|
-
adapt_ms_agent_framework_message_stream,
|
|
278
|
-
)
|
|
279
|
-
from ..adapters.ms_agent_framework.message import (
|
|
280
|
-
message_to_ms_agent_framework_message,
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
stream_adapter = adapt_ms_agent_framework_message_stream
|
|
284
|
-
kwargs.update(
|
|
285
|
-
{"msgs": message_to_ms_agent_framework_message(request.input)},
|
|
286
|
-
)
|
|
287
275
|
# TODO: support other frameworks
|
|
288
276
|
else:
|
|
289
277
|
|
|
@@ -26,11 +26,7 @@ from typing import (
|
|
|
26
26
|
from pydantic import BaseModel
|
|
27
27
|
from opentelemetry.propagate import extract
|
|
28
28
|
from opentelemetry.context import attach
|
|
29
|
-
from opentelemetry.trace import
|
|
30
|
-
ProxyTracerProvider,
|
|
31
|
-
StatusCode,
|
|
32
|
-
NoOpTracerProvider,
|
|
33
|
-
)
|
|
29
|
+
from opentelemetry.trace import StatusCode, NoOpTracerProvider
|
|
34
30
|
from opentelemetry import trace as ot_trace
|
|
35
31
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
|
36
32
|
OTLPSpanExporter as OTLPSpanGrpcExporter,
|
|
@@ -921,22 +917,12 @@ def _get_ot_tracer() -> ot_trace.Tracer:
|
|
|
921
917
|
ot_trace.Tracer: The OpenTelemetry tracer instance.
|
|
922
918
|
"""
|
|
923
919
|
|
|
924
|
-
def
|
|
925
|
-
from opentelemetry.trace import _TRACER_PROVIDER
|
|
926
|
-
|
|
920
|
+
def _get_ot_tracer_inner() -> ot_trace.Tracer:
|
|
927
921
|
existing_provider = ot_trace.get_tracer_provider()
|
|
928
|
-
if isinstance(existing_provider, NoOpTracerProvider):
|
|
929
|
-
return False
|
|
930
|
-
elif isinstance(existing_provider, ProxyTracerProvider):
|
|
931
|
-
# ProxyTracerProvider will use the _TRACER_PROVIDER as real tracer
|
|
932
|
-
# provider to get the tracer
|
|
933
|
-
return bool(_TRACER_PROVIDER)
|
|
934
922
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
def _get_ot_tracer_inner() -> ot_trace.Tracer:
|
|
938
|
-
if _has_existing_trace_provider():
|
|
923
|
+
if not isinstance(existing_provider, NoOpTracerProvider):
|
|
939
924
|
return ot_trace.get_tracer("agentscope_runtime")
|
|
925
|
+
|
|
940
926
|
resource = Resource(
|
|
941
927
|
attributes={
|
|
942
928
|
SERVICE_NAME: _get_service_name(),
|
|
@@ -3,30 +3,22 @@
|
|
|
3
3
|
# This ensures SandboxRegistry.register() runs at import time.
|
|
4
4
|
# Without this, lazy loading delays module import and types may not be
|
|
5
5
|
# registered.
|
|
6
|
-
from .box.base.base_sandbox import BaseSandbox
|
|
7
|
-
from .box.browser.browser_sandbox import BrowserSandbox
|
|
8
|
-
from .box.filesystem.filesystem_sandbox import
|
|
9
|
-
|
|
10
|
-
FilesystemSandboxAsync,
|
|
11
|
-
)
|
|
12
|
-
from .box.gui.gui_sandbox import GuiSandbox, GuiSandboxAsync
|
|
13
|
-
from .box.mobile.mobile_sandbox import MobileSandbox, MobileSandboxAsync
|
|
6
|
+
from .box.base.base_sandbox import BaseSandbox
|
|
7
|
+
from .box.browser.browser_sandbox import BrowserSandbox
|
|
8
|
+
from .box.filesystem.filesystem_sandbox import FilesystemSandbox
|
|
9
|
+
from .box.gui.gui_sandbox import GuiSandbox
|
|
14
10
|
from .box.training_box.training_box import TrainingSandbox
|
|
15
11
|
from .box.cloud.cloud_sandbox import CloudSandbox
|
|
12
|
+
from .box.mobile.mobile_sandbox import MobileSandbox
|
|
16
13
|
from .box.agentbay.agentbay_sandbox import AgentbaySandbox
|
|
17
14
|
|
|
18
15
|
__all__ = [
|
|
19
16
|
"BaseSandbox",
|
|
20
|
-
"BaseSandboxAsync",
|
|
21
17
|
"BrowserSandbox",
|
|
22
|
-
"BrowserSandboxAsync",
|
|
23
18
|
"FilesystemSandbox",
|
|
24
|
-
"FilesystemSandboxAsync",
|
|
25
19
|
"GuiSandbox",
|
|
26
|
-
"GuiSandboxAsync",
|
|
27
|
-
"MobileSandbox",
|
|
28
|
-
"MobileSandboxAsync",
|
|
29
20
|
"TrainingSandbox",
|
|
30
21
|
"CloudSandbox",
|
|
22
|
+
"MobileSandbox",
|
|
31
23
|
"AgentbaySandbox",
|
|
32
24
|
]
|
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
from ...utils import build_image_uri
|
|
5
5
|
from ...registry import SandboxRegistry
|
|
6
6
|
from ...enums import SandboxType
|
|
7
|
-
from ...box.sandbox import Sandbox
|
|
7
|
+
from ...box.sandbox import Sandbox
|
|
8
8
|
from ...constant import TIMEOUT
|
|
9
9
|
|
|
10
10
|
|
|
@@ -49,53 +49,3 @@ class BaseSandbox(Sandbox):
|
|
|
49
49
|
command (str): Shell command to execute.
|
|
50
50
|
"""
|
|
51
51
|
return self.call_tool("run_shell_command", {"command": command})
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@SandboxRegistry.register(
|
|
55
|
-
build_image_uri("runtime-sandbox-base"),
|
|
56
|
-
sandbox_type=SandboxType.BASE_ASYNC,
|
|
57
|
-
security_level="medium",
|
|
58
|
-
timeout=TIMEOUT,
|
|
59
|
-
description="Base Sandbox (Async)",
|
|
60
|
-
)
|
|
61
|
-
class BaseSandboxAsync(SandboxAsync):
|
|
62
|
-
def __init__(
|
|
63
|
-
self,
|
|
64
|
-
sandbox_id: Optional[str] = None,
|
|
65
|
-
timeout: int = 3000,
|
|
66
|
-
base_url: Optional[str] = None,
|
|
67
|
-
bearer_token: Optional[str] = None,
|
|
68
|
-
sandbox_type: SandboxType = SandboxType.BASE_ASYNC,
|
|
69
|
-
):
|
|
70
|
-
super().__init__(
|
|
71
|
-
sandbox_id,
|
|
72
|
-
timeout,
|
|
73
|
-
base_url,
|
|
74
|
-
bearer_token,
|
|
75
|
-
sandbox_type,
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
async def run_ipython_cell(self, code: str):
|
|
79
|
-
"""
|
|
80
|
-
Run an IPython cell asynchronously.
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
code (str): IPython code to execute.
|
|
84
|
-
Returns:
|
|
85
|
-
Any: Response from sandbox execution
|
|
86
|
-
"""
|
|
87
|
-
return await self.call_tool_async("run_ipython_cell", {"code": code})
|
|
88
|
-
|
|
89
|
-
async def run_shell_command(self, command: str):
|
|
90
|
-
"""
|
|
91
|
-
Run a shell command asynchronously.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
command (str): Shell command to execute.
|
|
95
|
-
Returns:
|
|
96
|
-
Any: Response from sandbox execution
|
|
97
|
-
"""
|
|
98
|
-
return await self.call_tool_async(
|
|
99
|
-
"run_shell_command",
|
|
100
|
-
{"command": command},
|
|
101
|
-
)
|