agentscope-runtime 0.1.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.
- agentscope_runtime/__init__.py +4 -0
- agentscope_runtime/engine/__init__.py +9 -0
- agentscope_runtime/engine/agents/__init__.py +2 -0
- agentscope_runtime/engine/agents/agentscope_agent/__init__.py +6 -0
- agentscope_runtime/engine/agents/agentscope_agent/agent.py +342 -0
- agentscope_runtime/engine/agents/agentscope_agent/hooks.py +156 -0
- agentscope_runtime/engine/agents/agno_agent.py +220 -0
- agentscope_runtime/engine/agents/base_agent.py +29 -0
- agentscope_runtime/engine/agents/langgraph_agent.py +59 -0
- agentscope_runtime/engine/agents/llm_agent.py +51 -0
- agentscope_runtime/engine/deployers/__init__.py +3 -0
- agentscope_runtime/engine/deployers/adapter/__init__.py +0 -0
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +425 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_agent_adapter.py +69 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +60 -0
- agentscope_runtime/engine/deployers/adapter/protocol_adapter.py +24 -0
- agentscope_runtime/engine/deployers/base.py +17 -0
- agentscope_runtime/engine/deployers/local_deployer.py +586 -0
- agentscope_runtime/engine/helpers/helper.py +127 -0
- agentscope_runtime/engine/llms/__init__.py +3 -0
- agentscope_runtime/engine/llms/base_llm.py +60 -0
- agentscope_runtime/engine/llms/qwen_llm.py +47 -0
- agentscope_runtime/engine/misc/__init__.py +0 -0
- agentscope_runtime/engine/runner.py +186 -0
- agentscope_runtime/engine/schemas/__init__.py +0 -0
- agentscope_runtime/engine/schemas/agent_schemas.py +551 -0
- agentscope_runtime/engine/schemas/context.py +54 -0
- agentscope_runtime/engine/services/__init__.py +9 -0
- agentscope_runtime/engine/services/base.py +77 -0
- agentscope_runtime/engine/services/context_manager.py +129 -0
- agentscope_runtime/engine/services/environment_manager.py +50 -0
- agentscope_runtime/engine/services/manager.py +174 -0
- agentscope_runtime/engine/services/memory_service.py +270 -0
- agentscope_runtime/engine/services/sandbox_service.py +198 -0
- agentscope_runtime/engine/services/session_history_service.py +256 -0
- agentscope_runtime/engine/tracing/__init__.py +40 -0
- agentscope_runtime/engine/tracing/base.py +309 -0
- agentscope_runtime/engine/tracing/local_logging_handler.py +356 -0
- agentscope_runtime/engine/tracing/tracing_metric.py +69 -0
- agentscope_runtime/engine/tracing/wrapper.py +321 -0
- agentscope_runtime/sandbox/__init__.py +14 -0
- agentscope_runtime/sandbox/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/base/__init__.py +0 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +37 -0
- agentscope_runtime/sandbox/box/base/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/browser/__init__.py +0 -0
- agentscope_runtime/sandbox/box/browser/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +176 -0
- agentscope_runtime/sandbox/box/dummy/__init__.py +0 -0
- agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +26 -0
- agentscope_runtime/sandbox/box/filesystem/__init__.py +0 -0
- agentscope_runtime/sandbox/box/filesystem/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +87 -0
- agentscope_runtime/sandbox/box/sandbox.py +115 -0
- agentscope_runtime/sandbox/box/shared/__init__.py +0 -0
- agentscope_runtime/sandbox/box/shared/app.py +44 -0
- agentscope_runtime/sandbox/box/shared/dependencies/__init__.py +5 -0
- agentscope_runtime/sandbox/box/shared/dependencies/deps.py +22 -0
- agentscope_runtime/sandbox/box/shared/routers/__init__.py +12 -0
- agentscope_runtime/sandbox/box/shared/routers/generic.py +173 -0
- agentscope_runtime/sandbox/box/shared/routers/mcp.py +207 -0
- agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +153 -0
- agentscope_runtime/sandbox/box/shared/routers/runtime_watcher.py +187 -0
- agentscope_runtime/sandbox/box/shared/routers/workspace.py +325 -0
- agentscope_runtime/sandbox/box/training_box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/training_box/base.py +120 -0
- agentscope_runtime/sandbox/box/training_box/env_service.py +752 -0
- agentscope_runtime/sandbox/box/training_box/environments/__init__.py +0 -0
- agentscope_runtime/sandbox/box/training_box/environments/appworld/appworld_env.py +987 -0
- agentscope_runtime/sandbox/box/training_box/registry.py +54 -0
- agentscope_runtime/sandbox/box/training_box/src/trajectory.py +278 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +219 -0
- agentscope_runtime/sandbox/build.py +213 -0
- agentscope_runtime/sandbox/client/__init__.py +5 -0
- agentscope_runtime/sandbox/client/http_client.py +527 -0
- agentscope_runtime/sandbox/client/training_client.py +265 -0
- agentscope_runtime/sandbox/constant.py +5 -0
- agentscope_runtime/sandbox/custom/__init__.py +16 -0
- agentscope_runtime/sandbox/custom/custom_sandbox.py +40 -0
- agentscope_runtime/sandbox/custom/example.py +37 -0
- agentscope_runtime/sandbox/enums.py +68 -0
- agentscope_runtime/sandbox/manager/__init__.py +4 -0
- agentscope_runtime/sandbox/manager/collections/__init__.py +22 -0
- agentscope_runtime/sandbox/manager/collections/base_mapping.py +20 -0
- agentscope_runtime/sandbox/manager/collections/base_queue.py +25 -0
- agentscope_runtime/sandbox/manager/collections/base_set.py +25 -0
- agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +22 -0
- agentscope_runtime/sandbox/manager/collections/in_memory_queue.py +28 -0
- agentscope_runtime/sandbox/manager/collections/in_memory_set.py +27 -0
- agentscope_runtime/sandbox/manager/collections/redis_mapping.py +26 -0
- agentscope_runtime/sandbox/manager/collections/redis_queue.py +27 -0
- agentscope_runtime/sandbox/manager/collections/redis_set.py +23 -0
- agentscope_runtime/sandbox/manager/container_clients/__init__.py +8 -0
- agentscope_runtime/sandbox/manager/container_clients/base_client.py +39 -0
- agentscope_runtime/sandbox/manager/container_clients/docker_client.py +170 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +694 -0
- agentscope_runtime/sandbox/manager/server/__init__.py +0 -0
- agentscope_runtime/sandbox/manager/server/app.py +194 -0
- agentscope_runtime/sandbox/manager/server/config.py +68 -0
- agentscope_runtime/sandbox/manager/server/models.py +17 -0
- agentscope_runtime/sandbox/manager/storage/__init__.py +10 -0
- agentscope_runtime/sandbox/manager/storage/data_storage.py +16 -0
- agentscope_runtime/sandbox/manager/storage/local_storage.py +44 -0
- agentscope_runtime/sandbox/manager/storage/oss_storage.py +89 -0
- agentscope_runtime/sandbox/manager/utils.py +78 -0
- agentscope_runtime/sandbox/mcp_server.py +192 -0
- agentscope_runtime/sandbox/model/__init__.py +12 -0
- agentscope_runtime/sandbox/model/api.py +16 -0
- agentscope_runtime/sandbox/model/container.py +72 -0
- agentscope_runtime/sandbox/model/manager_config.py +158 -0
- agentscope_runtime/sandbox/registry.py +129 -0
- agentscope_runtime/sandbox/tools/__init__.py +12 -0
- agentscope_runtime/sandbox/tools/base/__init__.py +8 -0
- agentscope_runtime/sandbox/tools/base/tool.py +52 -0
- agentscope_runtime/sandbox/tools/browser/__init__.py +57 -0
- agentscope_runtime/sandbox/tools/browser/tool.py +597 -0
- agentscope_runtime/sandbox/tools/filesystem/__init__.py +32 -0
- agentscope_runtime/sandbox/tools/filesystem/tool.py +319 -0
- agentscope_runtime/sandbox/tools/function_tool.py +321 -0
- agentscope_runtime/sandbox/tools/mcp_tool.py +191 -0
- agentscope_runtime/sandbox/tools/sandbox_tool.py +104 -0
- agentscope_runtime/sandbox/tools/tool.py +123 -0
- agentscope_runtime/sandbox/tools/utils.py +68 -0
- agentscope_runtime/version.py +2 -0
- agentscope_runtime-0.1.0.dist-info/METADATA +327 -0
- agentscope_runtime-0.1.0.dist-info/RECORD +131 -0
- agentscope_runtime-0.1.0.dist-info/WHEEL +5 -0
- agentscope_runtime-0.1.0.dist-info/entry_points.txt +4 -0
- agentscope_runtime-0.1.0.dist-info/licenses/LICENSE +202 -0
- agentscope_runtime-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=unused-argument
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
from pydantic import Field
|
|
9
|
+
from steel import Steel
|
|
10
|
+
|
|
11
|
+
from ..model import ContainerModel
|
|
12
|
+
from ..constant import BROWSER_SESSION_ID
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logging.getLogger("httpx").setLevel(logging.CRITICAL)
|
|
16
|
+
logging.basicConfig(level=logging.INFO)
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SandboxHttpClient:
|
|
21
|
+
"""
|
|
22
|
+
A Python client for interacting with the runtime API. Connect with
|
|
23
|
+
container directly.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
_generic_tools = {
|
|
27
|
+
"run_ipython_cell": {
|
|
28
|
+
"name": "run_ipython_cell",
|
|
29
|
+
"json_schema": {
|
|
30
|
+
"type": "function",
|
|
31
|
+
"function": {
|
|
32
|
+
"name": "run_ipython_cell",
|
|
33
|
+
"description": "Run an IPython cell.",
|
|
34
|
+
"parameters": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"code": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "IPython code to execute",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
"required": ["code"],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
"run_shell_command": {
|
|
48
|
+
"name": "run_shell_command",
|
|
49
|
+
"json_schema": {
|
|
50
|
+
"type": "function",
|
|
51
|
+
"function": {
|
|
52
|
+
"name": "run_shell_command",
|
|
53
|
+
"description": "Run a shell command.",
|
|
54
|
+
"parameters": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {
|
|
57
|
+
"command": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Shell command to execute",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
"required": ["command"],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
model: Optional[ContainerModel] = None,
|
|
72
|
+
timeout: int = 30,
|
|
73
|
+
enable_browser: bool = True,
|
|
74
|
+
domain: str = "localhost",
|
|
75
|
+
) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Initialize the Python client.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
model (ContainerModel): The pydantic model representing the
|
|
81
|
+
runtime sandbox.
|
|
82
|
+
"""
|
|
83
|
+
self.session_id = model.session_id
|
|
84
|
+
self.base_url = model.base_url.replace("localhost", domain)
|
|
85
|
+
self.browser_url = model.browser_url.replace("localhost", domain)
|
|
86
|
+
self.client_browser_ws = model.client_browser_ws.replace(
|
|
87
|
+
"localhost",
|
|
88
|
+
domain,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
self.enable_browser = enable_browser
|
|
92
|
+
self.timeout = timeout
|
|
93
|
+
self.session = requests.Session()
|
|
94
|
+
self.built_in_tools = []
|
|
95
|
+
self.secret = model.runtime_token
|
|
96
|
+
|
|
97
|
+
# Update headers with secret if provided
|
|
98
|
+
headers = {"Content-Type": "application/json"}
|
|
99
|
+
if self.secret:
|
|
100
|
+
headers["Authorization"] = f"Bearer {self.secret}"
|
|
101
|
+
self.session.headers.update(headers)
|
|
102
|
+
|
|
103
|
+
self.steel_client = None
|
|
104
|
+
|
|
105
|
+
def __enter__(self):
|
|
106
|
+
# Wait for the runtime api server to be healthy
|
|
107
|
+
self.wait_until_healthy()
|
|
108
|
+
|
|
109
|
+
if self.enable_browser:
|
|
110
|
+
self.steel_client = Steel(
|
|
111
|
+
steel_api_key="dummy",
|
|
112
|
+
base_url=self.browser_url,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Create a new browser session if it doesn't exist
|
|
116
|
+
try:
|
|
117
|
+
# Try to connet to existing session
|
|
118
|
+
self.steel_client.sessions.retrieve(
|
|
119
|
+
BROWSER_SESSION_ID,
|
|
120
|
+
)
|
|
121
|
+
except Exception:
|
|
122
|
+
# Session not found, create a new one
|
|
123
|
+
self.steel_client.sessions.create(
|
|
124
|
+
session_id=BROWSER_SESSION_ID,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return self
|
|
128
|
+
|
|
129
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
def check_health(self) -> bool:
|
|
133
|
+
"""
|
|
134
|
+
Checks if the runtime service is running by verifying the health
|
|
135
|
+
endpoint.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
bool: True if the service is reachable, False otherwise
|
|
139
|
+
"""
|
|
140
|
+
endpoint = f"{self.base_url}/healthz"
|
|
141
|
+
browser_endpoint = f"{self.browser_url}/v1/health"
|
|
142
|
+
try:
|
|
143
|
+
response_api = self.session.get(endpoint)
|
|
144
|
+
if self.enable_browser:
|
|
145
|
+
response_browser = self.session.get(browser_endpoint)
|
|
146
|
+
return (
|
|
147
|
+
response_api.status_code == 200
|
|
148
|
+
and response_browser.status_code == 200
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
return response_api.status_code == 200
|
|
152
|
+
except requests.RequestException:
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
def wait_until_healthy(self) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Waits until the runtime service is running for a specified timeout.
|
|
158
|
+
"""
|
|
159
|
+
start_time = time.time()
|
|
160
|
+
while time.time() - start_time < self.timeout:
|
|
161
|
+
if self.check_health():
|
|
162
|
+
return
|
|
163
|
+
time.sleep(1)
|
|
164
|
+
raise TimeoutError(
|
|
165
|
+
"Runtime service did not start within the specified timeout.",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def add_mcp_servers(self, server_configs, overwrite=False):
|
|
169
|
+
"""
|
|
170
|
+
Add MCP servers to runtime.
|
|
171
|
+
"""
|
|
172
|
+
try:
|
|
173
|
+
endpoint = f"{self.base_url}/mcp/add_servers"
|
|
174
|
+
response = self.session.post(
|
|
175
|
+
endpoint,
|
|
176
|
+
json={
|
|
177
|
+
"server_configs": server_configs,
|
|
178
|
+
"overwrite": overwrite,
|
|
179
|
+
},
|
|
180
|
+
)
|
|
181
|
+
response.raise_for_status()
|
|
182
|
+
return response.text
|
|
183
|
+
except requests.exceptions.RequestException as e:
|
|
184
|
+
logger.error(f"An error occurred while adding MCP servers: {e}")
|
|
185
|
+
return {
|
|
186
|
+
"isError": True,
|
|
187
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
def list_tools(self, tool_type=None, **kwargs) -> dict:
|
|
191
|
+
try:
|
|
192
|
+
endpoint = f"{self.base_url}/mcp/list_tools"
|
|
193
|
+
response = self.session.get(endpoint)
|
|
194
|
+
response.raise_for_status()
|
|
195
|
+
mcp_tools = response.json()
|
|
196
|
+
mcp_tools["generic"] = self.generic_tools
|
|
197
|
+
if tool_type:
|
|
198
|
+
return {tool_type: mcp_tools.get(tool_type, [])}
|
|
199
|
+
return mcp_tools
|
|
200
|
+
except requests.exceptions.RequestException as e:
|
|
201
|
+
logging.error(f"An error occurred: {e}")
|
|
202
|
+
return {
|
|
203
|
+
"isError": True,
|
|
204
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
def call_tool(
|
|
208
|
+
self,
|
|
209
|
+
name: str,
|
|
210
|
+
arguments: Optional[dict[str, Any]] = None,
|
|
211
|
+
) -> dict:
|
|
212
|
+
if arguments is None:
|
|
213
|
+
arguments = {}
|
|
214
|
+
|
|
215
|
+
if name in self.generic_tools:
|
|
216
|
+
if name == "run_ipython_cell":
|
|
217
|
+
return self.run_ipython_cell(**arguments)
|
|
218
|
+
elif name == "run_shell_command":
|
|
219
|
+
return self.run_shell_command(**arguments)
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
endpoint = f"{self.base_url}/mcp/call_tool"
|
|
223
|
+
response = self.session.post(
|
|
224
|
+
endpoint,
|
|
225
|
+
json={
|
|
226
|
+
"tool_name": name,
|
|
227
|
+
"arguments": arguments,
|
|
228
|
+
},
|
|
229
|
+
)
|
|
230
|
+
response.raise_for_status()
|
|
231
|
+
|
|
232
|
+
return response.json()
|
|
233
|
+
except requests.exceptions.RequestException as e:
|
|
234
|
+
logger.error(f"An error occurred: {e}")
|
|
235
|
+
return {
|
|
236
|
+
"isError": True,
|
|
237
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
def run_ipython_cell(
|
|
241
|
+
self,
|
|
242
|
+
code: str = Field(
|
|
243
|
+
description="IPython code to execute",
|
|
244
|
+
),
|
|
245
|
+
) -> dict:
|
|
246
|
+
"""Run an IPython cell."""
|
|
247
|
+
try:
|
|
248
|
+
endpoint = f"{self.base_url}/tools/run_ipython_cell"
|
|
249
|
+
response = self.session.post(endpoint, json={"code": code})
|
|
250
|
+
response.raise_for_status()
|
|
251
|
+
return response.json()
|
|
252
|
+
except requests.exceptions.RequestException as e:
|
|
253
|
+
logger.error(f"An error occurred: {e}")
|
|
254
|
+
return {
|
|
255
|
+
"isError": True,
|
|
256
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
def run_shell_command(
|
|
260
|
+
self,
|
|
261
|
+
command: str = Field(
|
|
262
|
+
description="Shell command to execute",
|
|
263
|
+
),
|
|
264
|
+
) -> dict:
|
|
265
|
+
"""Run a shell command."""
|
|
266
|
+
try:
|
|
267
|
+
endpoint = f"{self.base_url}/tools/run_shell_command"
|
|
268
|
+
response = self.session.post(endpoint, json={"command": command})
|
|
269
|
+
response.raise_for_status()
|
|
270
|
+
return response.json()
|
|
271
|
+
except requests.exceptions.RequestException as e:
|
|
272
|
+
logger.error(f"An error occurred: {e}")
|
|
273
|
+
return {
|
|
274
|
+
"isError": True,
|
|
275
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def generic_tools(self) -> dict:
|
|
280
|
+
return self._generic_tools
|
|
281
|
+
|
|
282
|
+
# Below the method is used by API Server
|
|
283
|
+
def commit_changes(self, commit_message: str = "Automated commit") -> dict:
|
|
284
|
+
"""
|
|
285
|
+
Commit the uncommitted changes with a given commit message.
|
|
286
|
+
"""
|
|
287
|
+
try:
|
|
288
|
+
endpoint = f"{self.base_url}/watcher/commit_changes"
|
|
289
|
+
response = self.session.post(
|
|
290
|
+
endpoint,
|
|
291
|
+
json={"commit_message": commit_message},
|
|
292
|
+
)
|
|
293
|
+
response.raise_for_status()
|
|
294
|
+
return response.json()
|
|
295
|
+
except requests.exceptions.RequestException as e:
|
|
296
|
+
logger.error(f"An error occurred while committing changes: {e}")
|
|
297
|
+
return {
|
|
298
|
+
"isError": True,
|
|
299
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
def generate_diff(
|
|
303
|
+
self,
|
|
304
|
+
commit_a: Optional[str] = None,
|
|
305
|
+
commit_b: Optional[str] = None,
|
|
306
|
+
) -> dict:
|
|
307
|
+
"""
|
|
308
|
+
Generate the diff between two commits or between uncommitted changes
|
|
309
|
+
and the latest commit.
|
|
310
|
+
"""
|
|
311
|
+
try:
|
|
312
|
+
endpoint = f"{self.base_url}/watcher/generate_diff"
|
|
313
|
+
response = self.session.post(
|
|
314
|
+
endpoint,
|
|
315
|
+
json={"commit_a": commit_a, "commit_b": commit_b},
|
|
316
|
+
)
|
|
317
|
+
response.raise_for_status()
|
|
318
|
+
return response.json()
|
|
319
|
+
except requests.exceptions.RequestException as e:
|
|
320
|
+
logger.error(f"An error occurred while generating diff: {e}")
|
|
321
|
+
return {
|
|
322
|
+
"isError": True,
|
|
323
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
def git_logs(self) -> dict:
|
|
327
|
+
"""
|
|
328
|
+
Retrieve the git logs.
|
|
329
|
+
"""
|
|
330
|
+
try:
|
|
331
|
+
endpoint = f"{self.base_url}/watcher/git_logs"
|
|
332
|
+
response = self.session.get(endpoint)
|
|
333
|
+
response.raise_for_status()
|
|
334
|
+
return response.json()
|
|
335
|
+
except requests.exceptions.RequestException as e:
|
|
336
|
+
logger.error(f"An error occurred while retrieving git logs: {e}")
|
|
337
|
+
return {
|
|
338
|
+
"isError": True,
|
|
339
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
def get_workspace_file(self, file_path: str) -> dict:
|
|
343
|
+
"""
|
|
344
|
+
Retrieve a file from the /workspace directory.
|
|
345
|
+
"""
|
|
346
|
+
try:
|
|
347
|
+
endpoint = f"{self.base_url}/workspace/files"
|
|
348
|
+
params = {"file_path": file_path}
|
|
349
|
+
response = self.session.get(endpoint, params=params)
|
|
350
|
+
response.raise_for_status()
|
|
351
|
+
# Return the binary content of the file
|
|
352
|
+
# Check for empty content
|
|
353
|
+
if response.headers.get("Content-Length") == "0":
|
|
354
|
+
logger.warning(f"The file {file_path} is empty.")
|
|
355
|
+
return {"data": b""}
|
|
356
|
+
|
|
357
|
+
# Accumulate the content in chunks
|
|
358
|
+
file_content = bytearray()
|
|
359
|
+
for chunk in response.iter_content(chunk_size=4096):
|
|
360
|
+
file_content.extend(chunk)
|
|
361
|
+
|
|
362
|
+
return {"data": bytes(file_content)}
|
|
363
|
+
except requests.exceptions.RequestException as e:
|
|
364
|
+
logger.error(f"An error occurred while retrieving the file: {e}")
|
|
365
|
+
return {
|
|
366
|
+
"isError": True,
|
|
367
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
def create_or_edit_workspace_file(
|
|
371
|
+
self,
|
|
372
|
+
file_path: str,
|
|
373
|
+
content: str,
|
|
374
|
+
) -> dict:
|
|
375
|
+
"""
|
|
376
|
+
Create or edit a file within the /workspace directory.
|
|
377
|
+
"""
|
|
378
|
+
try:
|
|
379
|
+
endpoint = f"{self.base_url}/workspace/files"
|
|
380
|
+
params = {"file_path": file_path}
|
|
381
|
+
data = {"content": content}
|
|
382
|
+
response = self.session.post(endpoint, params=params, json=data)
|
|
383
|
+
response.raise_for_status()
|
|
384
|
+
return response.json()
|
|
385
|
+
except requests.exceptions.RequestException as e:
|
|
386
|
+
logger.error(
|
|
387
|
+
f"An error occurred while creating or editing a workspace "
|
|
388
|
+
f"file: {e}",
|
|
389
|
+
)
|
|
390
|
+
return {
|
|
391
|
+
"isError": True,
|
|
392
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
def list_workspace_directories(
|
|
396
|
+
self,
|
|
397
|
+
directory: str = "/workspace",
|
|
398
|
+
) -> dict:
|
|
399
|
+
"""
|
|
400
|
+
List files in the specified directory within the /workspace.
|
|
401
|
+
"""
|
|
402
|
+
try:
|
|
403
|
+
endpoint = f"{self.base_url}/workspace/list-directories"
|
|
404
|
+
params = {"directory": directory}
|
|
405
|
+
response = self.session.get(endpoint, params=params)
|
|
406
|
+
response.raise_for_status()
|
|
407
|
+
return response.json()
|
|
408
|
+
except requests.exceptions.RequestException as e:
|
|
409
|
+
logger.error(f"An error occurred while listing files: {e}")
|
|
410
|
+
return {
|
|
411
|
+
"isError": True,
|
|
412
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
def create_workspace_directory(self, directory_path: str) -> dict:
|
|
416
|
+
"""
|
|
417
|
+
Create a directory within the /workspace directory.
|
|
418
|
+
"""
|
|
419
|
+
try:
|
|
420
|
+
endpoint = f"{self.base_url}/workspace/directories"
|
|
421
|
+
params = {"directory_path": directory_path}
|
|
422
|
+
response = self.session.post(endpoint, params=params)
|
|
423
|
+
response.raise_for_status()
|
|
424
|
+
return response.json()
|
|
425
|
+
except requests.exceptions.RequestException as e:
|
|
426
|
+
logger.error(
|
|
427
|
+
f"An error occurred while creating a workspace directory: {e}",
|
|
428
|
+
)
|
|
429
|
+
return {
|
|
430
|
+
"isError": True,
|
|
431
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
def delete_workspace_file(self, file_path: str) -> dict:
|
|
435
|
+
"""
|
|
436
|
+
Delete a file within the /workspace directory.
|
|
437
|
+
"""
|
|
438
|
+
try:
|
|
439
|
+
endpoint = f"{self.base_url}/workspace/files"
|
|
440
|
+
params = {"file_path": file_path}
|
|
441
|
+
response = self.session.delete(endpoint, params=params)
|
|
442
|
+
response.raise_for_status()
|
|
443
|
+
return response.json()
|
|
444
|
+
except requests.exceptions.RequestException as e:
|
|
445
|
+
logger.error(
|
|
446
|
+
f"An error occurred while deleting a workspace file: {e}",
|
|
447
|
+
)
|
|
448
|
+
return {
|
|
449
|
+
"isError": True,
|
|
450
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
def delete_workspace_directory(
|
|
454
|
+
self,
|
|
455
|
+
directory_path: str,
|
|
456
|
+
recursive: bool = False,
|
|
457
|
+
) -> dict:
|
|
458
|
+
"""
|
|
459
|
+
Delete a directory within the /workspace directory.
|
|
460
|
+
"""
|
|
461
|
+
try:
|
|
462
|
+
endpoint = f"{self.base_url}/workspace/directories"
|
|
463
|
+
params = {"directory_path": directory_path, "recursive": recursive}
|
|
464
|
+
response = self.session.delete(endpoint, params=params)
|
|
465
|
+
response.raise_for_status()
|
|
466
|
+
return response.json()
|
|
467
|
+
except requests.exceptions.RequestException as e:
|
|
468
|
+
logger.error(
|
|
469
|
+
f"An error occurred while deleting a workspace directory: {e}",
|
|
470
|
+
)
|
|
471
|
+
return {
|
|
472
|
+
"isError": True,
|
|
473
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
def move_or_rename_workspace_item(
|
|
477
|
+
self,
|
|
478
|
+
source_path: str,
|
|
479
|
+
destination_path: str,
|
|
480
|
+
) -> dict:
|
|
481
|
+
"""
|
|
482
|
+
Move or rename a file or directory within the /workspace directory.
|
|
483
|
+
"""
|
|
484
|
+
try:
|
|
485
|
+
endpoint = f"{self.base_url}/workspace/move"
|
|
486
|
+
params = {
|
|
487
|
+
"source_path": source_path,
|
|
488
|
+
"destination_path": destination_path,
|
|
489
|
+
}
|
|
490
|
+
response = self.session.put(endpoint, params=params)
|
|
491
|
+
response.raise_for_status()
|
|
492
|
+
return response.json()
|
|
493
|
+
except requests.exceptions.RequestException as e:
|
|
494
|
+
logger.error(
|
|
495
|
+
f"An error occurred while moving or renaming a workspace "
|
|
496
|
+
f"item: {e}",
|
|
497
|
+
)
|
|
498
|
+
return {
|
|
499
|
+
"isError": True,
|
|
500
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
def copy_workspace_item(
|
|
504
|
+
self,
|
|
505
|
+
source_path: str,
|
|
506
|
+
destination_path: str,
|
|
507
|
+
) -> dict:
|
|
508
|
+
"""
|
|
509
|
+
Copy a file or directory within the /workspace directory.
|
|
510
|
+
"""
|
|
511
|
+
try:
|
|
512
|
+
endpoint = f"{self.base_url}/workspace/copy"
|
|
513
|
+
params = {
|
|
514
|
+
"source_path": source_path,
|
|
515
|
+
"destination_path": destination_path,
|
|
516
|
+
}
|
|
517
|
+
response = self.session.post(endpoint, params=params)
|
|
518
|
+
response.raise_for_status()
|
|
519
|
+
return response.json()
|
|
520
|
+
except requests.exceptions.RequestException as e:
|
|
521
|
+
logger.error(
|
|
522
|
+
f"An error occurred while copying a workspace item: {e}",
|
|
523
|
+
)
|
|
524
|
+
return {
|
|
525
|
+
"isError": True,
|
|
526
|
+
"content": [{"type": "text", "text": str(e)}],
|
|
527
|
+
}
|