agentscope-runtime 1.0.4a1__py3-none-any.whl → 1.0.5.post1__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/adapters/agentscope/stream.py +2 -8
- agentscope_runtime/adapters/langgraph/stream.py +120 -70
- agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
- agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
- agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
- agentscope_runtime/adapters/utils.py +6 -0
- agentscope_runtime/cli/commands/deploy.py +836 -1
- agentscope_runtime/cli/commands/stop.py +16 -0
- agentscope_runtime/common/container_clients/__init__.py +52 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +6 -4
- agentscope_runtime/common/container_clients/boxlite_client.py +442 -0
- agentscope_runtime/common/container_clients/docker_client.py +0 -20
- agentscope_runtime/common/container_clients/fc_client.py +6 -4
- agentscope_runtime/common/container_clients/gvisor_client.py +38 -0
- agentscope_runtime/common/container_clients/knative_client.py +467 -0
- agentscope_runtime/common/utils/deprecation.py +164 -0
- agentscope_runtime/engine/__init__.py +4 -0
- agentscope_runtime/engine/app/agent_app.py +16 -4
- agentscope_runtime/engine/constant.py +1 -0
- agentscope_runtime/engine/deployers/__init__.py +34 -11
- agentscope_runtime/engine/deployers/adapter/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +26 -51
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +23 -13
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +4 -201
- agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +152 -25
- agentscope_runtime/engine/deployers/adapter/agui/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_adapter_utils.py +652 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_protocol_adapter.py +225 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
- agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
- agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
- agentscope_runtime/engine/deployers/pai_deployer.py +2335 -0
- agentscope_runtime/engine/deployers/utils/net_utils.py +37 -0
- agentscope_runtime/engine/deployers/utils/oss_utils.py +38 -0
- agentscope_runtime/engine/deployers/utils/package.py +46 -42
- agentscope_runtime/engine/helpers/agent_api_client.py +372 -0
- agentscope_runtime/engine/runner.py +13 -0
- agentscope_runtime/engine/schemas/agent_schemas.py +9 -3
- agentscope_runtime/engine/services/agent_state/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/redis_memory_service.py +15 -16
- agentscope_runtime/engine/services/session_history/__init__.py +7 -0
- agentscope_runtime/engine/tracing/local_logging_handler.py +2 -3
- agentscope_runtime/engine/tracing/wrapper.py +18 -4
- agentscope_runtime/sandbox/__init__.py +14 -6
- agentscope_runtime/sandbox/box/base/__init__.py +2 -2
- agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
- agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
- agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
- agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
- agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
- agentscope_runtime/sandbox/box/sandbox.py +102 -65
- agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
- agentscope_runtime/sandbox/client/__init__.py +6 -1
- agentscope_runtime/sandbox/client/async_http_client.py +339 -0
- agentscope_runtime/sandbox/client/base.py +74 -0
- agentscope_runtime/sandbox/client/http_client.py +108 -329
- agentscope_runtime/sandbox/enums.py +7 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +275 -29
- agentscope_runtime/sandbox/manager/server/app.py +7 -1
- agentscope_runtime/sandbox/manager/server/config.py +3 -1
- agentscope_runtime/sandbox/model/manager_config.py +11 -9
- agentscope_runtime/tools/modelstudio_memory/__init__.py +106 -0
- agentscope_runtime/tools/modelstudio_memory/base.py +220 -0
- agentscope_runtime/tools/modelstudio_memory/config.py +86 -0
- agentscope_runtime/tools/modelstudio_memory/core.py +594 -0
- agentscope_runtime/tools/modelstudio_memory/exceptions.py +60 -0
- agentscope_runtime/tools/modelstudio_memory/schemas.py +253 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/METADATA +187 -74
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/RECORD +79 -55
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/WHEEL +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=too-many-branches,too-many-statements
|
|
3
|
+
import copy
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from typing import AsyncIterator, Union, List
|
|
7
|
+
|
|
8
|
+
from agent_framework import (
|
|
9
|
+
AgentRunResponseUpdate,
|
|
10
|
+
TextContent as MSTextContent,
|
|
11
|
+
DataContent as MSDataContent,
|
|
12
|
+
TextReasoningContent,
|
|
13
|
+
UriContent,
|
|
14
|
+
FunctionCallContent,
|
|
15
|
+
FunctionResultContent,
|
|
16
|
+
ErrorContent,
|
|
17
|
+
UsageContent,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from ..utils import _update_obj_attrs
|
|
21
|
+
from ...engine.schemas.exception import AgentRuntimeErrorException
|
|
22
|
+
from ...engine.schemas.agent_schemas import (
|
|
23
|
+
Message,
|
|
24
|
+
TextContent,
|
|
25
|
+
Content,
|
|
26
|
+
DataContent,
|
|
27
|
+
FunctionCall,
|
|
28
|
+
FunctionCallOutput,
|
|
29
|
+
MessageType,
|
|
30
|
+
ImageContent,
|
|
31
|
+
AudioContent,
|
|
32
|
+
FileContent,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def adapt_ms_agent_framework_message_stream(
|
|
37
|
+
source_stream: AsyncIterator[AgentRunResponseUpdate],
|
|
38
|
+
) -> AsyncIterator[Union[Message, Content]]:
|
|
39
|
+
# Initialize variables to avoid uncaught errors
|
|
40
|
+
msg_id = None
|
|
41
|
+
usage = None
|
|
42
|
+
tool_start = False
|
|
43
|
+
message = None
|
|
44
|
+
reasoning_message = None
|
|
45
|
+
plugin_call_message = None
|
|
46
|
+
call_id = None
|
|
47
|
+
text_delta_content = None
|
|
48
|
+
data_delta_content = None
|
|
49
|
+
index = None
|
|
50
|
+
|
|
51
|
+
# Run agent
|
|
52
|
+
async for msg 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(
|
|
58
|
+
msg,
|
|
59
|
+
AgentRunResponseUpdate,
|
|
60
|
+
), f"Expected AgentRunResponseUpdate, got {type(msg)}"
|
|
61
|
+
|
|
62
|
+
# If a new message, create new Message
|
|
63
|
+
if msg.message_id != msg_id:
|
|
64
|
+
# If a new message, yield previous content
|
|
65
|
+
if text_delta_content is not None:
|
|
66
|
+
yield text_delta_content.completed()
|
|
67
|
+
text_delta_content = None
|
|
68
|
+
|
|
69
|
+
if data_delta_content is not None:
|
|
70
|
+
yield data_delta_content.completed()
|
|
71
|
+
data_delta_content = None
|
|
72
|
+
|
|
73
|
+
if message is not None:
|
|
74
|
+
message = _update_obj_attrs(
|
|
75
|
+
message,
|
|
76
|
+
usage=usage,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
yield message.completed()
|
|
80
|
+
message = None
|
|
81
|
+
|
|
82
|
+
if reasoning_message is not None:
|
|
83
|
+
reasoning_message = _update_obj_attrs(
|
|
84
|
+
reasoning_message,
|
|
85
|
+
usage=usage,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
yield reasoning_message.completed()
|
|
89
|
+
reasoning_message = None
|
|
90
|
+
|
|
91
|
+
if plugin_call_message is not None:
|
|
92
|
+
plugin_call_message = _update_obj_attrs(
|
|
93
|
+
plugin_call_message,
|
|
94
|
+
usage=usage,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
yield plugin_call_message.completed()
|
|
98
|
+
plugin_call_message = None
|
|
99
|
+
|
|
100
|
+
index = None
|
|
101
|
+
|
|
102
|
+
# Note: Tool use content only happens in the last of messages
|
|
103
|
+
tool_start = False
|
|
104
|
+
|
|
105
|
+
# Cache msg id
|
|
106
|
+
msg_id = msg.message_id
|
|
107
|
+
|
|
108
|
+
new_blocks = []
|
|
109
|
+
new_tool_blocks = []
|
|
110
|
+
if isinstance(msg.contents, List):
|
|
111
|
+
for block in msg.contents:
|
|
112
|
+
if block.type != "function_call":
|
|
113
|
+
new_blocks.append(block)
|
|
114
|
+
else:
|
|
115
|
+
new_tool_blocks.append(block)
|
|
116
|
+
if new_tool_blocks:
|
|
117
|
+
if tool_start:
|
|
118
|
+
msg.contents = new_tool_blocks
|
|
119
|
+
else:
|
|
120
|
+
msg.contents = new_blocks
|
|
121
|
+
tool_start = True
|
|
122
|
+
|
|
123
|
+
else:
|
|
124
|
+
msg.contents = new_blocks
|
|
125
|
+
|
|
126
|
+
if not msg.contents:
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
# msg content
|
|
130
|
+
content = msg.contents
|
|
131
|
+
|
|
132
|
+
for element in content:
|
|
133
|
+
if isinstance(element, UsageContent):
|
|
134
|
+
# TODO: consider keeping the same format with as
|
|
135
|
+
usage = element.details.to_dict()
|
|
136
|
+
|
|
137
|
+
elif isinstance(element, MSTextContent): # Text
|
|
138
|
+
text = element.text
|
|
139
|
+
if text:
|
|
140
|
+
if message is None:
|
|
141
|
+
message = Message(
|
|
142
|
+
role="assistant",
|
|
143
|
+
type=MessageType.MESSAGE,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
index = None
|
|
147
|
+
message = _update_obj_attrs(
|
|
148
|
+
message,
|
|
149
|
+
usage=usage,
|
|
150
|
+
)
|
|
151
|
+
yield message.in_progress()
|
|
152
|
+
|
|
153
|
+
text_delta_content = TextContent(
|
|
154
|
+
delta=True,
|
|
155
|
+
index=index,
|
|
156
|
+
text=text,
|
|
157
|
+
)
|
|
158
|
+
text_delta_content = message.add_delta_content(
|
|
159
|
+
new_content=text_delta_content,
|
|
160
|
+
)
|
|
161
|
+
index = text_delta_content.index
|
|
162
|
+
|
|
163
|
+
# Only yield valid text
|
|
164
|
+
if text_delta_content.text:
|
|
165
|
+
yield text_delta_content
|
|
166
|
+
|
|
167
|
+
if tool_start:
|
|
168
|
+
text_delta_content = message.content[index]
|
|
169
|
+
if text_delta_content.text:
|
|
170
|
+
yield text_delta_content.completed()
|
|
171
|
+
text_delta_content = None
|
|
172
|
+
|
|
173
|
+
message = _update_obj_attrs(
|
|
174
|
+
message,
|
|
175
|
+
usage=usage,
|
|
176
|
+
)
|
|
177
|
+
yield message.completed()
|
|
178
|
+
message = None
|
|
179
|
+
index = None
|
|
180
|
+
|
|
181
|
+
elif isinstance(element, TextReasoningContent): # Thinking
|
|
182
|
+
reasoning = element.text
|
|
183
|
+
if reasoning:
|
|
184
|
+
if reasoning_message is None:
|
|
185
|
+
index = None
|
|
186
|
+
reasoning_message = Message(
|
|
187
|
+
role="assistant",
|
|
188
|
+
type=MessageType.REASONING,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
reasoning_message = _update_obj_attrs(
|
|
192
|
+
reasoning_message,
|
|
193
|
+
usage=usage,
|
|
194
|
+
)
|
|
195
|
+
yield reasoning_message.in_progress()
|
|
196
|
+
|
|
197
|
+
text_delta_content = TextContent(
|
|
198
|
+
delta=True,
|
|
199
|
+
index=index,
|
|
200
|
+
text=reasoning,
|
|
201
|
+
)
|
|
202
|
+
text_delta_content = reasoning_message.add_delta_content(
|
|
203
|
+
new_content=text_delta_content,
|
|
204
|
+
)
|
|
205
|
+
index = text_delta_content.index
|
|
206
|
+
|
|
207
|
+
# Only yield valid text
|
|
208
|
+
if text_delta_content.text:
|
|
209
|
+
yield text_delta_content
|
|
210
|
+
|
|
211
|
+
if tool_start:
|
|
212
|
+
text_delta_content = reasoning_message.content[index]
|
|
213
|
+
if text_delta_content.text:
|
|
214
|
+
yield text_delta_content.completed()
|
|
215
|
+
text_delta_content = None
|
|
216
|
+
|
|
217
|
+
reasoning_message = _update_obj_attrs(
|
|
218
|
+
reasoning_message,
|
|
219
|
+
usage=usage,
|
|
220
|
+
)
|
|
221
|
+
yield reasoning_message.completed()
|
|
222
|
+
reasoning_message = None
|
|
223
|
+
index = None
|
|
224
|
+
|
|
225
|
+
elif isinstance(element, FunctionCallContent): # Tool use
|
|
226
|
+
msg_type = MessageType.PLUGIN_CALL
|
|
227
|
+
fc_cls = FunctionCall
|
|
228
|
+
fc_kwargs = {}
|
|
229
|
+
|
|
230
|
+
if element.call_id is not None: # New tool call
|
|
231
|
+
index = None
|
|
232
|
+
call_id = element.call_id
|
|
233
|
+
plugin_call_message = Message(
|
|
234
|
+
type=msg_type,
|
|
235
|
+
role="assistant",
|
|
236
|
+
)
|
|
237
|
+
plugin_call_message = _update_obj_attrs(
|
|
238
|
+
plugin_call_message,
|
|
239
|
+
usage=usage,
|
|
240
|
+
)
|
|
241
|
+
yield plugin_call_message.in_progress()
|
|
242
|
+
else:
|
|
243
|
+
# The last plugin_call_message is completed
|
|
244
|
+
if data_delta_content is not None:
|
|
245
|
+
yield data_delta_content.completed()
|
|
246
|
+
data_delta_content = None
|
|
247
|
+
if plugin_call_message is not None:
|
|
248
|
+
plugin_call_message = _update_obj_attrs(
|
|
249
|
+
plugin_call_message,
|
|
250
|
+
usage=usage,
|
|
251
|
+
)
|
|
252
|
+
yield plugin_call_message.completed()
|
|
253
|
+
plugin_call_message = None
|
|
254
|
+
index = None
|
|
255
|
+
|
|
256
|
+
data_delta_content = DataContent(
|
|
257
|
+
index=index,
|
|
258
|
+
data=fc_cls(
|
|
259
|
+
call_id=call_id,
|
|
260
|
+
name=element.name,
|
|
261
|
+
arguments=element.arguments,
|
|
262
|
+
**fc_kwargs,
|
|
263
|
+
).model_dump(),
|
|
264
|
+
delta=True,
|
|
265
|
+
msg_id=plugin_call_message.id,
|
|
266
|
+
)
|
|
267
|
+
yield data_delta_content.in_progress()
|
|
268
|
+
|
|
269
|
+
plugin_call_message = _update_obj_attrs(
|
|
270
|
+
plugin_call_message,
|
|
271
|
+
usage=usage,
|
|
272
|
+
)
|
|
273
|
+
yield plugin_call_message.in_progress()
|
|
274
|
+
|
|
275
|
+
elif isinstance(element, FunctionResultContent): # Tool result
|
|
276
|
+
try:
|
|
277
|
+
json_str = json.dumps(
|
|
278
|
+
element.result,
|
|
279
|
+
ensure_ascii=False,
|
|
280
|
+
)
|
|
281
|
+
except Exception:
|
|
282
|
+
json_str = str(element.result)
|
|
283
|
+
|
|
284
|
+
data_delta_content = DataContent(
|
|
285
|
+
index=None,
|
|
286
|
+
data=FunctionCallOutput(
|
|
287
|
+
call_id=element.call_id,
|
|
288
|
+
output=json_str,
|
|
289
|
+
).model_dump(),
|
|
290
|
+
)
|
|
291
|
+
plugin_output_message = Message(
|
|
292
|
+
type=MessageType.PLUGIN_CALL_OUTPUT,
|
|
293
|
+
role="tool",
|
|
294
|
+
content=[data_delta_content],
|
|
295
|
+
)
|
|
296
|
+
plugin_output_message = _update_obj_attrs(
|
|
297
|
+
plugin_output_message,
|
|
298
|
+
usage=usage,
|
|
299
|
+
)
|
|
300
|
+
yield plugin_output_message.completed()
|
|
301
|
+
message = None
|
|
302
|
+
reasoning_message = None
|
|
303
|
+
|
|
304
|
+
index = None
|
|
305
|
+
|
|
306
|
+
elif isinstance(element, MSDataContent):
|
|
307
|
+
delta_content = DataContent(
|
|
308
|
+
delta=True,
|
|
309
|
+
index=index,
|
|
310
|
+
data=element.uri,
|
|
311
|
+
type=element.type,
|
|
312
|
+
)
|
|
313
|
+
delta_content = message.add_delta_content(
|
|
314
|
+
new_content=delta_content,
|
|
315
|
+
)
|
|
316
|
+
index = delta_content.index
|
|
317
|
+
yield delta_content
|
|
318
|
+
|
|
319
|
+
elif isinstance(element, UriContent):
|
|
320
|
+
kwargs = {}
|
|
321
|
+
|
|
322
|
+
if "image" in element.type:
|
|
323
|
+
cnt_cls = ImageContent
|
|
324
|
+
kwargs.update(
|
|
325
|
+
{
|
|
326
|
+
"type": element.type,
|
|
327
|
+
"image_url": element.uri,
|
|
328
|
+
},
|
|
329
|
+
)
|
|
330
|
+
elif "audio" in element.type:
|
|
331
|
+
cnt_cls = AudioContent
|
|
332
|
+
kwargs.update(
|
|
333
|
+
{
|
|
334
|
+
"type": element.type,
|
|
335
|
+
"data": element.uri,
|
|
336
|
+
"format": element.media_type,
|
|
337
|
+
},
|
|
338
|
+
)
|
|
339
|
+
elif "video" in element.type:
|
|
340
|
+
# TODO: support video type
|
|
341
|
+
cnt_cls = ImageContent
|
|
342
|
+
kwargs.update(
|
|
343
|
+
{
|
|
344
|
+
"type": element.media_type,
|
|
345
|
+
"image_url": element.uri,
|
|
346
|
+
},
|
|
347
|
+
)
|
|
348
|
+
else:
|
|
349
|
+
cnt_cls = FileContent
|
|
350
|
+
kwargs.update(
|
|
351
|
+
{
|
|
352
|
+
"type": element.type,
|
|
353
|
+
"file_url": element.uri,
|
|
354
|
+
},
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
delta_content = cnt_cls(
|
|
358
|
+
delta=False,
|
|
359
|
+
index=index,
|
|
360
|
+
**kwargs,
|
|
361
|
+
)
|
|
362
|
+
delta_content = message.add_delta_content(
|
|
363
|
+
new_content=delta_content,
|
|
364
|
+
)
|
|
365
|
+
index = delta_content.index
|
|
366
|
+
yield delta_content
|
|
367
|
+
|
|
368
|
+
elif isinstance(element, ErrorContent):
|
|
369
|
+
raise AgentRuntimeErrorException(
|
|
370
|
+
code=element.error_code,
|
|
371
|
+
message=element.message,
|
|
372
|
+
details=element.details,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
else:
|
|
376
|
+
raise ValueError(f"Unknown element type: {type(element)}")
|
|
377
|
+
|
|
378
|
+
if (
|
|
379
|
+
text_delta_content is not None
|
|
380
|
+
and text_delta_content.status == "in_progress"
|
|
381
|
+
):
|
|
382
|
+
yield text_delta_content.completed()
|
|
383
|
+
|
|
384
|
+
if (
|
|
385
|
+
data_delta_content is not None
|
|
386
|
+
and data_delta_content.status == "in_progress"
|
|
387
|
+
):
|
|
388
|
+
yield data_delta_content.completed()
|
|
389
|
+
|
|
390
|
+
if message is not None and message.status == "in_progress":
|
|
391
|
+
message = _update_obj_attrs(
|
|
392
|
+
message,
|
|
393
|
+
usage=usage,
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
yield message.completed()
|
|
397
|
+
|
|
398
|
+
if (
|
|
399
|
+
reasoning_message is not None
|
|
400
|
+
and reasoning_message.status == "in_progress"
|
|
401
|
+
):
|
|
402
|
+
reasoning_message = _update_obj_attrs(
|
|
403
|
+
reasoning_message,
|
|
404
|
+
usage=usage,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
yield reasoning_message.completed()
|
|
408
|
+
|
|
409
|
+
if (
|
|
410
|
+
plugin_call_message is not None
|
|
411
|
+
and plugin_call_message.status == "in_progress"
|
|
412
|
+
):
|
|
413
|
+
plugin_call_message = _update_obj_attrs(
|
|
414
|
+
plugin_call_message,
|
|
415
|
+
usage=usage,
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
yield plugin_call_message.completed()
|