agentscope-runtime 0.2.0b2__py3-none-any.whl → 1.0.0b1__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 (183) hide show
  1. agentscope_runtime/adapters/__init__.py +0 -0
  2. agentscope_runtime/adapters/agentscope/__init__.py +0 -0
  3. agentscope_runtime/adapters/agentscope/long_term_memory/__init__.py +6 -0
  4. agentscope_runtime/adapters/agentscope/long_term_memory/_long_term_memory_adapter.py +258 -0
  5. agentscope_runtime/adapters/agentscope/memory/__init__.py +6 -0
  6. agentscope_runtime/adapters/agentscope/memory/_memory_adapter.py +152 -0
  7. agentscope_runtime/adapters/agentscope/message.py +535 -0
  8. agentscope_runtime/adapters/agentscope/stream.py +474 -0
  9. agentscope_runtime/adapters/agentscope/tool/__init__.py +9 -0
  10. agentscope_runtime/adapters/agentscope/tool/sandbox_tool.py +69 -0
  11. agentscope_runtime/adapters/agentscope/tool/tool.py +233 -0
  12. agentscope_runtime/adapters/autogen/__init__.py +0 -0
  13. agentscope_runtime/adapters/autogen/tool/__init__.py +7 -0
  14. agentscope_runtime/adapters/autogen/tool/tool.py +211 -0
  15. agentscope_runtime/adapters/text/__init__.py +0 -0
  16. agentscope_runtime/adapters/text/stream.py +29 -0
  17. agentscope_runtime/common/collections/redis_mapping.py +4 -1
  18. agentscope_runtime/common/container_clients/fc_client.py +855 -0
  19. agentscope_runtime/common/utils/__init__.py +0 -0
  20. agentscope_runtime/common/utils/lazy_loader.py +57 -0
  21. agentscope_runtime/engine/__init__.py +25 -18
  22. agentscope_runtime/engine/app/agent_app.py +161 -91
  23. agentscope_runtime/engine/app/base_app.py +4 -118
  24. agentscope_runtime/engine/constant.py +8 -0
  25. agentscope_runtime/engine/deployers/__init__.py +8 -0
  26. agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
  27. agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
  28. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
  29. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
  30. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
  31. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
  32. agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
  33. agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
  34. agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
  35. agentscope_runtime/engine/deployers/local_deployer.py +47 -74
  36. agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
  37. agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
  38. agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
  39. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
  40. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
  41. agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
  42. agentscope_runtime/engine/deployers/utils/package.py +693 -0
  43. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
  44. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +256 -282
  45. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
  46. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
  47. agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
  48. agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
  49. agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
  50. agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
  51. agentscope_runtime/engine/helpers/runner.py +40 -0
  52. agentscope_runtime/engine/runner.py +170 -130
  53. agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
  54. agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
  55. agentscope_runtime/engine/schemas/oai_llm.py +23 -23
  56. agentscope_runtime/engine/schemas/response_api.py +65 -0
  57. agentscope_runtime/engine/schemas/session.py +24 -0
  58. agentscope_runtime/engine/services/__init__.py +0 -9
  59. agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
  60. agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
  61. agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
  62. agentscope_runtime/engine/services/memory/__init__.py +24 -0
  63. agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
  64. agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
  65. agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
  66. agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
  67. agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
  68. agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
  69. agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
  70. agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
  71. agentscope_runtime/engine/services/session_history/__init__.py +23 -0
  72. agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
  73. agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
  74. agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
  75. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
  76. agentscope_runtime/engine/tracing/base.py +10 -9
  77. agentscope_runtime/engine/tracing/message_util.py +1 -1
  78. agentscope_runtime/engine/tracing/tracing_util.py +7 -2
  79. agentscope_runtime/sandbox/__init__.py +10 -2
  80. agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
  81. agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
  82. agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
  83. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
  84. agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
  85. agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
  86. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
  87. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
  88. agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
  89. agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
  90. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
  91. agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
  92. agentscope_runtime/sandbox/client/http_client.py +1 -0
  93. agentscope_runtime/sandbox/enums.py +2 -0
  94. agentscope_runtime/sandbox/manager/sandbox_manager.py +18 -2
  95. agentscope_runtime/sandbox/manager/server/app.py +12 -0
  96. agentscope_runtime/sandbox/manager/server/config.py +19 -0
  97. agentscope_runtime/sandbox/model/manager_config.py +79 -2
  98. agentscope_runtime/sandbox/utils.py +0 -18
  99. agentscope_runtime/tools/RAGs/__init__.py +0 -0
  100. agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
  101. agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
  102. agentscope_runtime/tools/__init__.py +119 -0
  103. agentscope_runtime/tools/_constants.py +18 -0
  104. agentscope_runtime/tools/alipay/__init__.py +4 -0
  105. agentscope_runtime/tools/alipay/base.py +334 -0
  106. agentscope_runtime/tools/alipay/payment.py +835 -0
  107. agentscope_runtime/tools/alipay/subscribe.py +551 -0
  108. agentscope_runtime/tools/base.py +264 -0
  109. agentscope_runtime/tools/cli/__init__.py +0 -0
  110. agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
  111. agentscope_runtime/tools/generations/__init__.py +75 -0
  112. agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
  113. agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
  114. agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
  115. agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
  116. agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
  117. agentscope_runtime/tools/generations/image_edit.py +208 -0
  118. agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
  119. agentscope_runtime/tools/generations/image_generation.py +202 -0
  120. agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
  121. agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
  122. agentscope_runtime/tools/generations/image_to_video.py +233 -0
  123. agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
  124. agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
  125. agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
  126. agentscope_runtime/tools/generations/speech_to_text.py +260 -0
  127. agentscope_runtime/tools/generations/speech_to_video.py +314 -0
  128. agentscope_runtime/tools/generations/text_to_video.py +221 -0
  129. agentscope_runtime/tools/mcp_wrapper.py +215 -0
  130. agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
  131. agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
  132. agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
  133. agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
  134. agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
  135. agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
  136. agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
  137. agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
  138. agentscope_runtime/tools/searches/__init__.py +3 -0
  139. agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
  140. agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
  141. agentscope_runtime/tools/utils/__init__.py +0 -0
  142. agentscope_runtime/tools/utils/api_key_util.py +45 -0
  143. agentscope_runtime/tools/utils/crypto_utils.py +99 -0
  144. agentscope_runtime/tools/utils/mcp_util.py +35 -0
  145. agentscope_runtime/version.py +1 -1
  146. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/METADATA +234 -165
  147. agentscope_runtime-1.0.0b1.dist-info/RECORD +240 -0
  148. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/entry_points.txt +1 -0
  149. agentscope_runtime/engine/agents/__init__.py +0 -2
  150. agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
  151. agentscope_runtime/engine/agents/agno_agent.py +0 -220
  152. agentscope_runtime/engine/agents/autogen_agent.py +0 -250
  153. agentscope_runtime/engine/agents/base_agent.py +0 -29
  154. agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
  155. agentscope_runtime/engine/agents/utils.py +0 -53
  156. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
  157. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  158. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  159. agentscope_runtime/engine/helpers/helper.py +0 -179
  160. agentscope_runtime/engine/schemas/context.py +0 -54
  161. agentscope_runtime/engine/services/context_manager.py +0 -164
  162. agentscope_runtime/engine/services/environment_manager.py +0 -50
  163. agentscope_runtime/engine/services/manager.py +0 -174
  164. agentscope_runtime/engine/services/rag_service.py +0 -195
  165. agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
  166. agentscope_runtime/sandbox/tools/__init__.py +0 -12
  167. agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
  168. agentscope_runtime/sandbox/tools/base/tool.py +0 -52
  169. agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
  170. agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
  171. agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
  172. agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
  173. agentscope_runtime/sandbox/tools/function_tool.py +0 -321
  174. agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
  175. agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
  176. agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
  177. agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
  178. agentscope_runtime/sandbox/tools/tool.py +0 -238
  179. agentscope_runtime/sandbox/tools/utils.py +0 -68
  180. agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
  181. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/WHEEL +0 -0
  182. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
  183. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/top_level.txt +0 -0
