agentscope-runtime 0.1.6__py3-none-any.whl → 0.2.0__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 (87) hide show
  1. agentscope_runtime/common/container_clients/__init__.py +0 -0
  2. agentscope_runtime/{sandbox/manager → common}/container_clients/kubernetes_client.py +546 -6
  3. agentscope_runtime/engine/__init__.py +12 -0
  4. agentscope_runtime/engine/agents/agentscope_agent.py +130 -10
  5. agentscope_runtime/engine/agents/agno_agent.py +8 -10
  6. agentscope_runtime/engine/agents/langgraph_agent.py +52 -9
  7. agentscope_runtime/engine/app/__init__.py +6 -0
  8. agentscope_runtime/engine/app/agent_app.py +239 -0
  9. agentscope_runtime/engine/app/base_app.py +181 -0
  10. agentscope_runtime/engine/app/celery_mixin.py +92 -0
  11. agentscope_runtime/engine/deployers/__init__.py +13 -0
  12. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +0 -0
  13. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +2890 -0
  14. agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +51 -0
  15. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +314 -0
  16. agentscope_runtime/engine/deployers/base.py +1 -0
  17. agentscope_runtime/engine/deployers/cli_fc_deploy.py +203 -0
  18. agentscope_runtime/engine/deployers/kubernetes_deployer.py +272 -0
  19. agentscope_runtime/engine/deployers/local_deployer.py +414 -501
  20. agentscope_runtime/engine/deployers/modelstudio_deployer.py +838 -0
  21. agentscope_runtime/engine/deployers/utils/__init__.py +0 -0
  22. agentscope_runtime/engine/deployers/utils/deployment_modes.py +14 -0
  23. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +8 -0
  24. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +429 -0
  25. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +240 -0
  26. agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +306 -0
  27. agentscope_runtime/engine/deployers/utils/package_project_utils.py +1163 -0
  28. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +9 -0
  29. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +1064 -0
  30. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +157 -0
  31. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +268 -0
  32. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +75 -0
  33. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +220 -0
  34. agentscope_runtime/engine/deployers/utils/service_utils/standalone_main.py.j2 +211 -0
  35. agentscope_runtime/engine/deployers/utils/wheel_packager.py +389 -0
  36. agentscope_runtime/engine/helpers/agent_api_builder.py +651 -0
  37. agentscope_runtime/engine/runner.py +76 -35
  38. agentscope_runtime/engine/schemas/agent_schemas.py +112 -2
  39. agentscope_runtime/engine/schemas/embedding.py +37 -0
  40. agentscope_runtime/engine/schemas/modelstudio_llm.py +310 -0
  41. agentscope_runtime/engine/schemas/oai_llm.py +538 -0
  42. agentscope_runtime/engine/schemas/realtime.py +254 -0
  43. agentscope_runtime/engine/services/tablestore_memory_service.py +4 -1
  44. agentscope_runtime/engine/tracing/__init__.py +9 -3
  45. agentscope_runtime/engine/tracing/asyncio_util.py +24 -0
  46. agentscope_runtime/engine/tracing/base.py +66 -34
  47. agentscope_runtime/engine/tracing/local_logging_handler.py +45 -31
  48. agentscope_runtime/engine/tracing/message_util.py +528 -0
  49. agentscope_runtime/engine/tracing/tracing_metric.py +20 -8
  50. agentscope_runtime/engine/tracing/tracing_util.py +130 -0
  51. agentscope_runtime/engine/tracing/wrapper.py +794 -169
  52. agentscope_runtime/sandbox/box/base/base_sandbox.py +2 -1
  53. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +2 -1
  54. agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +2 -1
  55. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +2 -1
  56. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +2 -1
  57. agentscope_runtime/sandbox/box/training_box/training_box.py +0 -42
  58. agentscope_runtime/sandbox/client/http_client.py +52 -18
  59. agentscope_runtime/sandbox/constant.py +3 -0
  60. agentscope_runtime/sandbox/custom/custom_sandbox.py +2 -1
  61. agentscope_runtime/sandbox/custom/example.py +2 -1
  62. agentscope_runtime/sandbox/enums.py +0 -1
  63. agentscope_runtime/sandbox/manager/sandbox_manager.py +29 -22
  64. agentscope_runtime/sandbox/model/container.py +6 -0
  65. agentscope_runtime/sandbox/registry.py +1 -1
  66. agentscope_runtime/sandbox/tools/tool.py +4 -0
  67. agentscope_runtime/version.py +1 -1
  68. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/METADATA +103 -59
  69. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/RECORD +87 -52
  70. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/entry_points.txt +1 -0
  71. /agentscope_runtime/{sandbox/manager/container_clients → common}/__init__.py +0 -0
  72. /agentscope_runtime/{sandbox/manager → common}/collections/__init__.py +0 -0
  73. /agentscope_runtime/{sandbox/manager → common}/collections/base_mapping.py +0 -0
  74. /agentscope_runtime/{sandbox/manager → common}/collections/base_queue.py +0 -0
  75. /agentscope_runtime/{sandbox/manager → common}/collections/base_set.py +0 -0
  76. /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_mapping.py +0 -0
  77. /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_queue.py +0 -0
  78. /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_set.py +0 -0
  79. /agentscope_runtime/{sandbox/manager → common}/collections/redis_mapping.py +0 -0
  80. /agentscope_runtime/{sandbox/manager → common}/collections/redis_queue.py +0 -0
  81. /agentscope_runtime/{sandbox/manager → common}/collections/redis_set.py +0 -0
  82. /agentscope_runtime/{sandbox/manager → common}/container_clients/agentrun_client.py +0 -0
  83. /agentscope_runtime/{sandbox/manager → common}/container_clients/base_client.py +0 -0
  84. /agentscope_runtime/{sandbox/manager → common}/container_clients/docker_client.py +0 -0
  85. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/WHEEL +0 -0
  86. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/licenses/LICENSE +0 -0
  87. {agentscope_runtime-0.1.6.dist-info → agentscope_runtime-0.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,220 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint:disable=line-too-long
3
+
4
+ from typing import Dict, Type, Any
5
+ from .service_config import (
6
+ ServiceType,
7
+ ServiceProvider,
8
+ ServiceConfig,
9
+ ServicesConfig,
10
+ )
11
+
12
+
13
+ class ServiceFactory:
14
+ """Factory for creating service instances based on configuration."""
15
+
16
+ # Service registry mapping service types and providers to
17
+ # implementation classes
18
+ _service_registry: Dict[str, Dict[str, Type]] = {}
19
+
20
+ @classmethod
21
+ def _populate_registry(cls):
22
+ """Populate the service registry with available implementations."""
23
+ if cls._service_registry:
24
+ return # Already populated
25
+
26
+ try:
27
+ # Import service implementations
28
+ from agentscope_runtime.engine.services.memory_service import (
29
+ InMemoryMemoryService,
30
+ )
31
+ from agentscope_runtime.engine.services.session_history_service import ( # noqa E501
32
+ InMemorySessionHistoryService,
33
+ )
34
+
35
+ # Register memory services
36
+ cls._service_registry[ServiceType.MEMORY] = {
37
+ ServiceProvider.IN_MEMORY: InMemoryMemoryService,
38
+ }
39
+
40
+ # Register session history services
41
+ cls._service_registry[ServiceType.SESSION_HISTORY] = {
42
+ ServiceProvider.IN_MEMORY: InMemorySessionHistoryService,
43
+ }
44
+
45
+ # Try to register Redis services if available
46
+
47
+ from agentscope_runtime.engine.services.redis_memory_service import ( # noqa E501
48
+ RedisMemoryService,
49
+ )
50
+ from agentscope_runtime.engine.services.redis_session_history_service import ( # noqa E501
51
+ RedisSessionHistoryService,
52
+ )
53
+
54
+ cls._service_registry[ServiceType.MEMORY][
55
+ ServiceProvider.REDIS
56
+ ] = RedisMemoryService
57
+ cls._service_registry[ServiceType.SESSION_HISTORY][
58
+ ServiceProvider.REDIS
59
+ ] = RedisSessionHistoryService
60
+
61
+ # Try to register other services if available
62
+ from agentscope_runtime.engine.services.sandbox_service import (
63
+ SandboxService,
64
+ )
65
+
66
+ # Assuming default implementation
67
+ cls._service_registry[ServiceType.SANDBOX] = {
68
+ ServiceProvider.IN_MEMORY: SandboxService,
69
+ }
70
+
71
+ from agentscope_runtime.engine.services.rag_service import (
72
+ RAGService,
73
+ )
74
+
75
+ # Assuming default implementation
76
+ cls._service_registry[ServiceType.RAG] = {
77
+ ServiceProvider.IN_MEMORY: RAGService,
78
+ }
79
+
80
+ except ImportError as e:
81
+ raise RuntimeError(
82
+ f"Failed to import required service classes: {e}",
83
+ ) from e
84
+
85
+ @classmethod
86
+ def create_service(
87
+ cls,
88
+ service_type: ServiceType,
89
+ config: ServiceConfig,
90
+ ) -> Any:
91
+ """Create a service instance based on type and configuration.
92
+
93
+ Args:
94
+ service_type: Type of service to create
95
+ config: Configuration for the service
96
+
97
+ Returns:
98
+ Service instance
99
+
100
+ Raises:
101
+ ValueError: If service type or provider is unknown
102
+ RuntimeError: If service creation fails
103
+ """
104
+ cls._populate_registry()
105
+
106
+ if service_type not in cls._service_registry:
107
+ raise ValueError(f"Unknown service type: {service_type}")
108
+
109
+ providers = cls._service_registry[service_type]
110
+ if config.provider not in providers:
111
+ available_providers = list(providers.keys())
112
+ raise ValueError(
113
+ f"Unknown provider '{config.provider}' for service '"
114
+ f"{service_type}'. Available providers: {available_providers}",
115
+ )
116
+
117
+ service_class = providers[config.provider]
118
+
119
+ try:
120
+ # Create service instance with configuration parameters
121
+ return service_class(**config.config)
122
+ except Exception as e:
123
+ raise RuntimeError(
124
+ f"Failed to create {service_type} service with provider "
125
+ f"'{config.provider}': {e}",
126
+ ) from e
127
+
128
+ @classmethod
129
+ def register_service(
130
+ cls,
131
+ service_type: ServiceType,
132
+ provider: ServiceProvider,
133
+ service_class: Type,
134
+ ):
135
+ """Register a new service implementation.
136
+
137
+ Args:
138
+ service_type: Type of service
139
+ provider: Service provider
140
+ service_class: Implementation class
141
+ """
142
+ cls._populate_registry()
143
+
144
+ if service_type not in cls._service_registry:
145
+ cls._service_registry[service_type] = {}
146
+
147
+ cls._service_registry[service_type][provider] = service_class
148
+
149
+ @classmethod
150
+ def create_services_from_config(
151
+ cls,
152
+ config: ServicesConfig,
153
+ ) -> Dict[str, Any]:
154
+ """Create all services from a services configuration.
155
+
156
+ Args:
157
+ config: Services configuration
158
+
159
+ Returns:
160
+ Dict mapping service names to service instances
161
+
162
+ Raises:
163
+ RuntimeError: If any required service creation fails
164
+ """
165
+ services = {}
166
+
167
+ # Create required services
168
+ try:
169
+ services["memory"] = cls.create_service(
170
+ ServiceType.MEMORY,
171
+ config.memory,
172
+ )
173
+ services["session_history"] = cls.create_service(
174
+ ServiceType.SESSION_HISTORY,
175
+ config.session_history,
176
+ )
177
+ except Exception as e:
178
+ raise RuntimeError(
179
+ f"Failed to create required services: {e}",
180
+ ) from e
181
+
182
+ # Create optional services
183
+ if config.sandbox:
184
+ try:
185
+ services["sandbox"] = cls.create_service(
186
+ ServiceType.SANDBOX,
187
+ config.sandbox,
188
+ )
189
+ except Exception as e:
190
+ # Log warning but don't fail
191
+ print(f"Warning: Failed to create sandbox service: {e}")
192
+
193
+ if config.rag:
194
+ try:
195
+ services["rag"] = cls.create_service(
196
+ ServiceType.RAG,
197
+ config.rag,
198
+ )
199
+ except Exception as e:
200
+ # Log warning but don't fail
201
+ print(f"Warning: Failed to create RAG service: {e}")
202
+
203
+ return services
204
+
205
+ @classmethod
206
+ def get_available_providers(cls, service_type: ServiceType) -> list:
207
+ """Get list of available providers for a service type.
208
+
209
+ Args:
210
+ service_type: Type of service
211
+
212
+ Returns:
213
+ List of available provider names
214
+ """
215
+ cls._populate_registry()
216
+
217
+ if service_type not in cls._service_registry:
218
+ return []
219
+
220
+ return list(cls._service_registry[service_type].keys())
@@ -0,0 +1,211 @@
1
+ import os
2
+ import sys
3
+
4
+ # Add current directory and handler directories to Python path for local module imports
5
+ current_dir = os.path.dirname(os.path.abspath(__file__))
6
+ if current_dir not in sys.path:
7
+ sys.path.insert(0, current_dir)
8
+
9
+ {% if handler_dirs %}
10
+ # Add copied handler directories to sys.path
11
+ {% for handler_dir in handler_dirs %}
12
+ handler_dir_path = os.path.join(current_dir, "{{handler_dir}}")
13
+ if os.path.isdir(handler_dir_path) and handler_dir_path not in sys.path:
14
+ sys.path.insert(0, handler_dir_path)
15
+ {% endfor %}
16
+ {% endif %}
17
+
18
+ import uvicorn
19
+ from agentscope_runtime.engine.deployers.utils.deployment_modes import DeploymentMode
20
+ from agentscope_runtime.engine.deployers.utils.service_utils import (
21
+ FastAPIAppFactory,
22
+ ServicesConfig,
23
+ ServiceConfig,
24
+ )
25
+ from agentscope_runtime.engine.schemas.agent_schemas import AgentRequest
26
+ from typing import Callable, Optional, Dict, List, Any, Union
27
+
28
+ from agent_file import {{agent_name}} as agent
29
+ {% if protocol_adapters %}{{protocol_adapters}}{% endif %}
30
+
31
+ {% if custom_endpoints %}
32
+ # Custom endpoint imports
33
+ {% for endpoint in custom_endpoints %}
34
+ {% if endpoint.handler_module and endpoint.function_name %}
35
+ from {{endpoint.handler_module}} import {{endpoint.function_name}}
36
+ {% elif endpoint.module and endpoint.function_name %}
37
+ from agent_file import {{endpoint.function_name}}
38
+ {% endif %}
39
+ {% endfor %}
40
+ {% endif %}
41
+
42
+
43
+
44
+ def load_services_config() -> ServicesConfig:
45
+ """Load services configuration from environment variables or config file."""
46
+ config_file = os.getenv('AGENTSCOPE_SERVICES_CONFIG')
47
+
48
+ if config_file and os.path.exists(config_file):
49
+ # Load from JSON config file
50
+ import json
51
+ with open(config_file, 'r', encoding='utf-8') as f:
52
+ config_data = json.load(f)
53
+ return ServicesConfig.model_validate(config_data)
54
+ else:
55
+ # Load from environment variables
56
+ memory_provider = os.getenv('MEMORY_PROVIDER', 'in_memory')
57
+ session_provider = os.getenv('SESSION_HISTORY_PROVIDER', 'in_memory')
58
+
59
+ memory_config = {}
60
+ session_config = {}
61
+
62
+ # Add Redis configuration if using Redis
63
+ if memory_provider == 'redis':
64
+ memory_config = {
65
+ 'host': os.getenv('REDIS_HOST', 'localhost'),
66
+ 'port': int(os.getenv('REDIS_PORT', 6379)),
67
+ 'db': int(os.getenv('REDIS_MEMORY_DB', 0))
68
+ }
69
+
70
+ if session_provider == 'redis':
71
+ session_config = {
72
+ 'host': os.getenv('REDIS_HOST', 'localhost'),
73
+ 'port': int(os.getenv('REDIS_PORT', 6379)),
74
+ 'db': int(os.getenv('REDIS_SESSION_DB', 1))
75
+ }
76
+
77
+ return ServicesConfig(
78
+ memory=ServiceConfig(provider=memory_provider, config=memory_config),
79
+ session_history=ServiceConfig(provider=session_provider, config=session_config)
80
+ )
81
+
82
+
83
+ def load_celery_config():
84
+ """Load Celery configuration from environment variables or infer from existing config."""
85
+ celery_config = {
86
+ 'broker_url': None,
87
+ 'backend_url': None,
88
+ 'enable_embedded_worker': False,
89
+ 'redis_available': False
90
+ }
91
+
92
+ {% if celery_config %}
93
+ # Apply inline Celery configuration
94
+ {{celery_config}}
95
+ {% endif %}
96
+
97
+ if not celery_config.get('broker_url') or not celery_config.get('backend_url'):
98
+ redis_host = os.getenv('REDIS_HOST', 'localhost')
99
+ redis_port = os.getenv('REDIS_PORT', '6379')
100
+
101
+ # Use different databases for different purposes
102
+ broker_db = os.getenv('CELERY_BROKER_DB', '2') # Default DB 2 for Celery broker
103
+ backend_db = os.getenv('CELERY_BACKEND_DB', '3') # Default DB 3 for Celery backend
104
+
105
+ # Auto-generate URLs if Redis is available
106
+ if not celery_config.get('broker_url'):
107
+ celery_config['broker_url'] = f"redis://{redis_host}:{redis_port}/{broker_db}"
108
+ if not celery_config.get('backend_url'):
109
+ celery_config['backend_url'] = f"redis://{redis_host}:{redis_port}/{backend_db}"
110
+
111
+ return celery_config
112
+
113
+
114
+ def _check_redis_availability(redis_url: str) -> bool:
115
+ """Check if Redis is available at the given URL."""
116
+ try:
117
+ import redis
118
+ from urllib.parse import urlparse
119
+
120
+ parsed = urlparse(redis_url)
121
+ host = parsed.hostname or 'localhost'
122
+ port = parsed.port or 6379
123
+
124
+ r = redis.Redis(host=host, port=port, socket_connect_timeout=2)
125
+ r.ping()
126
+ return True
127
+ except Exception:
128
+ return False
129
+
130
+
131
+ {% if custom_endpoints %}
132
+ def setup_custom_endpoints():
133
+ """Setup custom endpoints configuration."""
134
+ custom_endpoints = [
135
+ {% for endpoint in custom_endpoints %}
136
+ {
137
+ "path": "{{endpoint.path}}",
138
+ "handler": {% if endpoint.handler_module or endpoint.module %}{{endpoint.function_name}}{% else %}{{endpoint.inline_code|default('lambda request: {"error": "Handler not available"}')}}{% endif %},
139
+ "methods": {{endpoint.methods}}
140
+ },
141
+ {% endfor %}
142
+ ]
143
+ return custom_endpoints
144
+ {% endif %}
145
+
146
+
147
+ async def setup_runner_with_agent(app):
148
+ """Setup runner with the agent instance."""
149
+ if hasattr(app.state, 'runner') and app.state.runner:
150
+ # Set the agent on the runner
151
+ app.state.runner._agent = agent
152
+
153
+
154
+ async def before_start(app, **kwargs):
155
+ """Application startup callback."""
156
+ await setup_runner_with_agent(app)
157
+
158
+
159
+ async def after_finish(app, **kwargs):
160
+ """Application shutdown callback."""
161
+ # Runner cleanup is handled by the factory
162
+ pass
163
+
164
+
165
+ # Load services configuration
166
+ services_config = load_services_config()
167
+
168
+ # Load Celery configuration
169
+ celery_config = load_celery_config()
170
+
171
+ # Determine deployment mode from environment or use default
172
+ deployment_mode_str = os.getenv('DEPLOYMENT_MODE', '{{deployment_mode|default("standalone")}}')
173
+ if deployment_mode_str == 'detached_process':
174
+ deployment_mode = DeploymentMode.DETACHED_PROCESS
175
+ elif deployment_mode_str == 'standalone':
176
+ deployment_mode = DeploymentMode.STANDALONE
177
+ else:
178
+ deployment_mode = DeploymentMode.STANDALONE # fallback
179
+
180
+ # Create FastAPI application using the factory
181
+ app = FastAPIAppFactory.create_app(
182
+ endpoint_path="{{endpoint_path}}",
183
+ mode=deployment_mode,
184
+ services_config=services_config,
185
+ before_start=before_start,
186
+ after_finish=after_finish,
187
+ stream=True,
188
+ broker_url=celery_config['broker_url'],
189
+ backend_url=celery_config['backend_url'],
190
+ enable_embedded_worker=celery_config['enable_embedded_worker']{% if protocol_adapters %},
191
+ protocol_adapters=protocol_adapters{% endif %}{% if custom_endpoints %},
192
+ custom_endpoints=setup_custom_endpoints(){% endif %}
193
+ )
194
+
195
+
196
+ if __name__ == "__main__":
197
+ import argparse
198
+
199
+ parser = argparse.ArgumentParser(description="AgentScope Runtime Standalone Service")
200
+ parser.add_argument("--host", default="0.0.0.0", help="Host to bind to")
201
+ parser.add_argument("--port", type=int, default=8080, help="Port to bind to")
202
+ parser.add_argument("--workers", type=int, default=1, help="Number of worker processes")
203
+
204
+ args = parser.parse_args()
205
+
206
+ uvicorn.run(
207
+ app,
208
+ host=args.host,
209
+ port=args.port,
210
+ workers=args.workers if args.workers > 1 else None
211
+ )