agentscope-runtime 1.0.1__py3-none-any.whl → 1.0.3__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.
Files changed (69) hide show
  1. agentscope_runtime/adapters/agentscope/message.py +32 -7
  2. agentscope_runtime/adapters/agentscope/stream.py +121 -91
  3. agentscope_runtime/adapters/agno/__init__.py +0 -0
  4. agentscope_runtime/adapters/agno/message.py +30 -0
  5. agentscope_runtime/adapters/agno/stream.py +122 -0
  6. agentscope_runtime/adapters/langgraph/__init__.py +12 -0
  7. agentscope_runtime/adapters/langgraph/message.py +257 -0
  8. agentscope_runtime/adapters/langgraph/stream.py +205 -0
  9. agentscope_runtime/cli/__init__.py +7 -0
  10. agentscope_runtime/cli/cli.py +63 -0
  11. agentscope_runtime/cli/commands/__init__.py +2 -0
  12. agentscope_runtime/cli/commands/chat.py +815 -0
  13. agentscope_runtime/cli/commands/deploy.py +1074 -0
  14. agentscope_runtime/cli/commands/invoke.py +58 -0
  15. agentscope_runtime/cli/commands/list_cmd.py +103 -0
  16. agentscope_runtime/cli/commands/run.py +176 -0
  17. agentscope_runtime/cli/commands/sandbox.py +128 -0
  18. agentscope_runtime/cli/commands/status.py +60 -0
  19. agentscope_runtime/cli/commands/stop.py +185 -0
  20. agentscope_runtime/cli/commands/web.py +166 -0
  21. agentscope_runtime/cli/loaders/__init__.py +6 -0
  22. agentscope_runtime/cli/loaders/agent_loader.py +295 -0
  23. agentscope_runtime/cli/state/__init__.py +10 -0
  24. agentscope_runtime/cli/utils/__init__.py +18 -0
  25. agentscope_runtime/cli/utils/console.py +378 -0
  26. agentscope_runtime/cli/utils/validators.py +118 -0
  27. agentscope_runtime/common/collections/redis_mapping.py +4 -1
  28. agentscope_runtime/engine/app/agent_app.py +55 -9
  29. agentscope_runtime/engine/deployers/__init__.py +1 -0
  30. agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +56 -1
  31. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +449 -41
  32. agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +273 -0
  33. agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +640 -0
  34. agentscope_runtime/engine/deployers/agentrun_deployer.py +152 -22
  35. agentscope_runtime/engine/deployers/base.py +27 -2
  36. agentscope_runtime/engine/deployers/kubernetes_deployer.py +161 -31
  37. agentscope_runtime/engine/deployers/local_deployer.py +188 -25
  38. agentscope_runtime/engine/deployers/modelstudio_deployer.py +109 -18
  39. agentscope_runtime/engine/deployers/state/__init__.py +9 -0
  40. agentscope_runtime/engine/deployers/state/manager.py +388 -0
  41. agentscope_runtime/engine/deployers/state/schema.py +96 -0
  42. agentscope_runtime/engine/deployers/utils/build_cache.py +736 -0
  43. agentscope_runtime/engine/deployers/utils/detached_app.py +105 -30
  44. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +31 -10
  45. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +23 -10
  46. agentscope_runtime/engine/deployers/utils/docker_image_utils/image_factory.py +35 -2
  47. agentscope_runtime/engine/deployers/utils/k8s_utils.py +241 -0
  48. agentscope_runtime/engine/deployers/utils/net_utils.py +65 -0
  49. agentscope_runtime/engine/deployers/utils/package.py +56 -6
  50. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +16 -2
  51. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +155 -5
  52. agentscope_runtime/engine/deployers/utils/wheel_packager.py +107 -123
  53. agentscope_runtime/engine/runner.py +30 -9
  54. agentscope_runtime/engine/schemas/exception.py +604 -0
  55. agentscope_runtime/engine/services/agent_state/redis_state_service.py +61 -8
  56. agentscope_runtime/engine/services/agent_state/state_service_factory.py +2 -5
  57. agentscope_runtime/engine/services/memory/redis_memory_service.py +129 -25
  58. agentscope_runtime/engine/services/session_history/redis_session_history_service.py +160 -34
  59. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +113 -39
  60. agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +20 -4
  61. agentscope_runtime/sandbox/build.py +50 -57
  62. agentscope_runtime/sandbox/utils.py +2 -0
  63. agentscope_runtime/version.py +1 -1
  64. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/METADATA +31 -8
  65. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/RECORD +69 -36
  66. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/entry_points.txt +1 -0
  67. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/WHEEL +0 -0
  68. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/licenses/LICENSE +0 -0
  69. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,273 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ A2A Registry Extension Point
4
+
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.
12
+ """
13
+ import logging
14
+ import os
15
+ from abc import ABC, abstractmethod
16
+ from dataclasses import dataclass, field
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
22
+
23
+ from a2a.types import AgentCard
24
+
25
+ if TYPE_CHECKING:
26
+ from v2.nacos import ClientConfig
27
+
28
+ __all__ = [
29
+ "A2ARegistry",
30
+ "A2ATransportsProperties",
31
+ "A2ARegistrySettings",
32
+ "get_registry_settings",
33
+ "create_registry_from_env",
34
+ ]
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+
39
+ @dataclass
40
+ class A2ATransportsProperties:
41
+ """A2A transport properties for multi-transport support.
42
+
43
+ Attributes:
44
+ host: Transport host
45
+ port: Transport port
46
+ path: Transport path
47
+ support_tls: Whether TLS is supported
48
+ extra: Additional transport properties
49
+ transport_type: Type of transport (e.g., "JSONRPC", "HTTP")
50
+ """
51
+
52
+ host: Optional[str] = None
53
+ port: Optional[int] = None
54
+ path: Optional[str] = None
55
+ support_tls: Optional[bool] = False
56
+ extra: Dict[str, Any] = field(default_factory=dict)
57
+ transport_type: str = "JSONRPC"
58
+
59
+
60
+ class A2ARegistry(ABC):
61
+ """Abstract base class for A2A registry implementations.
62
+
63
+ Implementations should not raise on non-fatal errors during startup; the
64
+ runtime will catch and log exceptions so that registry failures do not
65
+ prevent the runtime from starting.
66
+ """
67
+
68
+ @abstractmethod
69
+ def registry_name(self) -> str:
70
+ """Return a short name identifying the registry (e.g. "nacos")."""
71
+ raise NotImplementedError("Subclasses must implement registry_name()")
72
+
73
+ @abstractmethod
74
+ def register(
75
+ self,
76
+ agent_card: AgentCard,
77
+ a2a_transports_properties: Optional[
78
+ List[A2ATransportsProperties]
79
+ ] = None,
80
+ ) -> None:
81
+ """Register an agent/service.
82
+
83
+ Args:
84
+ agent_card: Agent card of this agent
85
+ a2a_transports_properties: Multiple transports for A2A Server,
86
+ and each transport might include different configs.
87
+
88
+ Implementations may register the agent card itself and/or endpoint
89
+ depending on their semantics.
90
+ """
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