agentscope-runtime 0.2.0b1__py3-none-any.whl → 1.0.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.
Files changed (185) 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 +506 -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/container_clients/kubernetes_client.py +6 -13
  20. agentscope_runtime/common/utils/__init__.py +0 -0
  21. agentscope_runtime/common/utils/lazy_loader.py +57 -0
  22. agentscope_runtime/engine/__init__.py +25 -18
  23. agentscope_runtime/engine/app/agent_app.py +161 -91
  24. agentscope_runtime/engine/app/base_app.py +4 -118
  25. agentscope_runtime/engine/constant.py +8 -0
  26. agentscope_runtime/engine/deployers/__init__.py +8 -0
  27. agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
  28. agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
  29. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
  30. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
  31. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
  32. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
  33. agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
  34. agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
  35. agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
  36. agentscope_runtime/engine/deployers/local_deployer.py +47 -74
  37. agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
  38. agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
  39. agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
  40. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
  41. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
  42. agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
  43. agentscope_runtime/engine/deployers/utils/package.py +693 -0
  44. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
  45. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +301 -282
  46. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
  47. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
  48. agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
  49. agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
  50. agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
  51. agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
  52. agentscope_runtime/engine/helpers/runner.py +40 -0
  53. agentscope_runtime/engine/runner.py +171 -130
  54. agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
  55. agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
  56. agentscope_runtime/engine/schemas/oai_llm.py +23 -23
  57. agentscope_runtime/engine/schemas/response_api.py +65 -0
  58. agentscope_runtime/engine/schemas/session.py +24 -0
  59. agentscope_runtime/engine/services/__init__.py +0 -9
  60. agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
  61. agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
  62. agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
  63. agentscope_runtime/engine/services/memory/__init__.py +24 -0
  64. agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
  65. agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
  66. agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
  67. agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
  68. agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
  69. agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +16 -19
  70. agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
  71. agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
  72. agentscope_runtime/engine/services/session_history/__init__.py +23 -0
  73. agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
  74. agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
  75. agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
  76. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
  77. agentscope_runtime/engine/tracing/base.py +10 -9
  78. agentscope_runtime/engine/tracing/message_util.py +1 -1
  79. agentscope_runtime/engine/tracing/tracing_util.py +7 -2
  80. agentscope_runtime/engine/tracing/wrapper.py +49 -31
  81. agentscope_runtime/sandbox/__init__.py +10 -2
  82. agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
  83. agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
  84. agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
  85. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
  86. agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
  87. agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
  88. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
  89. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
  90. agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
  91. agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
  92. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
  93. agentscope_runtime/sandbox/box/training_box/training_box.py +2 -44
  94. agentscope_runtime/sandbox/client/http_client.py +1 -0
  95. agentscope_runtime/sandbox/enums.py +2 -1
  96. agentscope_runtime/sandbox/manager/sandbox_manager.py +15 -2
  97. agentscope_runtime/sandbox/manager/server/app.py +12 -0
  98. agentscope_runtime/sandbox/manager/server/config.py +19 -0
  99. agentscope_runtime/sandbox/model/manager_config.py +79 -2
  100. agentscope_runtime/sandbox/utils.py +0 -18
  101. agentscope_runtime/tools/RAGs/__init__.py +0 -0
  102. agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
  103. agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
  104. agentscope_runtime/tools/__init__.py +119 -0
  105. agentscope_runtime/tools/_constants.py +18 -0
  106. agentscope_runtime/tools/alipay/__init__.py +4 -0
  107. agentscope_runtime/tools/alipay/base.py +334 -0
  108. agentscope_runtime/tools/alipay/payment.py +835 -0
  109. agentscope_runtime/tools/alipay/subscribe.py +551 -0
  110. agentscope_runtime/tools/base.py +264 -0
  111. agentscope_runtime/tools/cli/__init__.py +0 -0
  112. agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
  113. agentscope_runtime/tools/generations/__init__.py +75 -0
  114. agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
  115. agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
  116. agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
  117. agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
  118. agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
  119. agentscope_runtime/tools/generations/image_edit.py +208 -0
  120. agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
  121. agentscope_runtime/tools/generations/image_generation.py +202 -0
  122. agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
  123. agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
  124. agentscope_runtime/tools/generations/image_to_video.py +233 -0
  125. agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
  126. agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
  127. agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
  128. agentscope_runtime/tools/generations/speech_to_text.py +260 -0
  129. agentscope_runtime/tools/generations/speech_to_video.py +314 -0
  130. agentscope_runtime/tools/generations/text_to_video.py +221 -0
  131. agentscope_runtime/tools/mcp_wrapper.py +215 -0
  132. agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
  133. agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
  134. agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
  135. agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
  136. agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
  137. agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
  138. agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
  139. agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
  140. agentscope_runtime/tools/searches/__init__.py +3 -0
  141. agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
  142. agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
  143. agentscope_runtime/tools/utils/__init__.py +0 -0
  144. agentscope_runtime/tools/utils/api_key_util.py +45 -0
  145. agentscope_runtime/tools/utils/crypto_utils.py +99 -0
  146. agentscope_runtime/tools/utils/mcp_util.py +35 -0
  147. agentscope_runtime/version.py +1 -1
  148. {agentscope_runtime-0.2.0b1.dist-info → agentscope_runtime-1.0.0.dist-info}/METADATA +244 -168
  149. agentscope_runtime-1.0.0.dist-info/RECORD +240 -0
  150. {agentscope_runtime-0.2.0b1.dist-info → agentscope_runtime-1.0.0.dist-info}/entry_points.txt +1 -0
  151. agentscope_runtime/engine/agents/__init__.py +0 -2
  152. agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
  153. agentscope_runtime/engine/agents/agno_agent.py +0 -222
  154. agentscope_runtime/engine/agents/autogen_agent.py +0 -250
  155. agentscope_runtime/engine/agents/base_agent.py +0 -29
  156. agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
  157. agentscope_runtime/engine/agents/utils.py +0 -53
  158. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
  159. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  160. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  161. agentscope_runtime/engine/helpers/helper.py +0 -179
  162. agentscope_runtime/engine/schemas/context.py +0 -54
  163. agentscope_runtime/engine/services/context_manager.py +0 -164
  164. agentscope_runtime/engine/services/environment_manager.py +0 -50
  165. agentscope_runtime/engine/services/manager.py +0 -174
  166. agentscope_runtime/engine/services/rag_service.py +0 -195
  167. agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
  168. agentscope_runtime/sandbox/tools/__init__.py +0 -12
  169. agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
  170. agentscope_runtime/sandbox/tools/base/tool.py +0 -52
  171. agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
  172. agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
  173. agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
  174. agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
  175. agentscope_runtime/sandbox/tools/function_tool.py +0 -321
  176. agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
  177. agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
  178. agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
  179. agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
  180. agentscope_runtime/sandbox/tools/tool.py +0 -238
  181. agentscope_runtime/sandbox/tools/utils.py +0 -68
  182. agentscope_runtime-0.2.0b1.dist-info/RECORD +0 -183
  183. {agentscope_runtime-0.2.0b1.dist-info → agentscope_runtime-1.0.0.dist-info}/WHEEL +0 -0
  184. {agentscope_runtime-0.2.0b1.dist-info → agentscope_runtime-1.0.0.dist-info}/licenses/LICENSE +0 -0
  185. {agentscope_runtime-0.2.0b1.dist-info → agentscope_runtime-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,506 @@
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.get(
256
+ call_id,
257
+ )
258
+
259
+ if plugin_call_message is None:
260
+ # Only one tool use message yields, we fake
261
+ # Build a new tool call message
262
+ plugin_call_message = Message(
263
+ type=MessageType.PLUGIN_CALL,
264
+ role="assistant",
265
+ )
266
+
267
+ data_delta_content = DataContent(
268
+ index=index,
269
+ data=FunctionCall(
270
+ call_id=element.get("id"),
271
+ name=element.get("name"),
272
+ arguments="",
273
+ ).model_dump(),
274
+ delta=True,
275
+ )
276
+
277
+ plugin_call_message = _update_obj_attrs(
278
+ plugin_call_message,
279
+ metadata=metadata,
280
+ usage=usage,
281
+ )
282
+ yield plugin_call_message.in_progress()
283
+ data_delta_content = (
284
+ plugin_call_message.add_delta_content(
285
+ new_content=data_delta_content,
286
+ )
287
+ )
288
+ yield data_delta_content
289
+
290
+ json_str = json.dumps(element.get("input"))
291
+ data_delta_content = DataContent(
292
+ index=index,
293
+ data=FunctionCall(
294
+ call_id=element.get("id"),
295
+ name=element.get("name"),
296
+ arguments=json_str,
297
+ ).model_dump(),
298
+ delta=True,
299
+ )
300
+ data_delta_content = (
301
+ plugin_call_message.add_delta_content(
302
+ new_content=data_delta_content,
303
+ )
304
+ )
305
+ yield data_delta_content.completed()
306
+ plugin_call_message = _update_obj_attrs(
307
+ plugin_call_message,
308
+ metadata=metadata,
309
+ usage=usage,
310
+ )
311
+ yield plugin_call_message.completed()
312
+ index = None
313
+ else:
314
+ if call_id in tool_use_messages_dict:
315
+ pass
316
+ else:
317
+ # Build a new tool call message
318
+ plugin_call_message = Message(
319
+ type=MessageType.PLUGIN_CALL,
320
+ role="assistant",
321
+ )
322
+
323
+ data_delta_content = DataContent(
324
+ index=index,
325
+ data=FunctionCall(
326
+ call_id=element.get("id"),
327
+ name=element.get("name"),
328
+ arguments="",
329
+ ).model_dump(),
330
+ delta=True,
331
+ )
332
+
333
+ plugin_call_message = _update_obj_attrs(
334
+ plugin_call_message,
335
+ metadata=metadata,
336
+ usage=usage,
337
+ )
338
+ yield plugin_call_message.in_progress()
339
+ data_delta_content = (
340
+ plugin_call_message.add_delta_content(
341
+ new_content=data_delta_content,
342
+ )
343
+ )
344
+ yield data_delta_content
345
+
346
+ tool_use_messages_dict[
347
+ call_id
348
+ ] = plugin_call_message
349
+
350
+ elif element.get("type") == "tool_result": # Tool result
351
+ json_str = json.dumps(
352
+ element.get("output"),
353
+ ensure_ascii=False,
354
+ )
355
+ data_delta_content = DataContent(
356
+ index=index,
357
+ data=FunctionCallOutput(
358
+ call_id=element.get("id"),
359
+ name=element.get("name"),
360
+ output=json_str,
361
+ ).model_dump(),
362
+ )
363
+ plugin_output_message = Message(
364
+ type=MessageType.PLUGIN_CALL_OUTPUT,
365
+ role="tool",
366
+ content=[data_delta_content],
367
+ )
368
+ plugin_output_message = _update_obj_attrs(
369
+ plugin_output_message,
370
+ metadata=metadata,
371
+ usage=usage,
372
+ )
373
+ yield plugin_output_message.completed()
374
+ message = Message(
375
+ type=MessageType.MESSAGE,
376
+ role="assistant",
377
+ )
378
+ should_start_message = True
379
+ index = None
380
+ else:
381
+ # TODO: handle image/audio/video block
382
+ if should_start_message:
383
+ index = None
384
+ message = _update_obj_attrs(
385
+ message,
386
+ metadata=metadata,
387
+ usage=usage,
388
+ )
389
+ yield message.in_progress()
390
+ should_start_message = False
391
+
392
+ if element.get("type") == "image":
393
+ kwargs = {}
394
+ if (
395
+ isinstance(element.get("source"), dict)
396
+ and element.get("source", {}).get(
397
+ "type",
398
+ )
399
+ == "url"
400
+ ):
401
+ kwargs.update(
402
+ {"image_url": element.get("source")},
403
+ )
404
+
405
+ elif (
406
+ isinstance(element.get("source"), dict)
407
+ and element.get("source").get(
408
+ "type",
409
+ )
410
+ == "base64"
411
+ ):
412
+ media_type = element.get("source", {}).get(
413
+ "media_type",
414
+ "image/jpeg",
415
+ )
416
+ base64_data = element.get("source", {}).get(
417
+ "data",
418
+ "",
419
+ )
420
+ url = f"data:{media_type};base64,{base64_data}"
421
+ kwargs.update({"image_url": url})
422
+ delta_content = ImageContent(
423
+ delta=True,
424
+ index=index,
425
+ **kwargs,
426
+ )
427
+ elif element.get("text") == "audio":
428
+ kwargs = {}
429
+ if (
430
+ isinstance(element.get("source"), dict)
431
+ and element.get("source", {}).get(
432
+ "type",
433
+ )
434
+ == "url"
435
+ ):
436
+ url = element.get("source", {}).get("url")
437
+ try:
438
+ _format = urlparse(url).path.split(".")[-1]
439
+ except (
440
+ AttributeError,
441
+ IndexError,
442
+ ValueError,
443
+ ):
444
+ _format = None
445
+ kwargs.update({"format": _format, "data": url})
446
+ # Base64Source runtime check (dict with type ==
447
+ # "base64")
448
+ elif (
449
+ isinstance(element.get("source"), dict)
450
+ and element.get("source").get(
451
+ "type",
452
+ )
453
+ == "base64"
454
+ ):
455
+ media_type = element.get("source", {}).get(
456
+ "media_type",
457
+ )
458
+ base64_data = element.get("source", {}).get(
459
+ "data",
460
+ "",
461
+ )
462
+ url = f"data:{media_type};base64,{base64_data}"
463
+ kwargs.update(
464
+ {"format": media_type, "data": url},
465
+ )
466
+ delta_content = AudioContent(
467
+ delta=True,
468
+ index=index,
469
+ **kwargs,
470
+ )
471
+ else:
472
+ delta_content = TextContent(
473
+ delta=True,
474
+ index=index,
475
+ text=f"{element}",
476
+ )
477
+ delta_content = message.add_delta_content(
478
+ new_content=delta_content,
479
+ )
480
+ index = delta_content.index
481
+ yield delta_content
482
+
483
+ if last_content:
484
+ if should_start_message:
485
+ index = None
486
+ message = _update_obj_attrs(
487
+ message,
488
+ metadata=metadata,
489
+ usage=usage,
490
+ )
491
+ yield message.in_progress()
492
+ text_delta_content = TextContent(
493
+ delta=True,
494
+ index=index,
495
+ text=last_content,
496
+ )
497
+ text_delta_content = message.add_delta_content(
498
+ new_content=text_delta_content,
499
+ )
500
+ yield text_delta_content
501
+ message = _update_obj_attrs(
502
+ message,
503
+ metadata=metadata,
504
+ usage=usage,
505
+ )
506
+ 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