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
@@ -0,0 +1,474 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint: disable=too-many-nested-blocks,too-many-branches,too-many-statements
3
+ import copy
4
+ import json
5
+
6
+ from typing import AsyncIterator, Tuple, List
7
+ from urllib.parse import urlparse
8
+
9
+ from agentscope.message import Msg
10
+
11
+ from ...engine.schemas.agent_schemas import (
12
+ Message,
13
+ TextContent,
14
+ ImageContent,
15
+ AudioContent,
16
+ DataContent,
17
+ FunctionCall,
18
+ FunctionCallOutput,
19
+ MessageType,
20
+ )
21
+
22
+
23
+ def _update_obj_attrs(obj, **attrs):
24
+ for key, value in attrs.items():
25
+ if hasattr(obj, key):
26
+ setattr(obj, key, value)
27
+ return obj
28
+
29
+
30
+ async def adapt_agentscope_message_stream(
31
+ source_stream: AsyncIterator[Tuple[Msg, bool]],
32
+ ) -> AsyncIterator[Message]:
33
+ # Initialize variables to avoid uncaught errors
34
+ msg_id = None
35
+ last_content = ""
36
+ metadata = None
37
+ usage = None
38
+ tool_start = False
39
+ message = Message(type=MessageType.MESSAGE, role="assistant")
40
+ reasoning_message = Message(
41
+ type=MessageType.REASONING,
42
+ role="assistant",
43
+ )
44
+ local_truncate_memory = ""
45
+ local_truncate_reasoning_memory = ""
46
+ should_start_message = True
47
+ should_start_reasoning_message = True
48
+ tool_use_messages_dict = {}
49
+ index = None
50
+
51
+ # Run agent
52
+ async for msg, last in source_stream:
53
+ # deepcopy required to avoid modifying the original message object
54
+ # which may be used elsewhere in the streaming pipeline
55
+ msg = copy.deepcopy(msg)
56
+
57
+ assert isinstance(msg, Msg), f"Expected Msg, got {type(msg)}"
58
+
59
+ # If a new message, create new Message
60
+ if msg.id != msg_id:
61
+ local_truncate_memory = ""
62
+ local_truncate_reasoning_memory = ""
63
+
64
+ # Yield new Msg instances as they are logged
65
+ last_content = ""
66
+
67
+ message = Message(type=MessageType.MESSAGE, role="assistant")
68
+ reasoning_message = Message(
69
+ type=MessageType.REASONING,
70
+ role="assistant",
71
+ )
72
+
73
+ should_start_message = True
74
+ should_start_reasoning_message = True
75
+
76
+ index = None
77
+
78
+ # Note: Tool use content only happens in the last of messages
79
+ tool_start = False
80
+
81
+ tool_use_messages_dict = {}
82
+
83
+ # Cache msg id
84
+ msg_id = msg.id
85
+
86
+ new_blocks = []
87
+ new_tool_blocks = []
88
+ if isinstance(msg.content, List):
89
+ for block in msg.content:
90
+ if block.get("type", "") != "tool_use":
91
+ new_blocks.append(block)
92
+ else:
93
+ new_tool_blocks.append(block)
94
+ if new_tool_blocks:
95
+ if tool_start:
96
+ msg.content = new_tool_blocks
97
+ else:
98
+ msg.content = new_blocks
99
+ tool_start = True
100
+
101
+ else:
102
+ msg.content = new_blocks
103
+
104
+ if not msg.content:
105
+ continue
106
+
107
+ # msg content
108
+ content = msg.content
109
+
110
+ # msg usage
111
+ usage = getattr(msg, "usage", None)
112
+
113
+ # msg metadata
114
+ metadata = msg.metadata
115
+
116
+ if isinstance(content, str):
117
+ last_content = content
118
+ else:
119
+ for element in content:
120
+ if isinstance(element, str) and element:
121
+ if should_start_message:
122
+ index = None
123
+ message = _update_obj_attrs(
124
+ message,
125
+ metadata=metadata,
126
+ usage=usage,
127
+ )
128
+ yield message.in_progress()
129
+ should_start_message = False
130
+ text_delta_content = TextContent(
131
+ delta=True,
132
+ index=index,
133
+ text=element,
134
+ )
135
+ text_delta_content = message.add_delta_content(
136
+ new_content=text_delta_content,
137
+ )
138
+ index = text_delta_content.index
139
+ yield text_delta_content
140
+ elif isinstance(element, dict):
141
+ if element.get("type") == "text": # Text
142
+ text = element.get(
143
+ "text",
144
+ "",
145
+ )
146
+ if text:
147
+ if should_start_message:
148
+ index = None
149
+ message = _update_obj_attrs(
150
+ message,
151
+ metadata=metadata,
152
+ usage=usage,
153
+ )
154
+ yield message.in_progress()
155
+ should_start_message = False
156
+
157
+ text_delta_content = TextContent(
158
+ delta=True,
159
+ index=index,
160
+ text=text.removeprefix(
161
+ local_truncate_memory,
162
+ ),
163
+ )
164
+ local_truncate_memory = element.get(
165
+ "text",
166
+ "",
167
+ )
168
+ text_delta_content = message.add_delta_content(
169
+ new_content=text_delta_content,
170
+ )
171
+ index = text_delta_content.index
172
+
173
+ # Only yield valid text
174
+ if text_delta_content.text:
175
+ yield text_delta_content
176
+
177
+ if last or tool_start:
178
+ completed_content = message.content[index]
179
+ if completed_content.text:
180
+ yield completed_content.completed()
181
+
182
+ message = _update_obj_attrs(
183
+ message,
184
+ metadata=metadata,
185
+ usage=usage,
186
+ )
187
+ yield message.completed()
188
+ message = Message(
189
+ type=MessageType.MESSAGE,
190
+ role="assistant",
191
+ )
192
+ index = None
193
+ should_start_message = True
194
+
195
+ elif element.get("type") == "thinking": # Thinking
196
+ reasoning = element.get(
197
+ "thinking",
198
+ "",
199
+ )
200
+ if reasoning:
201
+ if should_start_reasoning_message:
202
+ index = None
203
+ reasoning_message = _update_obj_attrs(
204
+ reasoning_message,
205
+ metadata=metadata,
206
+ usage=usage,
207
+ )
208
+ yield reasoning_message.in_progress()
209
+ should_start_reasoning_message = False
210
+ text_delta_content = TextContent(
211
+ delta=True,
212
+ index=index,
213
+ text=reasoning.removeprefix(
214
+ local_truncate_reasoning_memory,
215
+ ),
216
+ )
217
+ local_truncate_reasoning_memory = element.get(
218
+ "thinking",
219
+ "",
220
+ )
221
+ text_delta_content = (
222
+ reasoning_message.add_delta_content(
223
+ new_content=text_delta_content,
224
+ )
225
+ )
226
+ index = text_delta_content.index
227
+
228
+ # Only yield valid text
229
+ if text_delta_content.text:
230
+ yield text_delta_content
231
+
232
+ if last or tool_start:
233
+ completed_content = reasoning_message.content[
234
+ index
235
+ ]
236
+ if completed_content.text:
237
+ yield completed_content.completed()
238
+
239
+ reasoning_message = _update_obj_attrs(
240
+ reasoning_message,
241
+ metadata=metadata,
242
+ usage=usage,
243
+ )
244
+ yield reasoning_message.completed()
245
+ reasoning_message = Message(
246
+ type=MessageType.REASONING,
247
+ role="assistant",
248
+ )
249
+ index = None
250
+
251
+ elif element.get("type") == "tool_use": # Tool use
252
+ call_id = element.get("id")
253
+
254
+ if last:
255
+ plugin_call_message = tool_use_messages_dict[
256
+ call_id
257
+ ]
258
+ json_str = json.dumps(element.get("input"))
259
+ data_delta_content = DataContent(
260
+ index=index,
261
+ data=FunctionCall(
262
+ call_id=element.get("id"),
263
+ name=element.get("name"),
264
+ arguments=json_str,
265
+ ).model_dump(),
266
+ delta=True,
267
+ )
268
+ data_delta_content = (
269
+ plugin_call_message.add_delta_content(
270
+ new_content=data_delta_content,
271
+ )
272
+ )
273
+ yield data_delta_content.completed()
274
+ plugin_call_message = _update_obj_attrs(
275
+ plugin_call_message,
276
+ metadata=metadata,
277
+ usage=usage,
278
+ )
279
+ yield plugin_call_message.completed()
280
+ index = None
281
+ else:
282
+ if call_id in tool_use_messages_dict:
283
+ pass
284
+ else:
285
+ # Build a new tool call message
286
+ plugin_call_message = Message(
287
+ type=MessageType.PLUGIN_CALL,
288
+ role="assistant",
289
+ )
290
+
291
+ data_delta_content = DataContent(
292
+ index=index,
293
+ data=FunctionCall(
294
+ call_id=element.get("id"),
295
+ name=element.get("name"),
296
+ arguments="",
297
+ ).model_dump(),
298
+ delta=True,
299
+ )
300
+
301
+ plugin_call_message = _update_obj_attrs(
302
+ plugin_call_message,
303
+ metadata=metadata,
304
+ usage=usage,
305
+ )
306
+ yield plugin_call_message.in_progress()
307
+ data_delta_content = (
308
+ plugin_call_message.add_delta_content(
309
+ new_content=data_delta_content,
310
+ )
311
+ )
312
+ yield data_delta_content
313
+
314
+ tool_use_messages_dict[
315
+ call_id
316
+ ] = plugin_call_message
317
+
318
+ elif element.get("type") == "tool_result": # Tool result
319
+ json_str = json.dumps(
320
+ element.get("output"),
321
+ ensure_ascii=False,
322
+ )
323
+ data_delta_content = DataContent(
324
+ index=index,
325
+ data=FunctionCallOutput(
326
+ call_id=element.get("id"),
327
+ name=element.get("name"),
328
+ output=json_str,
329
+ ).model_dump(),
330
+ )
331
+ plugin_output_message = Message(
332
+ type=MessageType.PLUGIN_CALL_OUTPUT,
333
+ role="tool",
334
+ content=[data_delta_content],
335
+ )
336
+ plugin_output_message = _update_obj_attrs(
337
+ plugin_output_message,
338
+ metadata=metadata,
339
+ usage=usage,
340
+ )
341
+ yield plugin_output_message.completed()
342
+ message = Message(
343
+ type=MessageType.MESSAGE,
344
+ role="assistant",
345
+ )
346
+ should_start_message = True
347
+ index = None
348
+ else:
349
+ # TODO: handle image/audio/video block
350
+ if should_start_message:
351
+ index = None
352
+ message = _update_obj_attrs(
353
+ message,
354
+ metadata=metadata,
355
+ usage=usage,
356
+ )
357
+ yield message.in_progress()
358
+ should_start_message = False
359
+
360
+ if element.get("type") == "image":
361
+ kwargs = {}
362
+ if (
363
+ isinstance(element.get("source"), dict)
364
+ and element.get("source", {}).get(
365
+ "type",
366
+ )
367
+ == "url"
368
+ ):
369
+ kwargs.update(
370
+ {"image_url": element.get("source")},
371
+ )
372
+
373
+ elif (
374
+ isinstance(element.get("source"), dict)
375
+ and element.get("source").get(
376
+ "type",
377
+ )
378
+ == "base64"
379
+ ):
380
+ media_type = element.get("source", {}).get(
381
+ "media_type",
382
+ "image/jpeg",
383
+ )
384
+ base64_data = element.get("source", {}).get(
385
+ "data",
386
+ "",
387
+ )
388
+ url = f"data:{media_type};base64,{base64_data}"
389
+ kwargs.update({"image_url": url})
390
+ delta_content = ImageContent(
391
+ delta=True,
392
+ index=index,
393
+ **kwargs,
394
+ )
395
+ elif element.get("text") == "audio":
396
+ kwargs = {}
397
+ if (
398
+ isinstance(element.get("source"), dict)
399
+ and element.get("source", {}).get(
400
+ "type",
401
+ )
402
+ == "url"
403
+ ):
404
+ url = element.get("source", {}).get("url")
405
+ try:
406
+ _format = urlparse(url).path.split(".")[-1]
407
+ except (
408
+ AttributeError,
409
+ IndexError,
410
+ ValueError,
411
+ ):
412
+ _format = None
413
+ kwargs.update({"format": _format, "data": url})
414
+ # Base64Source runtime check (dict with type ==
415
+ # "base64")
416
+ elif (
417
+ isinstance(element.get("source"), dict)
418
+ and element.get("source").get(
419
+ "type",
420
+ )
421
+ == "base64"
422
+ ):
423
+ media_type = element.get("source", {}).get(
424
+ "media_type",
425
+ )
426
+ base64_data = element.get("source", {}).get(
427
+ "data",
428
+ "",
429
+ )
430
+ url = f"data:{media_type};base64,{base64_data}"
431
+ kwargs.update(
432
+ {"format": media_type, "data": url},
433
+ )
434
+ delta_content = AudioContent(
435
+ delta=True,
436
+ index=index,
437
+ **kwargs,
438
+ )
439
+ else:
440
+ delta_content = TextContent(
441
+ delta=True,
442
+ index=index,
443
+ text=f"{element}",
444
+ )
445
+ delta_content = message.add_delta_content(
446
+ new_content=delta_content,
447
+ )
448
+ index = delta_content.index
449
+ yield delta_content
450
+
451
+ if last_content:
452
+ if should_start_message:
453
+ index = None
454
+ message = _update_obj_attrs(
455
+ message,
456
+ metadata=metadata,
457
+ usage=usage,
458
+ )
459
+ yield message.in_progress()
460
+ text_delta_content = TextContent(
461
+ delta=True,
462
+ index=index,
463
+ text=last_content,
464
+ )
465
+ text_delta_content = message.add_delta_content(
466
+ new_content=text_delta_content,
467
+ )
468
+ yield text_delta_content
469
+ message = _update_obj_attrs(
470
+ message,
471
+ metadata=metadata,
472
+ usage=usage,
473
+ )
474
+ yield message.completed()
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .tool import agentscope_tool_adapter, agentscope_toolkit_adapter
3
+ from .sandbox_tool import sandbox_tool_adapter
4
+
5
+ __all__ = [
6
+ "agentscope_tool_adapter",
7
+ "agentscope_toolkit_adapter",
8
+ "sandbox_tool_adapter",
9
+ ]
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint: disable=protected-access
3
+ import logging
4
+ import functools
5
+
6
+ from mcp.types import CallToolResult
7
+ from agentscope.message import TextBlock
8
+ from agentscope.tool import ToolResponse
9
+ from agentscope.mcp import MCPClientBase
10
+
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def sandbox_tool_adapter(func):
16
+ """
17
+ Sandbox Tool Adapter.
18
+
19
+ Wraps a sandbox tool function so that its output is always converted
20
+ into a ToolResponse object, which is required by the Toolkit.
21
+
22
+ This adapter preserves the original function signature and docstring
23
+ so that JSON schemas can be correctly generated by the Toolkit.
24
+
25
+ Args:
26
+ func: Original sandbox tool function (may return dict, string, etc.).
27
+
28
+ Returns:
29
+ A callable that produces ToolResponse instead of raw data.
30
+ """
31
+
32
+ @functools.wraps(func)
33
+ def wrapper(*args, **kwargs):
34
+ res = func(*args, **kwargs)
35
+ if isinstance(res, ToolResponse):
36
+ return res
37
+
38
+ try:
39
+ mcp_res = CallToolResult.model_validate(res)
40
+ as_content = MCPClientBase._convert_mcp_content_to_as_blocks(
41
+ mcp_res.content,
42
+ )
43
+ resp = ToolResponse(
44
+ content=as_content,
45
+ metadata=mcp_res.meta,
46
+ )
47
+ return resp
48
+ except Exception as e:
49
+ logger.warning(
50
+ (
51
+ f"Failed to convert tool result to ToolResponse. "
52
+ f"Function: {func.__name__}, "
53
+ f"Args: {args}, "
54
+ f"Kwargs: {kwargs}, "
55
+ f"Result type: {type(res).__name__}, "
56
+ f"Result: {res!r}, "
57
+ f"Error: {e}"
58
+ ),
59
+ exc_info=True,
60
+ )
61
+ return ToolResponse(
62
+ content=[
63
+ TextBlock(
64
+ text=str(res),
65
+ ),
66
+ ],
67
+ )
68
+
69
+ return wrapper