@@ -1,488 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # pylint:disable=too-many-nested-blocks, too-many-branches, too-many-statements
3
- # pylint:disable=line-too-long, protected-access
4
- import copy
5
- import logging
6
- import json
7
- import traceback
8
- from functools import partial
9
- from typing import Optional, Type, List
10
-
11
- from agentscope import setup_logger
12
- from agentscope.agent import AgentBase, ReActAgent
13
- from agentscope.formatter import (
14
- FormatterBase,
15
- DashScopeChatFormatter,
16
- OpenAIChatFormatter,
17
- AnthropicChatFormatter,
18
- OllamaChatFormatter,
19
- GeminiChatFormatter,
20
- )
21
- from agentscope.memory import InMemoryMemory
22
- from agentscope.message import (
23
- Msg,
24
- ToolUseBlock,
25
- ToolResultBlock,
26
- TextBlock,
27
- ImageBlock,
28
- AudioBlock,
29
- # VideoBlock, # TODO: support
30
- URLSource,
31
- Base64Source,
32
- )
33
- from agentscope.model import (
34
- ChatModelBase,
35
- DashScopeChatModel,
36
- OpenAIChatModel,
37
- AnthropicChatModel,
38
- OllamaChatModel,
39
- GeminiChatModel,
40
- )
41
- from agentscope.pipeline import stream_printing_messages
42
- from agentscope.tool import (
43
- Toolkit,
44
- ToolResponse,
45
- )
46
- from agentscope.tool._toolkit import RegisteredToolFunction
47
-
48
-
49
- from .utils import build_agent
50
- from ..agents import Agent
51
- from ..schemas.agent_schemas import (
52
- Message,
53
- TextContent,
54
- DataContent,
55
- FunctionCall,
56
- FunctionCallOutput,
57
- MessageType,
58
- )
59
- from ..schemas.context import Context
60
-
61
- # Disable logging from agentscope
62
- setup_logger(level="CRITICAL")
63
- logger = logging.getLogger(__name__)
64
-
65
-
66
- class AgentScopeContextAdapter:
67
- def __init__(self, context: Context, attr: dict):
68
- self.context = context
69
- self.attr = attr
70
-
71
- # Adapted attribute
72
- self.toolkit = None
73
- self.model = None
74
- self.memory = None
75
- self.new_message = None
76
-
77
- async def initialize(self):
78
- self.model, self.formatter = await self.adapt_model()
79
- self.memory = await self.adapt_memory()
80
- self.new_message = await self.adapt_new_message()
81
- self.toolkit = await self.adapt_tools()
82
-
83
- async def adapt_memory(self):
84
- memory = self.attr["agent_config"].get("memory", InMemoryMemory())
85
- messages = []
86
-
87
- # Build context
88
- for msg in self.context.session.messages[:-1]: # Exclude the last one
89
- messages.append(AgentScopeContextAdapter.converter(msg))
90
-
91
- state_dict = {"content": [_.to_dict() for _ in messages]}
92
- memory.load_state_dict(state_dict)
93
-
94
- return memory
95
-
96
- @staticmethod
97
- def converter(message: Message) -> Msg:
98
- if message.role not in ["user", "system", "assistant"]:
99
- role_label = "user"
100
- else:
101
- role_label = message.role
102
-
103
- result = {
104
- "name": message.role,
105
- "role": role_label,
106
- "invocation_id": message.id,
107
- }
108
-
109
- if message.type in (
110
- MessageType.PLUGIN_CALL,
111
- MessageType.FUNCTION_CALL,
112
- ):
113
- # convert PLUGIN_CALL, FUNCTION_CALL to ToolUseBlock
114
- result["content"] = [
115
- ToolUseBlock(
116
- type="tool_use",
117
- id=message.content[0].data["call_id"],
118
- name=message.role,
119
- input=json.loads(message.content[0].data["arguments"]),
120
- ),
121
- ]
122
- elif message.type in (
123
- MessageType.PLUGIN_CALL_OUTPUT,
124
- MessageType.FUNCTION_CALL_OUTPUT,
125
- ):
126
- # convert PLUGIN_CALL_OUTPUT, FUNCTION_CALL_OUTPUT to
127
- # ToolResultBlock
128
- result["content"] = [
129
- ToolResultBlock(
130
- type="tool_result",
131
- id=message.content[0].data["call_id"],
132
- name=message.role,
133
- output=message.content[0].data["output"],
134
- ),
135
- ]
136
- else:
137
- type_mapping = {
138
- "text": (TextBlock, "text", None),
139
- "image": (ImageBlock, "image_url", True),
140
- "audio": (AudioBlock, "data", None),
141
- # "video": (VideoBlock, "video_url", True), # TODO: support
142
- }
143
-
144
- msg_content = []
145
- for cnt in message.content:
146
- cnt_type = cnt.type or "text"
147
-
148
- if cnt_type not in type_mapping:
149
- raise ValueError(f"Unsupported message type: {cnt_type}")
150
-
151
- block_cls, attr_name, is_url = type_mapping[cnt_type]
152
- value = getattr(cnt, attr_name)
153
- if cnt_type == "audio":
154
- from urllib.parse import urlparse
155
-
156
- result = urlparse(value)
157
- is_url = all([result.scheme, result.netloc])
158
- if is_url:
159
- url_source = URLSource(type="url", url=value)
160
- msg_content.append(
161
- block_cls(type=cnt_type, source=url_source),
162
- )
163
- else:
164
- if cnt_type == "audio":
165
- audio_format = getattr(cnt, "format")
166
- base64_source = Base64Source(
167
- type="base64",
168
- media_type=audio_format,
169
- data=value,
170
- )
171
- msg_content.append(
172
- block_cls(
173
- type=cnt_type,
174
- source=base64_source,
175
- ),
176
- )
177
- else:
178
- msg_content.append(
179
- block_cls(type=cnt_type, text=value),
180
- )
181
-
182
- result["content"] = msg_content
183
- return Msg(**result)
184
-
185
- async def adapt_new_message(self):
186
- last_message = self.context.session.messages[-1]
187
- return AgentScopeContextAdapter.converter(last_message)
188
-
189
- async def adapt_model(self):
190
- model = self.attr["model"]
191
-
192
- if hasattr(model, "stream"):
193
- model.stream = True
194
-
195
- formatter = self.attr["agent_config"].get("formatter")
196
- if formatter and isinstance(formatter, FormatterBase):
197
- return model, formatter
198
-
199
- if isinstance(model, OpenAIChatModel):
200
- formatter = OpenAIChatFormatter()
201
- elif isinstance(model, DashScopeChatModel):
202
- formatter = DashScopeChatFormatter()
203
- elif isinstance(model, AnthropicChatModel):
204
- formatter = AnthropicChatFormatter()
205
- elif isinstance(model, OllamaChatModel):
206
- formatter = OllamaChatFormatter()
207
- elif isinstance(model, GeminiChatModel):
208
- formatter = GeminiChatFormatter()
209
-
210
- return model, formatter
211
-
212
- async def adapt_tools(self):
213
- def func_wrapper(func, **kwargs):
214
- func_res = func(**kwargs)
215
- return ToolResponse(
216
- content=func_res["content"],
217
- )
218
-
219
- toolkit = self.attr["agent_config"].get("toolkit", Toolkit())
220
-
221
- # Deepcopy to avoid modify the original toolkit
222
- try:
223
- toolkit = copy.deepcopy(toolkit)
224
- except Exception as e:
225
- logger.warning(
226
- f"Failed to deepcopy toolkit for agent "
227
- f"'{self.attr.get('agent_config', {}).get('name')}' "
228
- f"Error: {e}\nTraceback:\n{traceback.format_exc()}",
229
- )
230
-
231
- tools = self.attr["tools"]
232
-
233
- # in case, tools is None and tools == []
234
- if not tools:
235
- return toolkit
236
-
237
- if self.context.activate_tools:
238
- # Only add activated tool
239
- activated_tools = self.context.activate_tools
240
- else:
241
- # Lazy import
242
- from ...sandbox.tools.utils import setup_tools
243
-
244
- activated_tools = setup_tools(
245
- tools=self.attr["tools"],
246
- environment_manager=self.context.environment_manager,
247
- session_id=self.context.session.id,
248
- user_id=self.context.session.user_id,
249
- include_schemas=False,
250
- )
251
-
252
- for tool in activated_tools:
253
- function = RegisteredToolFunction(
254
- name=tool.name,
255
- source="mcp_server",
256
- mcp_name=tool.tool_type,
257
- original_func=partial(
258
- func_wrapper,
259
- tool,
260
- ),
261
- json_schema=tool.schema,
262
- group="basic",
263
- )
264
- toolkit.tools[tool.name] = function
265
-
266
- return toolkit
267
-
268
-
269
- class AgentScopeAgent(Agent):
270
- def __init__(
271
- self,
272
- name: str,
273
- model: ChatModelBase,
274
- tools=None,
275
- agent_config=None,
276
- agent_builder: Optional[Type[AgentBase]] = ReActAgent,
277
- ):
278
- super().__init__(name=name, agent_config=agent_config)
279
- assert isinstance(
280
- model,
281
- ChatModelBase,
282
- ), "model must be a subclass of ChatModelBase in AgentScope"
283
-
284
- # Set default agent_builder
285
- if agent_builder is None:
286
- agent_builder = ReActAgent
287
-
288
- assert issubclass(
289
- agent_builder,
290
- AgentBase,
291
- ), "agent_builder must be a subclass of AgentBase in AgentScope"
292
-
293
- # Replace name if not exists
294
- self.agent_config["name"] = self.agent_config.get("name") or name
295
-
296
- self._attr = {
297
- "model": model,
298
- "tools": tools,
299
- "agent_config": self.agent_config,
300
- "agent_builder": agent_builder,
301
- }
302
- self.tools = tools
303
-
304
- def copy(self) -> "AgentScopeAgent":
305
- return AgentScopeAgent(**self._attr)
306
-
307
- def build(self, as_context) -> AgentBase:
308
- params = {
309
- **self._attr["agent_config"],
310
- **{
311
- "model": as_context.model,
312
- "formatter": self._attr["agent_config"].get(
313
- "formatter",
314
- as_context.formatter,
315
- ),
316
- "memory": as_context.memory,
317
- "toolkit": as_context.toolkit,
318
- },
319
- }
320
-
321
- builder_cls = self._attr["agent_builder"]
322
- _agent = build_agent(builder_cls, params)
323
- _agent.set_console_output_enabled(False)
324
-
325
- return _agent
326
-
327
- async def run_async(
328
- self,
329
- context,
330
- **kwargs,
331
- ):
332
- as_context = AgentScopeContextAdapter(context=context, attr=self._attr)
333
- await as_context.initialize()
334
- local_truncate_memory = ""
335
-
336
- # We should always build a new agent since the state is manage outside
337
- # the agent
338
- _agent = self.build(as_context)
339
-
340
- # Yield new Msg instances as they are logged
341
- last_content = ""
342
-
343
- message = Message(type=MessageType.MESSAGE, role="assistant")
344
- should_start_message = True
345
- index = None
346
-
347
- # Run agent
348
- async for msg, last in stream_printing_messages(
349
- agents=[_agent],
350
- coroutine_task=_agent(as_context.new_message),
351
- ):
352
- # deepcopy required to avoid modifying the original message object
353
- # which may be used elsewhere in the streaming pipeline
354
- msg = copy.deepcopy(msg)
355
-
356
- # Filter out unfinished tool_use messages
357
- if not last:
358
- new_blocks = []
359
- if isinstance(msg.content, List):
360
- for block in msg.content:
361
- if block.get("type", "") != "tool_use":
362
- new_blocks.append(block)
363
- msg.content = new_blocks
364
-
365
- if not msg.content:
366
- continue
367
-
368
- # TODO: make this as a message converter
369
- content = msg.content
370
- if isinstance(content, str):
371
- last_content = content
372
- else:
373
- for element in content:
374
- if isinstance(element, str) and element:
375
- if should_start_message:
376
- yield message.in_progress()
377
- should_start_message = False
378
- text_delta_content = TextContent(
379
- delta=True,
380
- index=index,
381
- text=element,
382
- )
383
- text_delta_content = message.add_delta_content(
384
- new_content=text_delta_content,
385
- )
386
- index = text_delta_content.index
387
- yield text_delta_content
388
- elif isinstance(element, dict):
389
- if element.get("type") == "text":
390
- text = element.get(
391
- "text",
392
- "",
393
- )
394
- if text:
395
- if should_start_message:
396
- yield message.in_progress()
397
- should_start_message = False
398
- text_delta_content = TextContent(
399
- delta=True,
400
- index=index,
401
- text=text.removeprefix(
402
- local_truncate_memory,
403
- ),
404
- )
405
- local_truncate_memory = element.get(
406
- "text",
407
- "",
408
- )
409
- text_delta_content = message.add_delta_content(
410
- new_content=text_delta_content,
411
- )
412
- index = text_delta_content.index
413
-
414
- # Only yield valid text
415
- if text_delta_content.text:
416
- yield text_delta_content
417
-
418
- if last:
419
- yield message.completed()
420
- message = Message(
421
- type=MessageType.MESSAGE,
422
- role="assistant",
423
- )
424
- index = None
425
-
426
- elif element.get("type") == "tool_use":
427
- json_str = json.dumps(element.get("input"))
428
- data_delta_content = DataContent(
429
- index=index,
430
- data=FunctionCall(
431
- call_id=element.get("id"),
432
- name=element.get("name"),
433
- arguments=json_str,
434
- ).model_dump(),
435
- )
436
- plugin_call_message = Message(
437
- type=MessageType.PLUGIN_CALL,
438
- role="assistant",
439
- content=[data_delta_content],
440
- )
441
- yield plugin_call_message.completed()
442
- elif element.get("type") == "tool_result":
443
- data_delta_content = DataContent(
444
- index=index,
445
- data=FunctionCallOutput(
446
- call_id=element.get("id"),
447
- output=str(element.get("output")),
448
- ).model_dump(),
449
- )
450
- plugin_output_message = Message(
451
- type=MessageType.PLUGIN_CALL_OUTPUT,
452
- role="assistant",
453
- content=[data_delta_content],
454
- )
455
- yield plugin_output_message.completed()
456
- message = Message(
457
- type=MessageType.MESSAGE,
458
- role="assistant",
459
- )
460
- should_start_message = True
461
- else:
462
- if should_start_message:
463
- yield message.in_progress()
464
- should_start_message = False
465
- text_delta_content = TextContent(
466
- delta=True,
467
- index=index,
468
- text=f"{element}",
469
- )
470
- text_delta_content = message.add_delta_content(
471
- new_content=text_delta_content,
472
- )
473
- index = text_delta_content.index
474
- yield text_delta_content
475
-
476
- if last_content:
477
- if should_start_message:
478
- yield message.in_progress()
479
- text_delta_content = TextContent(
480
- delta=True,
481
- index=index,
482
- text=last_content,
483
- )
484
- text_delta_content = message.add_delta_content(
485
- new_content=text_delta_content,
486
- )
487
- yield text_delta_content
488
- yield message.completed()
@@ -1,220 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # pylint:disable=too-many-nested-blocks, too-many-branches, too-many-statements
3
- import json
4
- from typing import Optional, Type
5
-
6
- from agno.agent import Agent as AgAgent
7
- from agno.models.base import Model
8
- from agno.run.agent import (
9
- RunContentEvent,
10
- ToolCallStartedEvent,
11
- ToolCallCompletedEvent,
12
- )
13
- from agno.tools.function import Function
14
-
15
- from .utils import build_agent
16
- from ..agents import Agent
17
- from ..schemas.context import Context
18
- from ..schemas.agent_schemas import (
19
- Message,
20
- TextContent,
21
- DataContent,
22
- FunctionCall,
23
- FunctionCallOutput,
24
- MessageType,
25
- RunStatus,
26
- )
27
-
28
-
29
- class AgnoContextAdapter:
30
- def __init__(self, context: Context, attr: dict):
31
- self.context = context
32
- self.attr = attr
33
-
34
- # Adapted attribute
35
- self.toolkit = None
36
- self.model = None
37
- self.memory = None
38
- self.new_message = None
39
-
40
- async def initialize(self):
41
- self.model = await self.adapt_model()
42
- self.memory = await self.adapt_memory()
43
- self.new_message = await self.adapt_new_message()
44
- self.toolkit = await self.adapt_tools()
45
-
46
- async def adapt_memory(self):
47
- messages = []
48
-
49
- # Build context
50
- for msg in self.context.session.messages[:-1]: # Exclude the last one
51
- messages.append(AgnoContextAdapter.converter(msg))
52
-
53
- return messages
54
-
55
- @staticmethod
56
- def converter(message: Message):
57
- # TODO: support more message type
58
- return dict(message)
59
-
60
- async def adapt_new_message(self):
61
- last_message = self.context.session.messages[-1]
62
- return AgnoContextAdapter.converter(last_message)
63
-
64
- async def adapt_model(self):
65
- return self.attr["model"]
66
-
67
- async def adapt_tools(self):
68
- toolkit = self.attr["agent_config"].get("tools", [])
69
- tools = self.attr["tools"]
70
-
71
- # in case, tools is None and tools == []
72
- if not tools:
73
- return toolkit
74
-
75
- if self.context.activate_tools:
76
- # Only add activated tool
77
- activated_tools = self.context.activate_tools
78
- else:
79
- from ...sandbox.tools.utils import setup_tools
80
-
81
- activated_tools = setup_tools(
82
- tools=self.attr["tools"],
83
- environment_manager=self.context.environment_manager,
84
- session_id=self.context.session.id,
85
- user_id=self.context.session.user_id,
86
- include_schemas=False,
87
- )
88
-
89
- for tool in activated_tools:
90
- func = Function(
91
- name=tool.name,
92
- description=tool.schema["function"]["description"],
93
- parameters=tool.schema["function"]["parameters"],
94
- entrypoint=tool.__call__,
95
- )
96
- toolkit.append(func)
97
-
98
- return toolkit
99
-
100
-
101
- class AgnoAgent(Agent):
102
- def __init__(
103
- self,
104
- name: str,
105
- model: Model,
106
- tools=None,
107
- agent_config=None,
108
- agent_builder: Optional[Type[AgAgent]] = AgAgent,
109
- ):
110
- super().__init__(name=name, agent_config=agent_config)
111
-
112
- assert isinstance(
113
- model,
114
- Model,
115
- ), "model must be a subclass of Model in Agno"
116
-
117
- # Set default agent_builder
118
- if agent_builder is None:
119
- agent_builder = Agent
120
-
121
- assert issubclass(
122
- agent_builder,
123
- AgAgent,
124
- ), "agent_builder must be a subclass of Agent in Agno"
125
-
126
- # Replace name if not exists
127
- self.agent_config["name"] = self.agent_config.get("name") or name
128
-
129
- self._attr = {
130
- "model": model,
131
- "tools": tools,
132
- "agent_config": self.agent_config,
133
- "agent_builder": agent_builder,
134
- }
135
- self.tools = tools
136
-
137
- def copy(self) -> "AgnoAgent":
138
- return AgnoAgent(**self._attr)
139
-
140
- def build(self, as_context):
141
- params = {
142
- **self._attr["agent_config"],
143
- **{
144
- "model": as_context.model,
145
- "tools": as_context.toolkit,
146
- }, # Context will be added at `_agent.arun`
147
- }
148
-
149
- builder_cls = self._attr["agent_builder"]
150
- _agent = build_agent(builder_cls, params)
151
-
152
- return _agent
153
-
154
- async def run_async(
155
- self,
156
- context,
157
- **kwargs,
158
- ):
159
- ag_context = AgnoContextAdapter(context=context, attr=self._attr)
160
- await ag_context.initialize()
161
-
162
- # We should always build a new agent since the state is manage outside
163
- # the agent
164
- _agent = self.build(ag_context)
165
-
166
- text_message = Message(
167
- type=MessageType.MESSAGE,
168
- role="assistant",
169
- status=RunStatus.InProgress,
170
- )
171
- yield text_message
172
-
173
- text_delta_content = TextContent(delta=True)
174
- is_text_delta = False
175
- async for event in _agent.arun(
176
- ag_context.new_message,
177
- session_state=ag_context.memory,
178
- stream=True,
179
- ):
180
- if isinstance(event, RunContentEvent):
181
- is_text_delta = True
182
- text_delta_content.text = event.content
183
- text_delta_content = text_message.add_delta_content(
184
- new_content=text_delta_content,
185
- )
186
- yield text_delta_content
187
- elif isinstance(event, ToolCallStartedEvent):
188
- json_str = json.dumps(event.tool.tool_args)
189
- data = DataContent(
190
- data=FunctionCall(
191
- call_id=event.tool.tool_call_id,
192
- name=event.tool.tool_name,
193
- arguments=json_str,
194
- ).model_dump(),
195
- )
196
- message = Message(
197
- type=MessageType.PLUGIN_CALL,
198
- role="assistant",
199
- status=RunStatus.Completed,
200
- content=[data],
201
- )
202
- yield message
203
- elif isinstance(event, ToolCallCompletedEvent):
204
- data = DataContent(
205
- data=FunctionCallOutput(
206
- call_id=event.tool.tool_call_id,
207
- output=str(event.tool.result),
208
- ).model_dump(),
209
- )
210
- message = Message(
211
- type=MessageType.PLUGIN_CALL_OUTPUT,
212
- role="assistant",
213
- status=RunStatus.Completed,
214
- content=[data],
215
- )
216
- yield message
217
-
218
- if is_text_delta:
219
- yield text_message.content_completed(text_delta_content.index)
220
- yield text_message.completed()