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,551 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# type: ignore
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import List, Dict, Optional, Any
|
|
6
|
+
from typing import Union
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from typing import Self
|
|
10
|
+
except ImportError:
|
|
11
|
+
from typing_extensions import Self
|
|
12
|
+
from uuid import uuid4
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, Field, field_validator
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MessageType:
|
|
18
|
+
MESSAGE = "message"
|
|
19
|
+
FUNCTION_CALL = "function_call"
|
|
20
|
+
FUNCTION_CALL_OUTPUT = "function_call_output"
|
|
21
|
+
PLUGIN_CALL = "plugin_call"
|
|
22
|
+
PLUGIN_CALL_OUTPUT = "plugin_call_output"
|
|
23
|
+
COMPONENT_CALL = "component_call"
|
|
24
|
+
COMPONENT_CALL_OUTPUT = "component_call_output"
|
|
25
|
+
MCP_LIST_TOOLS = "mcp_list_tools"
|
|
26
|
+
MCP_APPROVAL_REQUEST = "mcp_approval_request"
|
|
27
|
+
MCP_TOOL_CALL = "mcp_call"
|
|
28
|
+
MCP_APPROVAL_RESPONSE = "mcp_approval_response"
|
|
29
|
+
HEARTBEAT = "heartbeat"
|
|
30
|
+
ERROR = "error"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ContentType:
|
|
34
|
+
TEXT = "text"
|
|
35
|
+
DATA = "data"
|
|
36
|
+
IMAGE = "image"
|
|
37
|
+
AUDIO = "audio"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Role:
|
|
41
|
+
ASSISTANT = "assistant"
|
|
42
|
+
USER = "user"
|
|
43
|
+
SYSTEM = "system"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RunStatus:
|
|
47
|
+
"""
|
|
48
|
+
Enum class for agent event message.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
Created = "created"
|
|
52
|
+
InProgress = "in_progress"
|
|
53
|
+
Completed = "completed"
|
|
54
|
+
Canceled = "canceled"
|
|
55
|
+
Failed = "failed"
|
|
56
|
+
Rejected = "rejected"
|
|
57
|
+
Unknown = "unknown"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class FunctionParameters(BaseModel):
|
|
61
|
+
type: str
|
|
62
|
+
"""The type of the parameters object. Must be `object`."""
|
|
63
|
+
|
|
64
|
+
properties: Dict[str, Any]
|
|
65
|
+
"""The properties of the parameters object."""
|
|
66
|
+
|
|
67
|
+
required: Optional[List[str]]
|
|
68
|
+
"""The names of the required properties."""
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class FunctionTool(BaseModel):
|
|
72
|
+
"""
|
|
73
|
+
Model class for prompt message tool.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
name: str
|
|
77
|
+
"""The name of the function to be called. """
|
|
78
|
+
|
|
79
|
+
description: str
|
|
80
|
+
"""A description of what the function does, used by the model to choose
|
|
81
|
+
when and how to call the function.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
parameters: Union[FunctionParameters, Dict[str, Any]]
|
|
85
|
+
"""The parameters the functions accepts, described as a JSON Schema object.
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Tool(BaseModel):
|
|
91
|
+
"""
|
|
92
|
+
Model class for assistant prompt message tool call.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
type: Optional[str] = None
|
|
96
|
+
"""The type of the tool. Currently, only `function` is supported."""
|
|
97
|
+
|
|
98
|
+
function: Optional[FunctionTool] = None
|
|
99
|
+
"""The function that the model called."""
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class FunctionCall(BaseModel):
|
|
103
|
+
"""
|
|
104
|
+
Model class for assistant prompt message tool call function.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
call_id: Optional[str] = None
|
|
108
|
+
"""The ID of the tool call."""
|
|
109
|
+
|
|
110
|
+
name: Optional[str] = None
|
|
111
|
+
"""The name of the function to call."""
|
|
112
|
+
|
|
113
|
+
arguments: Optional[str] = None
|
|
114
|
+
"""The arguments to call the function with, as generated by the model in
|
|
115
|
+
JSON format.
|
|
116
|
+
|
|
117
|
+
Note that the model does not always generate valid JSON, and may
|
|
118
|
+
hallucinate parameters not defined by your function schema. Validate
|
|
119
|
+
the arguments in your code before calling your function.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class FunctionCallOutput(BaseModel):
|
|
124
|
+
"""
|
|
125
|
+
Model class for assistant prompt message tool call function.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
call_id: str
|
|
129
|
+
"""The ID of the tool call."""
|
|
130
|
+
|
|
131
|
+
output: str
|
|
132
|
+
"""The result of the function."""
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class Error(BaseModel):
|
|
136
|
+
code: str
|
|
137
|
+
"""The error code of the message."""
|
|
138
|
+
|
|
139
|
+
message: str
|
|
140
|
+
"""The error message of the message."""
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class Event(BaseModel):
|
|
144
|
+
sequence_number: Optional[str] = None
|
|
145
|
+
"""sequence number of event"""
|
|
146
|
+
|
|
147
|
+
object: str
|
|
148
|
+
"""The identity of the content part."""
|
|
149
|
+
|
|
150
|
+
status: Optional[str] = None
|
|
151
|
+
"""The status of the message. in_progress, completed, or incomplete"""
|
|
152
|
+
|
|
153
|
+
error: Optional[Error] = None
|
|
154
|
+
"""response error for output"""
|
|
155
|
+
|
|
156
|
+
def created(self) -> Self:
|
|
157
|
+
"""
|
|
158
|
+
Set the message status to 'created'.
|
|
159
|
+
"""
|
|
160
|
+
self.status = RunStatus.Created
|
|
161
|
+
return self
|
|
162
|
+
|
|
163
|
+
def in_progress(self) -> Self:
|
|
164
|
+
"""
|
|
165
|
+
Set the message status to 'in_progress'.
|
|
166
|
+
"""
|
|
167
|
+
self.status = RunStatus.InProgress
|
|
168
|
+
return self
|
|
169
|
+
|
|
170
|
+
def completed(self) -> Self:
|
|
171
|
+
"""
|
|
172
|
+
Set the message status to 'completed'.
|
|
173
|
+
"""
|
|
174
|
+
self.status = RunStatus.Completed
|
|
175
|
+
return self
|
|
176
|
+
|
|
177
|
+
def failed(self, error: Error) -> Self:
|
|
178
|
+
"""
|
|
179
|
+
Set the message status to 'failed'.
|
|
180
|
+
"""
|
|
181
|
+
self.status = RunStatus.Failed
|
|
182
|
+
self.error = error
|
|
183
|
+
return self
|
|
184
|
+
|
|
185
|
+
def rejected(self) -> Self:
|
|
186
|
+
"""
|
|
187
|
+
Set the message status to 'rejected'.
|
|
188
|
+
"""
|
|
189
|
+
self.status = RunStatus.Rejected
|
|
190
|
+
return self
|
|
191
|
+
|
|
192
|
+
def canceled(self) -> Self:
|
|
193
|
+
"""
|
|
194
|
+
Set the message status to 'canceled'.
|
|
195
|
+
"""
|
|
196
|
+
self.status = RunStatus.Canceled
|
|
197
|
+
return self
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class Content(Event):
|
|
201
|
+
type: str
|
|
202
|
+
"""The type of the content part."""
|
|
203
|
+
|
|
204
|
+
object: str = "content"
|
|
205
|
+
"""The identity of the content part."""
|
|
206
|
+
|
|
207
|
+
index: Optional[int] = None
|
|
208
|
+
"""the content index in message's content list"""
|
|
209
|
+
|
|
210
|
+
delta: Optional[bool] = False
|
|
211
|
+
"""Whether this content is a delta."""
|
|
212
|
+
|
|
213
|
+
msg_id: str = None
|
|
214
|
+
"""message unique id"""
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class ImageContent(Content):
|
|
218
|
+
type: str = ContentType.IMAGE
|
|
219
|
+
"""The type of the content part."""
|
|
220
|
+
|
|
221
|
+
image_url: Optional[str] = None
|
|
222
|
+
"""The image URL details."""
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class TextContent(Content):
|
|
226
|
+
type: str = ContentType.TEXT
|
|
227
|
+
"""The type of the content part."""
|
|
228
|
+
|
|
229
|
+
text: Optional[str] = None
|
|
230
|
+
"""The text content."""
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class DataContent(Content):
|
|
234
|
+
type: str = ContentType.DATA
|
|
235
|
+
"""The type of the content part."""
|
|
236
|
+
|
|
237
|
+
data: Optional[Dict] = None
|
|
238
|
+
"""The data content."""
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class Message(Event):
|
|
242
|
+
id: str = Field(default_factory=lambda: "msg_" + str(uuid4()))
|
|
243
|
+
"""message unique id"""
|
|
244
|
+
|
|
245
|
+
object: str = "message"
|
|
246
|
+
"""message identity"""
|
|
247
|
+
|
|
248
|
+
type: str = "message"
|
|
249
|
+
"""The type of the message."""
|
|
250
|
+
|
|
251
|
+
status: str = RunStatus.Created
|
|
252
|
+
"""The status of the message. in_progress, completed, or incomplete"""
|
|
253
|
+
|
|
254
|
+
role: Optional[str] = None
|
|
255
|
+
"""The role of the messages author, should be in `user`,`system`,
|
|
256
|
+
'assistant'."""
|
|
257
|
+
|
|
258
|
+
content: Optional[
|
|
259
|
+
List[Union[TextContent, ImageContent, DataContent]]
|
|
260
|
+
] = None
|
|
261
|
+
"""The contents of the message."""
|
|
262
|
+
|
|
263
|
+
code: Optional[str] = None
|
|
264
|
+
"""The error code of the message."""
|
|
265
|
+
|
|
266
|
+
message: Optional[str] = None
|
|
267
|
+
"""The error message of the message."""
|
|
268
|
+
|
|
269
|
+
def add_delta_content(
|
|
270
|
+
self,
|
|
271
|
+
new_content: Union[TextContent, ImageContent, DataContent],
|
|
272
|
+
):
|
|
273
|
+
self.content = self.content or []
|
|
274
|
+
|
|
275
|
+
# new content
|
|
276
|
+
if new_content.index is None:
|
|
277
|
+
copy = deepcopy(new_content)
|
|
278
|
+
copy.delta = None
|
|
279
|
+
copy.index = None
|
|
280
|
+
copy.msg_id = None
|
|
281
|
+
self.content.append(copy)
|
|
282
|
+
|
|
283
|
+
new_content.index = len(self.content) - 1
|
|
284
|
+
new_content.msg_id = self.id
|
|
285
|
+
new_content.in_progress()
|
|
286
|
+
return new_content
|
|
287
|
+
|
|
288
|
+
# delta content
|
|
289
|
+
if new_content.delta is True:
|
|
290
|
+
# append the content
|
|
291
|
+
pre_content = self.content[new_content.index]
|
|
292
|
+
_type = pre_content.type
|
|
293
|
+
|
|
294
|
+
# append text
|
|
295
|
+
if _type == ContentType.TEXT:
|
|
296
|
+
pre_content.text += new_content.text
|
|
297
|
+
|
|
298
|
+
# append image_url
|
|
299
|
+
if _type == ContentType.IMAGE:
|
|
300
|
+
pre_content.image_url += new_content.image_url
|
|
301
|
+
|
|
302
|
+
# append data
|
|
303
|
+
if _type == ContentType.DATA:
|
|
304
|
+
for key in new_content.data:
|
|
305
|
+
if (
|
|
306
|
+
key in pre_content.data
|
|
307
|
+
and isinstance(pre_content.data[key], (list, str))
|
|
308
|
+
and isinstance(
|
|
309
|
+
new_content.data[key],
|
|
310
|
+
type(pre_content.data[key]),
|
|
311
|
+
)
|
|
312
|
+
):
|
|
313
|
+
if isinstance(pre_content.data[key], list):
|
|
314
|
+
pre_content.data[key].extend(new_content.data[key])
|
|
315
|
+
elif isinstance(pre_content.data[key], str):
|
|
316
|
+
pre_content.data[key] += new_content.data[key]
|
|
317
|
+
new_content.msg_id = self.id
|
|
318
|
+
new_content.in_progress()
|
|
319
|
+
return new_content
|
|
320
|
+
|
|
321
|
+
return None
|
|
322
|
+
|
|
323
|
+
def content_completed(self, content_index: int):
|
|
324
|
+
if self.content is None:
|
|
325
|
+
return None
|
|
326
|
+
if content_index >= len(self.content):
|
|
327
|
+
return None
|
|
328
|
+
else:
|
|
329
|
+
content = self.content[content_index]
|
|
330
|
+
new_content = deepcopy(content)
|
|
331
|
+
new_content.delta = False
|
|
332
|
+
new_content.index = content_index
|
|
333
|
+
new_content.msg_id = self.id
|
|
334
|
+
new_content.completed()
|
|
335
|
+
return new_content
|
|
336
|
+
|
|
337
|
+
def add_content(
|
|
338
|
+
self,
|
|
339
|
+
new_content: Union[TextContent, ImageContent, DataContent],
|
|
340
|
+
):
|
|
341
|
+
self.content = self.content or []
|
|
342
|
+
|
|
343
|
+
# new content
|
|
344
|
+
if new_content.index is None:
|
|
345
|
+
copy = deepcopy(new_content)
|
|
346
|
+
self.content.append(copy)
|
|
347
|
+
|
|
348
|
+
new_content.index = len(self.content) - 1
|
|
349
|
+
new_content.msg_id = self.id
|
|
350
|
+
new_content.completed()
|
|
351
|
+
return new_content
|
|
352
|
+
|
|
353
|
+
return None
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class BaseRequest(BaseModel):
|
|
357
|
+
"""agent request"""
|
|
358
|
+
|
|
359
|
+
input: List[Message]
|
|
360
|
+
"""
|
|
361
|
+
input messages
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
stream: bool = True
|
|
365
|
+
"""If set, partial message deltas will be sent, like in ChatGPT. """
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class AgentRequest(BaseRequest):
|
|
369
|
+
"""agent request"""
|
|
370
|
+
|
|
371
|
+
model: Optional[str] = None
|
|
372
|
+
"""
|
|
373
|
+
model id
|
|
374
|
+
"""
|
|
375
|
+
|
|
376
|
+
top_p: Optional[float] = None
|
|
377
|
+
"""Nucleus sampling, between (0, 1.0], where the model considers the
|
|
378
|
+
results of the tokens with top_p probability mass.
|
|
379
|
+
|
|
380
|
+
So 0.1 means only the tokens comprising the top 10% probability mass are
|
|
381
|
+
considered.
|
|
382
|
+
|
|
383
|
+
We generally recommend altering this or `temperature` but not both.
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
temperature: Optional[float] = None
|
|
387
|
+
"""What sampling temperature to use, between 0 and 2.
|
|
388
|
+
|
|
389
|
+
Higher values like 0.8 will make the output more random, while lower values
|
|
390
|
+
like 0.2 will make it more focused and deterministic.
|
|
391
|
+
|
|
392
|
+
We generally recommend altering this or `top_p` but not both.
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
frequency_penalty: Optional[float] = None
|
|
396
|
+
"""Positive values penalize new tokens based on their existing frequency in
|
|
397
|
+
the text so far, decreasing the model's likelihood to repeat the same line
|
|
398
|
+
verbatim.
|
|
399
|
+
|
|
400
|
+
"""
|
|
401
|
+
|
|
402
|
+
presence_penalty: Optional[float] = None
|
|
403
|
+
"""Number between -2.0 and 2.0.
|
|
404
|
+
|
|
405
|
+
Positive values penalize new tokens based on whether they appear in the
|
|
406
|
+
text so far, increasing the model's likelihood to talk about new topics.
|
|
407
|
+
|
|
408
|
+
"""
|
|
409
|
+
|
|
410
|
+
max_tokens: Optional[int] = None
|
|
411
|
+
"""The maximum number of [tokens](/tokenizer) that can be generated in the
|
|
412
|
+
chat completion.
|
|
413
|
+
|
|
414
|
+
The total length of input tokens and generated tokens is limited by the
|
|
415
|
+
model's context length.
|
|
416
|
+
"""
|
|
417
|
+
|
|
418
|
+
stop: Optional[Union[Optional[str], List[str]]] = None
|
|
419
|
+
"""Up to 4 sequences where the API will stop generating further tokens."""
|
|
420
|
+
|
|
421
|
+
n: Optional[int] = Field(default=1, ge=1, le=5)
|
|
422
|
+
"""How many chat completion choices to generate for each input message.
|
|
423
|
+
|
|
424
|
+
Note that you will be charged based on the number of generated tokens
|
|
425
|
+
across all of the choices. Keep `n` as `1` to minimize costs.
|
|
426
|
+
"""
|
|
427
|
+
|
|
428
|
+
seed: Optional[int] = None
|
|
429
|
+
"""If specified, system will make a best effort to sample
|
|
430
|
+
deterministically, such that repeated requests with the same `seed` and
|
|
431
|
+
parameters should return the same result.
|
|
432
|
+
"""
|
|
433
|
+
|
|
434
|
+
tools: Optional[List[Union[Tool, Dict]]] = None
|
|
435
|
+
"""
|
|
436
|
+
tool call list
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
session_id: Optional[str] = None
|
|
440
|
+
"""conversation id for dialog"""
|
|
441
|
+
|
|
442
|
+
response_id: Optional[str] = None
|
|
443
|
+
"""response unique id"""
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class BaseResponse(Event):
|
|
447
|
+
id: Optional[str] = Field(
|
|
448
|
+
default_factory=lambda: "response_"
|
|
449
|
+
+ str(
|
|
450
|
+
uuid4(),
|
|
451
|
+
),
|
|
452
|
+
)
|
|
453
|
+
"""response unique id"""
|
|
454
|
+
|
|
455
|
+
@field_validator("id", mode="before")
|
|
456
|
+
@classmethod
|
|
457
|
+
def validate_id(cls, v):
|
|
458
|
+
if v is None:
|
|
459
|
+
return "response_" + str(uuid4())
|
|
460
|
+
return v
|
|
461
|
+
|
|
462
|
+
object: str = "response"
|
|
463
|
+
"""response identity"""
|
|
464
|
+
|
|
465
|
+
status: str = RunStatus.Created
|
|
466
|
+
"""response run status"""
|
|
467
|
+
|
|
468
|
+
created_at: int = int(datetime.now().timestamp())
|
|
469
|
+
"""request start time"""
|
|
470
|
+
|
|
471
|
+
completed_at: Optional[int] = None
|
|
472
|
+
"""request completed time"""
|
|
473
|
+
|
|
474
|
+
output: Optional[List[Message]] = None
|
|
475
|
+
"""response data for output"""
|
|
476
|
+
|
|
477
|
+
usage: Optional[Dict] = None
|
|
478
|
+
"""response usage for output"""
|
|
479
|
+
|
|
480
|
+
def add_new_message(self, message: Message):
|
|
481
|
+
self.output = self.output or []
|
|
482
|
+
self.output.append(message)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class AgentResponse(BaseResponse):
|
|
486
|
+
"""agent response"""
|
|
487
|
+
|
|
488
|
+
session_id: Optional[str] = None
|
|
489
|
+
"""conversation id for dialog"""
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def convert_to_openai_tool_call(function: FunctionCall):
|
|
493
|
+
return {
|
|
494
|
+
"id": function.get("call_id", None),
|
|
495
|
+
"type": "function",
|
|
496
|
+
"function": {
|
|
497
|
+
"name": function.get("name", None),
|
|
498
|
+
"arguments": function.get("arguments", None),
|
|
499
|
+
},
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def convert_to_openai_messages(messages: List[Message]) -> list:
|
|
504
|
+
"""
|
|
505
|
+
Convert a generic message protocol to a model-specific protocol.
|
|
506
|
+
Args:
|
|
507
|
+
messages: Original list of messages
|
|
508
|
+
Returns:
|
|
509
|
+
list: Message format required by the model
|
|
510
|
+
"""
|
|
511
|
+
converted = []
|
|
512
|
+
for msg in messages:
|
|
513
|
+
if MessageType.MESSAGE == msg.type:
|
|
514
|
+
converted.append(
|
|
515
|
+
{
|
|
516
|
+
"role": msg.role,
|
|
517
|
+
"content": [c.model_dump() for c in msg.content],
|
|
518
|
+
},
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
if MessageType.FUNCTION_CALL == msg.type:
|
|
522
|
+
converted.append(
|
|
523
|
+
{
|
|
524
|
+
"role": Role.ASSISTANT,
|
|
525
|
+
"tool_calls": [
|
|
526
|
+
convert_to_openai_tool_call(c.data)
|
|
527
|
+
for c in msg.content
|
|
528
|
+
],
|
|
529
|
+
},
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
if MessageType.FUNCTION_CALL_OUTPUT == msg.type:
|
|
533
|
+
for function_call_output in msg.content:
|
|
534
|
+
converted.append(
|
|
535
|
+
{
|
|
536
|
+
"role": "tool",
|
|
537
|
+
"tool_call_id": function_call_output.data.get(
|
|
538
|
+
"call_id",
|
|
539
|
+
),
|
|
540
|
+
"content": function_call_output.data.get("output"),
|
|
541
|
+
},
|
|
542
|
+
)
|
|
543
|
+
return converted
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def convert_to_openai_tools(tools: List[Union[Tool, Dict]]) -> Optional[list]:
|
|
547
|
+
if not tools:
|
|
548
|
+
return None
|
|
549
|
+
return [
|
|
550
|
+
tool.model_dump() if isinstance(tool, Tool) else tool for tool in tools
|
|
551
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from typing import Optional, List, Dict
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, ConfigDict
|
|
5
|
+
|
|
6
|
+
from .agent_schemas import AgentRequest
|
|
7
|
+
from .agent_schemas import Message
|
|
8
|
+
from ..agents.base_agent import Agent
|
|
9
|
+
from ..services.context_manager import ContextManager
|
|
10
|
+
|
|
11
|
+
from ..services.session_history_service import (
|
|
12
|
+
Session,
|
|
13
|
+
)
|
|
14
|
+
from ..services.environment_manager import EnvironmentManager
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Context(BaseModel):
|
|
18
|
+
"""
|
|
19
|
+
Holds all contextual information for a single agent invocation.
|
|
20
|
+
|
|
21
|
+
This object is created by the Runner and passed through the agent
|
|
22
|
+
execution flow, providing access to necessary services and data,
|
|
23
|
+
including a live request queue for real-time interaction.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
model_config = ConfigDict(
|
|
27
|
+
arbitrary_types_allowed=True,
|
|
28
|
+
extra="forbid",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Core context
|
|
32
|
+
user_id: str
|
|
33
|
+
session: Session = Session(id="", user_id="")
|
|
34
|
+
activate_tools: list = []
|
|
35
|
+
new_message: Optional[Message] = None
|
|
36
|
+
current_messages: List[Message] = []
|
|
37
|
+
request: AgentRequest
|
|
38
|
+
new_message_dict: Optional[Dict] = None
|
|
39
|
+
messages_list: List[Dict] = []
|
|
40
|
+
|
|
41
|
+
# Services available to the agent
|
|
42
|
+
|
|
43
|
+
environment_manager: Optional[EnvironmentManager] = None
|
|
44
|
+
context_manager: Optional[ContextManager] = None
|
|
45
|
+
# Agent specific config
|
|
46
|
+
agent: Agent
|
|
47
|
+
agent_config: Optional[dict] = None
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def messages(self):
|
|
51
|
+
if self.new_message_dict:
|
|
52
|
+
return self.messages_list + [self.new_message_dict]
|
|
53
|
+
else:
|
|
54
|
+
return self.messages_list
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from .base import (
|
|
3
|
+
Service,
|
|
4
|
+
ServiceWithLifecycleManager,
|
|
5
|
+
ServiceLifecycleManagerMixin,
|
|
6
|
+
)
|
|
7
|
+
from .sandbox_service import SandboxService
|
|
8
|
+
from .memory_service import MemoryService
|
|
9
|
+
from .session_history_service import SessionHistoryService
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Service(ABC):
|
|
6
|
+
"""Abstract base class for services.
|
|
7
|
+
|
|
8
|
+
This class defines the interface that all services must implement.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
async def start(self) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Starts the service, initializing any necessary resources or
|
|
15
|
+
connections.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
async def stop(self) -> None:
|
|
20
|
+
"""Stops the service, releasing any acquired resources."""
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
async def health(self) -> bool:
|
|
24
|
+
"""
|
|
25
|
+
Checks the health of the service.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
True if the service is healthy, False otherwise.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ServiceLifecycleManagerMixin:
|
|
33
|
+
"""Mixin class that provides async lifecycle manager functionality for
|
|
34
|
+
services.
|
|
35
|
+
|
|
36
|
+
This mixin can be used with any class that implements the Service
|
|
37
|
+
interface.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
async def __aenter__(self):
|
|
41
|
+
"""Async context manager entry."""
|
|
42
|
+
await self.start()
|
|
43
|
+
return self
|
|
44
|
+
|
|
45
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
46
|
+
"""Async context manager exit."""
|
|
47
|
+
await self.stop()
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ServiceWithLifecycleManager(Service, ServiceLifecycleManagerMixin):
|
|
52
|
+
"""Base class for services that want async lifecycle manager functionality.
|
|
53
|
+
|
|
54
|
+
This class combines the Service interface with the context manager mixin,
|
|
55
|
+
providing a convenient base class for most service implementations.
|
|
56
|
+
|
|
57
|
+
Note: This is an abstract base class. Subclasses must implement the
|
|
58
|
+
abstract methods from the Service class.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
async def start(self) -> None:
|
|
63
|
+
"""Starts the service, initializing any necessary resources or
|
|
64
|
+
connections."""
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
async def stop(self) -> None:
|
|
68
|
+
"""Stops the service, releasing any acquired resources."""
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
async def health(self) -> bool:
|
|
72
|
+
"""
|
|
73
|
+
Checks the health of the service.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
True if the service is healthy, False otherwise.
|
|
77
|
+
"""
|