agentscope-runtime 0.1.5b2__py3-none-any.whl → 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.
- agentscope_runtime/engine/agents/agentscope_agent.py +447 -0
- agentscope_runtime/engine/agents/agno_agent.py +19 -18
- agentscope_runtime/engine/agents/autogen_agent.py +13 -8
- agentscope_runtime/engine/agents/utils.py +53 -0
- agentscope_runtime/engine/deployers/__init__.py +0 -13
- agentscope_runtime/engine/deployers/local_deployer.py +501 -356
- agentscope_runtime/engine/helpers/helper.py +60 -41
- agentscope_runtime/engine/runner.py +11 -36
- agentscope_runtime/engine/schemas/agent_schemas.py +2 -70
- agentscope_runtime/engine/services/sandbox_service.py +62 -70
- agentscope_runtime/engine/services/tablestore_memory_service.py +304 -0
- agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
- agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
- agentscope_runtime/sandbox/__init__.py +2 -0
- agentscope_runtime/sandbox/box/base/__init__.py +4 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +4 -3
- agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +8 -13
- agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
- agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +8 -6
- agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +80 -0
- agentscope_runtime/sandbox/box/sandbox.py +5 -2
- agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
- agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +10 -15
- agentscope_runtime/sandbox/build.py +143 -58
- agentscope_runtime/sandbox/client/http_client.py +43 -49
- agentscope_runtime/sandbox/client/training_client.py +0 -1
- agentscope_runtime/sandbox/constant.py +24 -1
- agentscope_runtime/sandbox/custom/custom_sandbox.py +5 -5
- agentscope_runtime/sandbox/custom/example.py +2 -2
- agentscope_runtime/sandbox/enums.py +1 -0
- agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +11 -6
- agentscope_runtime/sandbox/manager/collections/redis_mapping.py +25 -9
- agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
- agentscope_runtime/sandbox/manager/container_clients/agentrun_client.py +1098 -0
- agentscope_runtime/sandbox/manager/container_clients/docker_client.py +33 -205
- agentscope_runtime/sandbox/manager/container_clients/kubernetes_client.py +8 -555
- agentscope_runtime/sandbox/manager/sandbox_manager.py +187 -88
- agentscope_runtime/sandbox/manager/server/app.py +82 -14
- agentscope_runtime/sandbox/manager/server/config.py +50 -3
- agentscope_runtime/sandbox/model/container.py +6 -23
- agentscope_runtime/sandbox/model/manager_config.py +93 -5
- agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
- agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
- agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
- agentscope_runtime/sandbox/utils.py +124 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/METADATA +168 -77
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/RECORD +59 -78
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/entry_points.txt +0 -1
- agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
- agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
- agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
- agentscope_runtime/engine/agents/llm_agent.py +0 -51
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +0 -2886
- agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +0 -51
- agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +0 -314
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +0 -184
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +0 -265
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +0 -677
- agentscope_runtime/engine/deployers/utils/deployment_modes.py +0 -14
- agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +0 -8
- agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +0 -429
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +0 -240
- agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +0 -297
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -932
- agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -9
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +0 -504
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +0 -157
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +0 -268
- agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
- agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +0 -389
- agentscope_runtime/engine/helpers/agent_api_builder.py +0 -651
- agentscope_runtime/engine/llms/__init__.py +0 -3
- agentscope_runtime/engine/llms/base_llm.py +0 -60
- agentscope_runtime/engine/llms/qwen_llm.py +0 -47
- agentscope_runtime/engine/schemas/embedding.py +0 -37
- agentscope_runtime/engine/schemas/modelstudio_llm.py +0 -310
- agentscope_runtime/engine/schemas/oai_llm.py +0 -538
- agentscope_runtime/engine/schemas/realtime.py +0 -254
- /agentscope_runtime/engine/{deployers/adapter/responses → services/utils}/__init__.py +0 -0
- /agentscope_runtime/{engine/deployers/utils → sandbox/box/gui/box}/__init__.py +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.1.6.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
+
import logging
|
|
2
3
|
|
|
3
4
|
from agentscope_runtime.engine import Runner
|
|
4
5
|
from agentscope_runtime.engine.schemas.agent_schemas import (
|
|
@@ -13,22 +14,28 @@ from agentscope_runtime.engine.services.environment_manager import (
|
|
|
13
14
|
create_environment_manager,
|
|
14
15
|
)
|
|
15
16
|
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
async def simple_call_agent(query, runner, user_id=None, session_id=None):
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
if isinstance(query, str):
|
|
22
|
+
request = AgentRequest(
|
|
23
|
+
input=[
|
|
24
|
+
{
|
|
25
|
+
"role": "user",
|
|
26
|
+
"content": [
|
|
27
|
+
{
|
|
28
|
+
"type": "text",
|
|
29
|
+
"text": query,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
session_id=session_id,
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
request = query
|
|
38
|
+
|
|
32
39
|
all_result = ""
|
|
33
40
|
async for message in runner.stream_query(
|
|
34
41
|
user_id=user_id,
|
|
@@ -58,6 +65,23 @@ async def simple_call_agent_direct(agent, query):
|
|
|
58
65
|
|
|
59
66
|
|
|
60
67
|
async def simple_call_agent_tool(agent, query):
|
|
68
|
+
if isinstance(query, str):
|
|
69
|
+
request = AgentRequest(
|
|
70
|
+
input=[
|
|
71
|
+
{
|
|
72
|
+
"role": "user",
|
|
73
|
+
"content": [
|
|
74
|
+
{
|
|
75
|
+
"type": "text",
|
|
76
|
+
"text": query,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
)
|
|
82
|
+
else:
|
|
83
|
+
request = query
|
|
84
|
+
|
|
61
85
|
all_result = ""
|
|
62
86
|
async with create_context_manager() as context_manager:
|
|
63
87
|
async with create_environment_manager() as environment_manager:
|
|
@@ -67,20 +91,6 @@ async def simple_call_agent_tool(agent, query):
|
|
|
67
91
|
environment_manager=environment_manager,
|
|
68
92
|
)
|
|
69
93
|
|
|
70
|
-
request = AgentRequest(
|
|
71
|
-
input=[
|
|
72
|
-
{
|
|
73
|
-
"role": "user",
|
|
74
|
-
"content": [
|
|
75
|
-
{
|
|
76
|
-
"type": "text",
|
|
77
|
-
"text": query,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
)
|
|
83
|
-
|
|
84
94
|
async for message in runner.stream_query(
|
|
85
95
|
request=request,
|
|
86
96
|
):
|
|
@@ -94,12 +104,7 @@ async def simple_call_agent_tool(agent, query):
|
|
|
94
104
|
|
|
95
105
|
|
|
96
106
|
async def simple_call_agent_tool_auto_lifecycle(agent, query):
|
|
97
|
-
|
|
98
|
-
async with Runner(
|
|
99
|
-
agent=agent,
|
|
100
|
-
context_manager=create_context_manager(),
|
|
101
|
-
environment_manager=create_environment_manager(),
|
|
102
|
-
) as runner:
|
|
107
|
+
if isinstance(query, str):
|
|
103
108
|
request = AgentRequest(
|
|
104
109
|
input=[
|
|
105
110
|
{
|
|
@@ -113,7 +118,15 @@ async def simple_call_agent_tool_auto_lifecycle(agent, query):
|
|
|
113
118
|
},
|
|
114
119
|
],
|
|
115
120
|
)
|
|
121
|
+
else:
|
|
122
|
+
request = query
|
|
116
123
|
|
|
124
|
+
all_result = ""
|
|
125
|
+
async with Runner(
|
|
126
|
+
agent=agent,
|
|
127
|
+
context_manager=create_context_manager(),
|
|
128
|
+
environment_manager=create_environment_manager(),
|
|
129
|
+
) as runner:
|
|
117
130
|
async for message in runner.stream_query(
|
|
118
131
|
request=request,
|
|
119
132
|
):
|
|
@@ -127,13 +140,7 @@ async def simple_call_agent_tool_auto_lifecycle(agent, query):
|
|
|
127
140
|
|
|
128
141
|
|
|
129
142
|
async def simple_call_agent_tool_wo_env(agent, query):
|
|
130
|
-
|
|
131
|
-
async with create_context_manager() as context_manager:
|
|
132
|
-
runner = Runner(
|
|
133
|
-
agent=agent,
|
|
134
|
-
context_manager=context_manager,
|
|
135
|
-
)
|
|
136
|
-
|
|
143
|
+
if isinstance(query, str):
|
|
137
144
|
request = AgentRequest(
|
|
138
145
|
input=[
|
|
139
146
|
{
|
|
@@ -147,6 +154,15 @@ async def simple_call_agent_tool_wo_env(agent, query):
|
|
|
147
154
|
},
|
|
148
155
|
],
|
|
149
156
|
)
|
|
157
|
+
else:
|
|
158
|
+
request = query
|
|
159
|
+
|
|
160
|
+
all_result = ""
|
|
161
|
+
async with create_context_manager() as context_manager:
|
|
162
|
+
runner = Runner(
|
|
163
|
+
agent=agent,
|
|
164
|
+
context_manager=context_manager,
|
|
165
|
+
)
|
|
150
166
|
|
|
151
167
|
async for message in runner.stream_query(
|
|
152
168
|
request=request,
|
|
@@ -157,4 +173,7 @@ async def simple_call_agent_tool_wo_env(agent, query):
|
|
|
157
173
|
and RunStatus.Completed == message.status
|
|
158
174
|
):
|
|
159
175
|
all_result = message.content[0].text
|
|
176
|
+
|
|
177
|
+
logger.debug(message.model_dump())
|
|
178
|
+
|
|
160
179
|
return all_result
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import uuid
|
|
3
|
+
from typing import Optional, List, AsyncGenerator, Any
|
|
3
4
|
from contextlib import AsyncExitStack
|
|
4
|
-
from typing import Optional, List, AsyncGenerator, Any, Union, Dict
|
|
5
5
|
|
|
6
6
|
from openai.types.chat import ChatCompletion
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
ServicesConfig,
|
|
10
|
-
)
|
|
8
|
+
from .deployers.adapter.protocol_adapter import ProtocolAdapter
|
|
11
9
|
from .agents import Agent
|
|
10
|
+
from .schemas.context import Context
|
|
12
11
|
from .deployers import (
|
|
13
12
|
DeployManager,
|
|
14
13
|
LocalDeployManager,
|
|
15
14
|
)
|
|
16
|
-
from .deployers.adapter.protocol_adapter import ProtocolAdapter
|
|
17
15
|
from .schemas.agent_schemas import (
|
|
18
16
|
Event,
|
|
19
17
|
AgentRequest,
|
|
20
18
|
RunStatus,
|
|
21
19
|
AgentResponse,
|
|
22
20
|
)
|
|
23
|
-
from .schemas.context import Context
|
|
24
21
|
from .services.context_manager import ContextManager
|
|
25
22
|
from .services.environment_manager import EnvironmentManager
|
|
26
23
|
from .tracing import TraceType
|
|
@@ -80,57 +77,37 @@ class Runner:
|
|
|
80
77
|
endpoint_path: str = "/process",
|
|
81
78
|
stream: bool = True,
|
|
82
79
|
protocol_adapters: Optional[list[ProtocolAdapter]] = None,
|
|
83
|
-
requirements: Optional[Union[str, List[str]]] = None,
|
|
84
|
-
extra_packages: Optional[List[str]] = None,
|
|
85
|
-
base_image: str = "python:3.9-slim",
|
|
86
|
-
environment: Optional[Dict[str, str]] = None,
|
|
87
|
-
runtime_config: Optional[Dict] = None,
|
|
88
|
-
services_config: Optional[Union[ServicesConfig, dict]] = None,
|
|
89
|
-
**kwargs,
|
|
90
80
|
):
|
|
91
81
|
"""
|
|
92
82
|
Deploys the agent as a service.
|
|
93
83
|
|
|
94
84
|
Args:
|
|
85
|
+
protocol_adapters: protocol adapters
|
|
95
86
|
deploy_manager: Deployment manager to handle service deployment
|
|
96
87
|
endpoint_path: API endpoint path for the processing function
|
|
97
88
|
stream: If start a streaming service
|
|
98
|
-
protocol_adapters: protocol adapters
|
|
99
|
-
requirements: PyPI dependencies
|
|
100
|
-
extra_packages: User code directory/file path
|
|
101
|
-
base_image: Docker base image (for containerized deployment)
|
|
102
|
-
environment: Environment variables dict
|
|
103
|
-
runtime_config: Runtime configuration dict
|
|
104
|
-
services_config: Services configuration dict
|
|
105
|
-
**kwargs: Additional arguments passed to deployment manager
|
|
106
89
|
Returns:
|
|
107
90
|
URL of the deployed service
|
|
108
91
|
|
|
109
92
|
Raises:
|
|
110
93
|
RuntimeError: If deployment fails
|
|
111
94
|
"""
|
|
95
|
+
if stream:
|
|
96
|
+
deploy_func = self.stream_query
|
|
97
|
+
else:
|
|
98
|
+
deploy_func = self.query
|
|
112
99
|
deploy_result = await deploy_manager.deploy(
|
|
113
|
-
|
|
100
|
+
deploy_func,
|
|
114
101
|
endpoint_path=endpoint_path,
|
|
115
|
-
stream=stream,
|
|
116
102
|
protocol_adapters=protocol_adapters,
|
|
117
|
-
requirements=requirements,
|
|
118
|
-
extra_packages=extra_packages,
|
|
119
|
-
base_image=base_image,
|
|
120
|
-
environment=environment,
|
|
121
|
-
runtime_config=runtime_config,
|
|
122
|
-
services_config=services_config,
|
|
123
|
-
**kwargs,
|
|
124
103
|
)
|
|
125
|
-
|
|
126
|
-
# TODO: add redis or other persistant method
|
|
127
104
|
self._deploy_managers[deploy_manager.deploy_id] = deploy_result
|
|
128
105
|
return deploy_result
|
|
129
106
|
|
|
130
107
|
@trace(TraceType.AGENT_STEP)
|
|
131
108
|
async def stream_query( # pylint:disable=unused-argument
|
|
132
109
|
self,
|
|
133
|
-
request:
|
|
110
|
+
request: AgentRequest,
|
|
134
111
|
user_id: Optional[str] = None,
|
|
135
112
|
tools: Optional[List] = None,
|
|
136
113
|
**kwargs: Any,
|
|
@@ -138,9 +115,6 @@ class Runner:
|
|
|
138
115
|
"""
|
|
139
116
|
Streams the agent.
|
|
140
117
|
"""
|
|
141
|
-
if isinstance(request, dict):
|
|
142
|
-
request = AgentRequest(**request)
|
|
143
|
-
|
|
144
118
|
response = AgentResponse()
|
|
145
119
|
yield response
|
|
146
120
|
|
|
@@ -221,6 +195,7 @@ class Runner:
|
|
|
221
195
|
"""
|
|
222
196
|
Streams the agent.
|
|
223
197
|
"""
|
|
198
|
+
# TODO: fix this @zhicheng
|
|
224
199
|
return self._agent.query(message, session_id)
|
|
225
200
|
|
|
226
201
|
# TODO: should be sync method?
|
|
@@ -27,7 +27,6 @@ class MessageType:
|
|
|
27
27
|
MCP_APPROVAL_REQUEST = "mcp_approval_request"
|
|
28
28
|
MCP_TOOL_CALL = "mcp_call"
|
|
29
29
|
MCP_APPROVAL_RESPONSE = "mcp_approval_response"
|
|
30
|
-
REASONING = "reasoning"
|
|
31
30
|
HEARTBEAT = "heartbeat"
|
|
32
31
|
ERROR = "error"
|
|
33
32
|
|
|
@@ -46,8 +45,6 @@ class ContentType:
|
|
|
46
45
|
DATA = "data"
|
|
47
46
|
IMAGE = "image"
|
|
48
47
|
AUDIO = "audio"
|
|
49
|
-
FILE = "file"
|
|
50
|
-
REFUSAL = "refusal"
|
|
51
48
|
|
|
52
49
|
|
|
53
50
|
class Role:
|
|
@@ -69,8 +66,6 @@ class RunStatus:
|
|
|
69
66
|
Failed = "failed"
|
|
70
67
|
Rejected = "rejected"
|
|
71
68
|
Unknown = "unknown"
|
|
72
|
-
Queued = "queued"
|
|
73
|
-
Incomplete = "incomplete"
|
|
74
69
|
|
|
75
70
|
|
|
76
71
|
class FunctionParameters(BaseModel):
|
|
@@ -287,63 +282,6 @@ class DataContent(Content):
|
|
|
287
282
|
"""The data content."""
|
|
288
283
|
|
|
289
284
|
|
|
290
|
-
class AudioContent(Content):
|
|
291
|
-
type: Literal[ContentType.AUDIO] = ContentType.AUDIO
|
|
292
|
-
"""The type of the content part."""
|
|
293
|
-
|
|
294
|
-
data: Optional[str] = None
|
|
295
|
-
"""The audio data details."""
|
|
296
|
-
|
|
297
|
-
format: Optional[str] = None
|
|
298
|
-
"""
|
|
299
|
-
The format of the audio data.
|
|
300
|
-
"""
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
class FileContent(Content):
|
|
304
|
-
type: Literal[ContentType.FILE] = ContentType.FILE
|
|
305
|
-
"""The type of the content part."""
|
|
306
|
-
|
|
307
|
-
file_url: Optional[str] = None
|
|
308
|
-
"""The file URL details."""
|
|
309
|
-
|
|
310
|
-
file_id: Optional[str] = None
|
|
311
|
-
"""The file ID details."""
|
|
312
|
-
|
|
313
|
-
filename: Optional[str] = None
|
|
314
|
-
"""The file name details."""
|
|
315
|
-
|
|
316
|
-
file_data: Optional[str] = None
|
|
317
|
-
"""The file data details."""
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
class RefusalContent(Content):
|
|
321
|
-
type: Literal[ContentType.REFUSAL] = ContentType.REFUSAL
|
|
322
|
-
"""The type of the content part."""
|
|
323
|
-
|
|
324
|
-
refusal: Optional[str] = None
|
|
325
|
-
"""The refusal content."""
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
class ToolCall(BaseModel):
|
|
329
|
-
arguments: str
|
|
330
|
-
"""A JSON string of the arguments to pass to the function."""
|
|
331
|
-
|
|
332
|
-
call_id: str
|
|
333
|
-
"""The unique ID of the function tool call generated by the model."""
|
|
334
|
-
|
|
335
|
-
name: str
|
|
336
|
-
"""The name of the function to run."""
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
class ToolCallOutput(BaseModel):
|
|
340
|
-
call_id: str
|
|
341
|
-
"""The unique ID of the function tool call generated by the model."""
|
|
342
|
-
|
|
343
|
-
output: str
|
|
344
|
-
"""A JSON string of the output of the function tool call."""
|
|
345
|
-
|
|
346
|
-
|
|
347
285
|
AgentRole: TypeAlias = Literal[
|
|
348
286
|
Role.ASSISTANT,
|
|
349
287
|
Role.SYSTEM,
|
|
@@ -351,15 +289,9 @@ AgentRole: TypeAlias = Literal[
|
|
|
351
289
|
Role.TOOL,
|
|
352
290
|
]
|
|
353
291
|
|
|
292
|
+
|
|
354
293
|
AgentContent = Annotated[
|
|
355
|
-
Union[
|
|
356
|
-
TextContent,
|
|
357
|
-
ImageContent,
|
|
358
|
-
DataContent,
|
|
359
|
-
AudioContent,
|
|
360
|
-
FileContent,
|
|
361
|
-
RefusalContent,
|
|
362
|
-
],
|
|
294
|
+
Union[TextContent, ImageContent, DataContent],
|
|
363
295
|
Field(discriminator="type"),
|
|
364
296
|
]
|
|
365
297
|
|
|
@@ -2,27 +2,17 @@
|
|
|
2
2
|
# pylint: disable=too-many-branches
|
|
3
3
|
from typing import List
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from ...sandbox.tools.function_tool import FunctionTool
|
|
12
|
-
except ImportError:
|
|
13
|
-
pass
|
|
14
|
-
|
|
5
|
+
from ...sandbox.enums import SandboxType
|
|
6
|
+
from ...sandbox.manager import SandboxManager
|
|
7
|
+
from ...sandbox.registry import SandboxRegistry
|
|
8
|
+
from ...sandbox.tools.mcp_tool import MCPTool
|
|
9
|
+
from ...sandbox.tools.sandbox_tool import SandboxTool
|
|
10
|
+
from ...sandbox.tools.function_tool import FunctionTool
|
|
15
11
|
from ...engine.services.base import ServiceWithLifecycleManager
|
|
16
12
|
|
|
17
13
|
|
|
18
14
|
class SandboxService(ServiceWithLifecycleManager):
|
|
19
15
|
def __init__(self, base_url=None, bearer_token=None):
|
|
20
|
-
if SandboxManager is None:
|
|
21
|
-
raise ImportError(
|
|
22
|
-
"SandboxManager is not available. "
|
|
23
|
-
"Please install agentscope-runtime[sandbox]",
|
|
24
|
-
)
|
|
25
|
-
|
|
26
16
|
self.manager_api = SandboxManager(
|
|
27
17
|
base_url=base_url,
|
|
28
18
|
bearer_token=bearer_token,
|
|
@@ -30,18 +20,20 @@ class SandboxService(ServiceWithLifecycleManager):
|
|
|
30
20
|
|
|
31
21
|
self.base_url = base_url
|
|
32
22
|
self.bearer_token = bearer_token
|
|
33
|
-
self.sandbox_type_set = set(item.value for item in SandboxType)
|
|
34
|
-
|
|
35
|
-
self.session_mapping = {}
|
|
36
23
|
|
|
37
24
|
async def start(self) -> None:
|
|
38
25
|
pass
|
|
39
26
|
|
|
40
27
|
async def stop(self) -> None:
|
|
41
28
|
# Release all environments
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
session_keys = self.manager_api.list_session_keys()
|
|
30
|
+
|
|
31
|
+
if session_keys:
|
|
32
|
+
for session_ctx_id in session_keys:
|
|
33
|
+
env_ids = self.manager_api.get_session_mapping(session_ctx_id)
|
|
34
|
+
if env_ids:
|
|
35
|
+
for env_id in env_ids:
|
|
36
|
+
self.manager_api.release(env_id)
|
|
45
37
|
|
|
46
38
|
if self.base_url is None:
|
|
47
39
|
# Embedded mode
|
|
@@ -57,61 +49,52 @@ class SandboxService(ServiceWithLifecycleManager):
|
|
|
57
49
|
env_types=None,
|
|
58
50
|
tools=None,
|
|
59
51
|
) -> List:
|
|
60
|
-
for tool in tools:
|
|
61
|
-
if not isinstance(tool, (SandboxTool, FunctionTool, MCPTool)):
|
|
62
|
-
raise ValueError(
|
|
63
|
-
"tools must be instances of SandboxTool, FunctionTool, "
|
|
64
|
-
"or MCPTool",
|
|
65
|
-
)
|
|
66
|
-
|
|
67
52
|
# Create a composite key
|
|
68
|
-
|
|
53
|
+
session_ctx_id = self._create_session_ctx_id(session_id, user_id)
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
env_ids = self.manager_api.get_session_mapping(session_ctx_id)
|
|
56
|
+
|
|
57
|
+
# Check if the session_ctx_id already has an environment
|
|
58
|
+
if env_ids:
|
|
72
59
|
# Connect to existing environment
|
|
73
|
-
return self._connect_existing_environment(
|
|
60
|
+
return self._connect_existing_environment(env_ids)
|
|
74
61
|
else:
|
|
75
62
|
# Create a new environment
|
|
76
63
|
return self._create_new_environment(
|
|
77
|
-
|
|
64
|
+
session_ctx_id,
|
|
78
65
|
env_types,
|
|
79
66
|
tools,
|
|
80
67
|
)
|
|
81
68
|
|
|
82
69
|
def _create_new_environment(
|
|
83
70
|
self,
|
|
84
|
-
|
|
71
|
+
session_ctx_id: str,
|
|
85
72
|
env_types=None,
|
|
86
73
|
tools=None,
|
|
87
74
|
):
|
|
75
|
+
if tools:
|
|
76
|
+
for tool in tools:
|
|
77
|
+
if not isinstance(tool, (SandboxTool, FunctionTool, MCPTool)):
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"tools must be instances of SandboxTool, "
|
|
80
|
+
"FunctionTool, or MCPTool",
|
|
81
|
+
)
|
|
82
|
+
|
|
88
83
|
if env_types is None:
|
|
89
84
|
assert (
|
|
90
85
|
tools is not None
|
|
91
86
|
), "tools must be specified when env_types is not set"
|
|
92
87
|
|
|
93
|
-
server_configs = None
|
|
94
88
|
if tools:
|
|
95
|
-
server_config_list = []
|
|
96
89
|
tool_env_types = set()
|
|
97
90
|
for tool in tools:
|
|
98
91
|
tool_env_types.add(tool.sandbox_type)
|
|
99
|
-
if isinstance(tool, MCPTool):
|
|
100
|
-
server_config_list.append(tool.server_configs)
|
|
101
|
-
|
|
102
92
|
if env_types is None:
|
|
103
93
|
env_types = []
|
|
104
94
|
|
|
105
|
-
if server_config_list:
|
|
106
|
-
server_configs = {"mcpServers": {}}
|
|
107
|
-
for server_config in server_config_list:
|
|
108
|
-
server_configs["mcpServers"].update(
|
|
109
|
-
server_config["mcpServers"],
|
|
110
|
-
)
|
|
111
|
-
|
|
112
95
|
env_types = set(env_types) | tool_env_types
|
|
113
96
|
|
|
114
|
-
|
|
97
|
+
sandboxes = []
|
|
115
98
|
for env_type in env_types:
|
|
116
99
|
if env_type is None:
|
|
117
100
|
continue
|
|
@@ -120,6 +103,7 @@ class SandboxService(ServiceWithLifecycleManager):
|
|
|
120
103
|
|
|
121
104
|
box_id = self.manager_api.create_from_pool(
|
|
122
105
|
sandbox_type=box_type.value,
|
|
106
|
+
meta={"session_ctx_id": session_ctx_id},
|
|
123
107
|
)
|
|
124
108
|
box_cls = SandboxRegistry.get_classes_by_type(box_type)
|
|
125
109
|
|
|
@@ -135,22 +119,30 @@ class SandboxService(ServiceWithLifecycleManager):
|
|
|
135
119
|
# Embedded mode
|
|
136
120
|
box.manager_api = self.manager_api
|
|
137
121
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
122
|
+
# Add MCP to the sandbox
|
|
123
|
+
server_config_list = []
|
|
124
|
+
if tools:
|
|
125
|
+
for tool in tools:
|
|
126
|
+
if isinstance(tool, MCPTool) and SandboxType(
|
|
127
|
+
tool.sandbox_type,
|
|
128
|
+
) == SandboxType(box_type):
|
|
129
|
+
server_config_list.append(tool.server_configs)
|
|
130
|
+
if server_config_list:
|
|
131
|
+
server_configs = {"mcpServers": {}}
|
|
132
|
+
for server_config in server_config_list:
|
|
133
|
+
if (
|
|
134
|
+
server_config is not None
|
|
135
|
+
and "mcpServers" in server_config
|
|
136
|
+
):
|
|
137
|
+
server_configs["mcpServers"].update(
|
|
138
|
+
server_config["mcpServers"],
|
|
139
|
+
)
|
|
140
|
+
box.add_mcp_servers(server_configs, overwrite=False)
|
|
141
|
+
|
|
142
|
+
sandboxes.append(box)
|
|
143
|
+
return sandboxes
|
|
144
|
+
|
|
145
|
+
def _connect_existing_environment(self, env_ids: List[str]):
|
|
154
146
|
boxes = []
|
|
155
147
|
for env_id in env_ids:
|
|
156
148
|
info = self.manager_api.get_info(env_id)
|
|
@@ -183,16 +175,16 @@ class SandboxService(ServiceWithLifecycleManager):
|
|
|
183
175
|
return boxes
|
|
184
176
|
|
|
185
177
|
def release(self, session_id, user_id):
|
|
186
|
-
|
|
178
|
+
session_ctx_id = self._create_session_ctx_id(session_id, user_id)
|
|
187
179
|
|
|
188
|
-
|
|
189
|
-
env_ids = self.session_mapping.pop(composite_key, [])
|
|
180
|
+
env_ids = self.manager_api.get_session_mapping(session_ctx_id)
|
|
190
181
|
|
|
191
|
-
|
|
192
|
-
|
|
182
|
+
if env_ids:
|
|
183
|
+
for env_id in env_ids:
|
|
184
|
+
self.manager_api.release(env_id)
|
|
193
185
|
|
|
194
186
|
return True
|
|
195
187
|
|
|
196
|
-
def
|
|
188
|
+
def _create_session_ctx_id(self, session_id, user_id):
|
|
197
189
|
# Create a composite key from session_id and user_id
|
|
198
190
|
return f"{session_id}_{user_id}"
|