agentscope-runtime 1.0.0b2__py3-none-any.whl → 1.0.2__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/message.py +78 -10
- agentscope_runtime/adapters/agentscope/stream.py +155 -101
- agentscope_runtime/adapters/agentscope/tool/tool.py +1 -3
- agentscope_runtime/adapters/agno/__init__.py +0 -0
- agentscope_runtime/adapters/agno/message.py +30 -0
- agentscope_runtime/adapters/agno/stream.py +122 -0
- agentscope_runtime/adapters/langgraph/__init__.py +12 -0
- agentscope_runtime/adapters/langgraph/message.py +257 -0
- agentscope_runtime/adapters/langgraph/stream.py +205 -0
- agentscope_runtime/cli/__init__.py +7 -0
- agentscope_runtime/cli/cli.py +63 -0
- agentscope_runtime/cli/commands/__init__.py +2 -0
- agentscope_runtime/cli/commands/chat.py +815 -0
- agentscope_runtime/cli/commands/deploy.py +1062 -0
- agentscope_runtime/cli/commands/invoke.py +58 -0
- agentscope_runtime/cli/commands/list_cmd.py +103 -0
- agentscope_runtime/cli/commands/run.py +176 -0
- agentscope_runtime/cli/commands/sandbox.py +128 -0
- agentscope_runtime/cli/commands/status.py +60 -0
- agentscope_runtime/cli/commands/stop.py +185 -0
- agentscope_runtime/cli/commands/web.py +166 -0
- agentscope_runtime/cli/loaders/__init__.py +6 -0
- agentscope_runtime/cli/loaders/agent_loader.py +295 -0
- agentscope_runtime/cli/state/__init__.py +10 -0
- agentscope_runtime/cli/utils/__init__.py +18 -0
- agentscope_runtime/cli/utils/console.py +378 -0
- agentscope_runtime/cli/utils/validators.py +118 -0
- agentscope_runtime/engine/app/agent_app.py +15 -5
- agentscope_runtime/engine/deployers/__init__.py +1 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +154 -24
- agentscope_runtime/engine/deployers/base.py +27 -2
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +158 -31
- agentscope_runtime/engine/deployers/local_deployer.py +188 -25
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +109 -18
- agentscope_runtime/engine/deployers/state/__init__.py +9 -0
- agentscope_runtime/engine/deployers/state/manager.py +388 -0
- agentscope_runtime/engine/deployers/state/schema.py +96 -0
- agentscope_runtime/engine/deployers/utils/build_cache.py +736 -0
- agentscope_runtime/engine/deployers/utils/detached_app.py +105 -30
- agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +31 -10
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +15 -8
- agentscope_runtime/engine/deployers/utils/docker_image_utils/image_factory.py +30 -2
- agentscope_runtime/engine/deployers/utils/k8s_utils.py +241 -0
- agentscope_runtime/engine/deployers/utils/package.py +56 -6
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +68 -9
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +155 -5
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +107 -123
- agentscope_runtime/engine/runner.py +32 -12
- agentscope_runtime/engine/schemas/agent_schemas.py +21 -7
- agentscope_runtime/engine/schemas/exception.py +580 -0
- agentscope_runtime/engine/services/agent_state/__init__.py +2 -0
- agentscope_runtime/engine/services/agent_state/state_service_factory.py +55 -0
- agentscope_runtime/engine/services/memory/__init__.py +2 -0
- agentscope_runtime/engine/services/memory/memory_service_factory.py +126 -0
- agentscope_runtime/engine/services/sandbox/__init__.py +2 -0
- agentscope_runtime/engine/services/sandbox/sandbox_service_factory.py +49 -0
- agentscope_runtime/engine/services/service_factory.py +119 -0
- agentscope_runtime/engine/services/session_history/__init__.py +2 -0
- agentscope_runtime/engine/services/session_history/session_history_service_factory.py +73 -0
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +35 -10
- agentscope_runtime/engine/tracing/wrapper.py +49 -31
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +113 -39
- agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +20 -4
- agentscope_runtime/sandbox/utils.py +2 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/METADATA +82 -11
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/RECORD +71 -36
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/entry_points.txt +1 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/WHEEL +0 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# pylint:disable=too-many-branches,too-many-statements
|
|
2
|
+
# pylint:disable=too-many-branches,too-many-statements,protected-access
|
|
3
3
|
# TODO: support file block
|
|
4
4
|
import json
|
|
5
5
|
|
|
@@ -7,6 +7,7 @@ from collections import OrderedDict
|
|
|
7
7
|
from typing import Union, List
|
|
8
8
|
from urllib.parse import urlparse
|
|
9
9
|
|
|
10
|
+
from mcp.types import CallToolResult
|
|
10
11
|
from agentscope.message import (
|
|
11
12
|
Msg,
|
|
12
13
|
ToolUseBlock,
|
|
@@ -19,6 +20,7 @@ from agentscope.message import (
|
|
|
19
20
|
URLSource,
|
|
20
21
|
Base64Source,
|
|
21
22
|
)
|
|
23
|
+
from agentscope.mcp._client_base import MCPClientBase
|
|
22
24
|
|
|
23
25
|
from ...engine.schemas.agent_schemas import (
|
|
24
26
|
Message,
|
|
@@ -338,6 +340,16 @@ def message_to_agentscope_msg(
|
|
|
338
340
|
A single Msg object or a list of Msg objects.
|
|
339
341
|
"""
|
|
340
342
|
|
|
343
|
+
def _try_loads(v, default, keep_original=False):
|
|
344
|
+
if isinstance(v, (dict, list)):
|
|
345
|
+
return v
|
|
346
|
+
if isinstance(v, str) and v.strip():
|
|
347
|
+
try:
|
|
348
|
+
return json.loads(v)
|
|
349
|
+
except Exception:
|
|
350
|
+
return v if keep_original else default
|
|
351
|
+
return default
|
|
352
|
+
|
|
341
353
|
def _convert_one(message: Message) -> Msg:
|
|
342
354
|
# Normalize role
|
|
343
355
|
if message.role == "tool":
|
|
@@ -362,24 +374,49 @@ def message_to_agentscope_msg(
|
|
|
362
374
|
|
|
363
375
|
if message.type in (
|
|
364
376
|
MessageType.PLUGIN_CALL,
|
|
377
|
+
MessageType.MCP_TOOL_CALL,
|
|
365
378
|
MessageType.FUNCTION_CALL,
|
|
366
379
|
):
|
|
367
|
-
# convert
|
|
380
|
+
# convert CALL to ToolUseBlock
|
|
381
|
+
tool_args = None
|
|
382
|
+
for cnt in reversed(message.content):
|
|
383
|
+
if hasattr(cnt, "data"):
|
|
384
|
+
v = cnt.data.get("arguments")
|
|
385
|
+
if isinstance(v, (dict, list)) or (
|
|
386
|
+
isinstance(v, str) and v.strip()
|
|
387
|
+
):
|
|
388
|
+
tool_args = _try_loads(v, {}, keep_original=False)
|
|
389
|
+
break
|
|
390
|
+
if tool_args is None:
|
|
391
|
+
tool_args = {}
|
|
368
392
|
result["content"] = [
|
|
369
393
|
ToolUseBlock(
|
|
370
394
|
type="tool_use",
|
|
371
395
|
id=message.content[0].data["call_id"],
|
|
372
396
|
name=message.content[0].data.get("name"),
|
|
373
|
-
input=
|
|
397
|
+
input=tool_args,
|
|
374
398
|
),
|
|
375
399
|
]
|
|
376
400
|
elif message.type in (
|
|
377
401
|
MessageType.PLUGIN_CALL_OUTPUT,
|
|
402
|
+
MessageType.MCP_TOOL_CALL_OUTPUT,
|
|
378
403
|
MessageType.FUNCTION_CALL_OUTPUT,
|
|
379
404
|
):
|
|
380
|
-
# convert
|
|
381
|
-
|
|
382
|
-
|
|
405
|
+
# convert CALL_OUTPUT to ToolResultBlock
|
|
406
|
+
out = None
|
|
407
|
+
raw_output = ""
|
|
408
|
+
for cnt in reversed(message.content):
|
|
409
|
+
if hasattr(cnt, "data"):
|
|
410
|
+
v = cnt.data.get("output")
|
|
411
|
+
if isinstance(v, (dict, list)) or (
|
|
412
|
+
isinstance(v, str) and v.strip()
|
|
413
|
+
):
|
|
414
|
+
raw_output = v
|
|
415
|
+
out = _try_loads(v, "", keep_original=True)
|
|
416
|
+
break
|
|
417
|
+
if out is None:
|
|
418
|
+
out = ""
|
|
419
|
+
blk = out
|
|
383
420
|
|
|
384
421
|
def is_valid_block(obj):
|
|
385
422
|
return any(
|
|
@@ -389,12 +426,32 @@ def message_to_agentscope_msg(
|
|
|
389
426
|
|
|
390
427
|
if isinstance(blk, list):
|
|
391
428
|
if not all(is_valid_block(item) for item in blk):
|
|
392
|
-
|
|
429
|
+
try:
|
|
430
|
+
# Try to convert MCP content list to blocks
|
|
431
|
+
call_tool_result = {
|
|
432
|
+
"content": blk,
|
|
433
|
+
"structuredContent": None,
|
|
434
|
+
"isError": False,
|
|
435
|
+
}
|
|
436
|
+
blk = MCPClientBase._convert_mcp_content_to_as_blocks(
|
|
437
|
+
CallToolResult.model_validate(
|
|
438
|
+
call_tool_result,
|
|
439
|
+
).content,
|
|
440
|
+
)
|
|
441
|
+
except Exception:
|
|
442
|
+
blk = raw_output
|
|
393
443
|
elif isinstance(blk, dict):
|
|
394
444
|
if not is_valid_block(blk):
|
|
395
|
-
|
|
445
|
+
try:
|
|
446
|
+
# Try to convert to MCP CallToolResult then to blocks
|
|
447
|
+
blk = CallToolResult.model_validate(blk)
|
|
448
|
+
blk = MCPClientBase._convert_mcp_content_to_as_blocks(
|
|
449
|
+
blk.content,
|
|
450
|
+
)
|
|
451
|
+
except Exception:
|
|
452
|
+
blk = raw_output
|
|
396
453
|
else:
|
|
397
|
-
blk =
|
|
454
|
+
blk = raw_output
|
|
398
455
|
|
|
399
456
|
result["content"] = [
|
|
400
457
|
ToolResultBlock(
|
|
@@ -416,6 +473,7 @@ def message_to_agentscope_msg(
|
|
|
416
473
|
"text": (TextBlock, "text"),
|
|
417
474
|
"image": (ImageBlock, "image_url"),
|
|
418
475
|
"audio": (AudioBlock, "data"),
|
|
476
|
+
"data": (TextBlock, "data"),
|
|
419
477
|
# "video": (VideoBlock, "video_url", True),
|
|
420
478
|
# TODO: support video
|
|
421
479
|
}
|
|
@@ -490,7 +548,17 @@ def message_to_agentscope_msg(
|
|
|
490
548
|
block_cls(type=cnt_type, source=base64_source),
|
|
491
549
|
)
|
|
492
550
|
else:
|
|
493
|
-
|
|
551
|
+
# text & data
|
|
552
|
+
if isinstance(value, str):
|
|
553
|
+
msg_content.append(
|
|
554
|
+
TextBlock(type="text", text=value),
|
|
555
|
+
)
|
|
556
|
+
else:
|
|
557
|
+
try:
|
|
558
|
+
json_str = json.dumps(value, ensure_ascii=False)
|
|
559
|
+
except Exception:
|
|
560
|
+
json_str = str(value)
|
|
561
|
+
msg_content.append(TextBlock(text=json_str))
|
|
494
562
|
|
|
495
563
|
result["content"] = msg_content
|
|
496
564
|
_msg = Msg(**result)
|
|
@@ -3,22 +3,28 @@
|
|
|
3
3
|
import copy
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
|
-
from typing import AsyncIterator, Tuple, List
|
|
6
|
+
from typing import AsyncIterator, Tuple, List, Union
|
|
7
7
|
from urllib.parse import urlparse
|
|
8
8
|
|
|
9
|
+
from agentscope import setup_logger
|
|
9
10
|
from agentscope.message import Msg
|
|
10
11
|
|
|
11
12
|
from ...engine.schemas.agent_schemas import (
|
|
12
13
|
Message,
|
|
14
|
+
Content,
|
|
13
15
|
TextContent,
|
|
14
16
|
ImageContent,
|
|
15
17
|
AudioContent,
|
|
16
18
|
DataContent,
|
|
19
|
+
McpCall,
|
|
20
|
+
McpCallOutput,
|
|
17
21
|
FunctionCall,
|
|
18
22
|
FunctionCallOutput,
|
|
19
23
|
MessageType,
|
|
20
24
|
)
|
|
21
25
|
|
|
26
|
+
setup_logger("ERROR")
|
|
27
|
+
|
|
22
28
|
|
|
23
29
|
def _update_obj_attrs(obj, **attrs):
|
|
24
30
|
for key, value in attrs.items():
|
|
@@ -29,7 +35,7 @@ def _update_obj_attrs(obj, **attrs):
|
|
|
29
35
|
|
|
30
36
|
async def adapt_agentscope_message_stream(
|
|
31
37
|
source_stream: AsyncIterator[Tuple[Msg, bool]],
|
|
32
|
-
) -> AsyncIterator[Message]:
|
|
38
|
+
) -> AsyncIterator[Union[Message, Content]]:
|
|
33
39
|
# Initialize variables to avoid uncaught errors
|
|
34
40
|
msg_id = None
|
|
35
41
|
last_content = ""
|
|
@@ -46,6 +52,7 @@ async def adapt_agentscope_message_stream(
|
|
|
46
52
|
should_start_message = True
|
|
47
53
|
should_start_reasoning_message = True
|
|
48
54
|
tool_use_messages_dict = {}
|
|
55
|
+
tool_result_messages_dict = {}
|
|
49
56
|
index = None
|
|
50
57
|
|
|
51
58
|
# Run agent
|
|
@@ -78,8 +85,6 @@ async def adapt_agentscope_message_stream(
|
|
|
78
85
|
# Note: Tool use content only happens in the last of messages
|
|
79
86
|
tool_start = False
|
|
80
87
|
|
|
81
|
-
tool_use_messages_dict = {}
|
|
82
|
-
|
|
83
88
|
# Cache msg id
|
|
84
89
|
msg_id = msg.id
|
|
85
90
|
|
|
@@ -251,132 +256,181 @@ async def adapt_agentscope_message_stream(
|
|
|
251
256
|
elif element.get("type") == "tool_use": # Tool use
|
|
252
257
|
call_id = element.get("id")
|
|
253
258
|
|
|
254
|
-
if
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
)
|
|
259
|
+
if element.get("tool_type", "plugin") == "mcp":
|
|
260
|
+
msg_type = MessageType.MCP_TOOL_CALL
|
|
261
|
+
fc_cls = McpCall
|
|
262
|
+
fc_kwargs = {
|
|
263
|
+
"server_label": element.get("server_label"),
|
|
264
|
+
}
|
|
265
|
+
else:
|
|
266
|
+
msg_type = MessageType.PLUGIN_CALL
|
|
267
|
+
fc_cls = FunctionCall
|
|
268
|
+
fc_kwargs = {}
|
|
276
269
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
|
270
|
+
plugin_call_message = tool_use_messages_dict.get(
|
|
271
|
+
call_id,
|
|
272
|
+
)
|
|
289
273
|
|
|
290
|
-
|
|
274
|
+
if plugin_call_message is None:
|
|
275
|
+
# Create a new message
|
|
276
|
+
plugin_call_message = Message(
|
|
277
|
+
type=msg_type,
|
|
278
|
+
role="assistant",
|
|
279
|
+
)
|
|
291
280
|
data_delta_content = DataContent(
|
|
292
|
-
index=
|
|
293
|
-
data=
|
|
294
|
-
call_id=element
|
|
281
|
+
index=0,
|
|
282
|
+
data=fc_cls(
|
|
283
|
+
call_id=element["id"],
|
|
295
284
|
name=element.get("name"),
|
|
296
|
-
arguments=
|
|
285
|
+
arguments="",
|
|
286
|
+
**fc_kwargs,
|
|
297
287
|
).model_dump(),
|
|
298
|
-
delta=
|
|
299
|
-
)
|
|
300
|
-
data_delta_content = (
|
|
301
|
-
plugin_call_message.add_delta_content(
|
|
302
|
-
new_content=data_delta_content,
|
|
303
|
-
)
|
|
288
|
+
delta=False,
|
|
304
289
|
)
|
|
305
|
-
yield data_delta_content.completed()
|
|
306
290
|
plugin_call_message = _update_obj_attrs(
|
|
307
291
|
plugin_call_message,
|
|
308
292
|
metadata=metadata,
|
|
309
293
|
usage=usage,
|
|
310
294
|
)
|
|
295
|
+
yield plugin_call_message.in_progress()
|
|
296
|
+
data_delta_content.msg_id = plugin_call_message.id
|
|
297
|
+
yield data_delta_content.in_progress()
|
|
298
|
+
tool_use_messages_dict[
|
|
299
|
+
call_id
|
|
300
|
+
] = plugin_call_message
|
|
301
|
+
|
|
302
|
+
# Update arguments
|
|
303
|
+
json_str = json.dumps(
|
|
304
|
+
element.get("input"),
|
|
305
|
+
ensure_ascii=False,
|
|
306
|
+
)
|
|
307
|
+
data_delta_content = DataContent(
|
|
308
|
+
index=None if last else 0,
|
|
309
|
+
data=fc_cls(
|
|
310
|
+
call_id=element["id"],
|
|
311
|
+
name=element.get("name"),
|
|
312
|
+
arguments=json_str,
|
|
313
|
+
**fc_kwargs,
|
|
314
|
+
).model_dump(),
|
|
315
|
+
delta=False,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
plugin_call_message = _update_obj_attrs(
|
|
319
|
+
plugin_call_message,
|
|
320
|
+
metadata=metadata,
|
|
321
|
+
usage=usage,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if last:
|
|
325
|
+
plugin_call_message.add_content(
|
|
326
|
+
new_content=data_delta_content,
|
|
327
|
+
)
|
|
328
|
+
yield data_delta_content.completed()
|
|
311
329
|
yield plugin_call_message.completed()
|
|
312
|
-
index = None
|
|
313
330
|
else:
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
else:
|
|
317
|
-
# Build a new tool call message
|
|
318
|
-
plugin_call_message = Message(
|
|
319
|
-
type=MessageType.PLUGIN_CALL,
|
|
320
|
-
role="assistant",
|
|
321
|
-
)
|
|
331
|
+
data_delta_content.msg_id = plugin_call_message.id
|
|
332
|
+
yield data_delta_content.in_progress()
|
|
322
333
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
data=FunctionCall(
|
|
326
|
-
call_id=element.get("id"),
|
|
327
|
-
name=element.get("name"),
|
|
328
|
-
arguments="",
|
|
329
|
-
).model_dump(),
|
|
330
|
-
delta=True,
|
|
331
|
-
)
|
|
334
|
+
elif element.get("type") == "tool_result": # Tool result
|
|
335
|
+
call_id = element.get("id")
|
|
332
336
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
new_content=data_delta_content,
|
|
342
|
-
)
|
|
343
|
-
)
|
|
344
|
-
yield data_delta_content
|
|
337
|
+
plugin_call_message = tool_use_messages_dict.get(
|
|
338
|
+
call_id,
|
|
339
|
+
)
|
|
340
|
+
# Determine the output message type and class to use
|
|
341
|
+
# for the tool result message based on the type of
|
|
342
|
+
# the original tool call message.
|
|
343
|
+
msg_type = MessageType.PLUGIN_CALL_OUTPUT
|
|
344
|
+
fc_cls = FunctionCallOutput
|
|
345
345
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
if plugin_call_message:
|
|
347
|
+
if (
|
|
348
|
+
plugin_call_message.type
|
|
349
|
+
== MessageType.MCP_TOOL_CALL
|
|
350
|
+
):
|
|
351
|
+
msg_type = MessageType.MCP_TOOL_CALL_OUTPUT
|
|
352
|
+
fc_cls = McpCallOutput
|
|
349
353
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
element.get("output"),
|
|
353
|
-
ensure_ascii=False,
|
|
354
|
+
plugin_output_message = tool_result_messages_dict.get(
|
|
355
|
+
call_id,
|
|
354
356
|
)
|
|
357
|
+
|
|
358
|
+
if plugin_output_message is None:
|
|
359
|
+
# Create a new message
|
|
360
|
+
plugin_output_message = Message(
|
|
361
|
+
type=msg_type,
|
|
362
|
+
role="tool",
|
|
363
|
+
)
|
|
364
|
+
data_delta_content = DataContent(
|
|
365
|
+
index=0,
|
|
366
|
+
data=fc_cls(
|
|
367
|
+
call_id=element.get("id"),
|
|
368
|
+
name=element.get("name"),
|
|
369
|
+
output="",
|
|
370
|
+
).model_dump(),
|
|
371
|
+
delta=False,
|
|
372
|
+
)
|
|
373
|
+
plugin_output_message = _update_obj_attrs(
|
|
374
|
+
plugin_output_message,
|
|
375
|
+
metadata=metadata,
|
|
376
|
+
usage=usage,
|
|
377
|
+
)
|
|
378
|
+
yield plugin_output_message.in_progress()
|
|
379
|
+
data_delta_content.msg_id = (
|
|
380
|
+
plugin_output_message.id
|
|
381
|
+
)
|
|
382
|
+
yield data_delta_content.in_progress()
|
|
383
|
+
tool_result_messages_dict[
|
|
384
|
+
call_id
|
|
385
|
+
] = plugin_output_message
|
|
386
|
+
|
|
387
|
+
# Update output
|
|
388
|
+
try:
|
|
389
|
+
json_str = json.dumps(
|
|
390
|
+
element.get("output"),
|
|
391
|
+
ensure_ascii=False,
|
|
392
|
+
)
|
|
393
|
+
except Exception:
|
|
394
|
+
# For non-JSON outputs, we just use the string
|
|
395
|
+
# representation
|
|
396
|
+
json_str = str(element.get("output"))
|
|
397
|
+
|
|
355
398
|
data_delta_content = DataContent(
|
|
356
|
-
index=
|
|
357
|
-
data=
|
|
399
|
+
index=None if last else 0,
|
|
400
|
+
data=fc_cls(
|
|
358
401
|
call_id=element.get("id"),
|
|
359
402
|
name=element.get("name"),
|
|
360
403
|
output=json_str,
|
|
361
404
|
).model_dump(),
|
|
405
|
+
delta=False,
|
|
362
406
|
)
|
|
363
|
-
|
|
364
|
-
type=MessageType.PLUGIN_CALL_OUTPUT,
|
|
365
|
-
role="tool",
|
|
366
|
-
content=[data_delta_content],
|
|
367
|
-
)
|
|
407
|
+
|
|
368
408
|
plugin_output_message = _update_obj_attrs(
|
|
369
409
|
plugin_output_message,
|
|
370
410
|
metadata=metadata,
|
|
371
411
|
usage=usage,
|
|
372
412
|
)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
413
|
+
|
|
414
|
+
if last:
|
|
415
|
+
plugin_output_message.add_content(
|
|
416
|
+
new_content=data_delta_content,
|
|
417
|
+
)
|
|
418
|
+
yield data_delta_content.completed()
|
|
419
|
+
yield plugin_output_message.completed()
|
|
420
|
+
|
|
421
|
+
message = Message(
|
|
422
|
+
type=MessageType.MESSAGE,
|
|
423
|
+
role="assistant",
|
|
424
|
+
)
|
|
425
|
+
should_start_message = True
|
|
426
|
+
index = None
|
|
427
|
+
|
|
428
|
+
else:
|
|
429
|
+
data_delta_content.msg_id = (
|
|
430
|
+
plugin_output_message.id
|
|
431
|
+
)
|
|
432
|
+
yield data_delta_content.in_progress()
|
|
433
|
+
|
|
380
434
|
else:
|
|
381
435
|
# TODO: handle image/audio/video block
|
|
382
436
|
if should_start_message:
|
|
@@ -9,9 +9,7 @@ from typing import (
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
from agentscope.tool import Toolkit, ToolResponse
|
|
12
|
-
from agentscope.tool.
|
|
13
|
-
RegisteredToolFunction,
|
|
14
|
-
)
|
|
12
|
+
from agentscope.tool._types import RegisteredToolFunction
|
|
15
13
|
|
|
16
14
|
from agentscope_runtime.tools.base import Tool
|
|
17
15
|
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from typing import Union, List
|
|
3
|
+
|
|
4
|
+
from agentscope.formatter import OpenAIChatFormatter
|
|
5
|
+
|
|
6
|
+
from ...engine.schemas.agent_schemas import Message
|
|
7
|
+
from ..agentscope.message import message_to_agentscope_msg
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def message_to_agno_message(
|
|
11
|
+
messages: Union[Message, List[Message]],
|
|
12
|
+
) -> Union[dict, List[dict]]:
|
|
13
|
+
"""
|
|
14
|
+
Convert AgentScope runtime Message(s) to Agno Message(s).
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
messages: A single AgentScope runtime Message or list of Messages.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
A single AgnoMessage object or a list of AgnoMessage objects.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
as_msgs = message_to_agentscope_msg(messages)
|
|
24
|
+
raw_list = isinstance(as_msgs, list)
|
|
25
|
+
as_msgs = as_msgs if raw_list else [as_msgs]
|
|
26
|
+
|
|
27
|
+
formatter = OpenAIChatFormatter()
|
|
28
|
+
agno_message = await formatter.format(as_msgs)
|
|
29
|
+
|
|
30
|
+
return agno_message if raw_list else agno_message[0]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint:disable=too-many-branches,too-many-statements
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from typing import AsyncIterator, Union
|
|
6
|
+
|
|
7
|
+
from agno.run.agent import (
|
|
8
|
+
BaseAgentRunEvent,
|
|
9
|
+
RunContentEvent,
|
|
10
|
+
RunCompletedEvent,
|
|
11
|
+
RunContentCompletedEvent,
|
|
12
|
+
RunStartedEvent,
|
|
13
|
+
# ReasoningStartedEvent, # Not support now
|
|
14
|
+
# ReasoningStepEvent,
|
|
15
|
+
# ReasoningCompletedEvent,
|
|
16
|
+
ToolCallStartedEvent,
|
|
17
|
+
ToolCallCompletedEvent,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from ...engine.schemas.agent_schemas import (
|
|
22
|
+
Message,
|
|
23
|
+
Content,
|
|
24
|
+
DataContent,
|
|
25
|
+
FunctionCall,
|
|
26
|
+
FunctionCallOutput,
|
|
27
|
+
MessageType,
|
|
28
|
+
)
|
|
29
|
+
from ...engine.helpers.agent_api_builder import ResponseBuilder
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def adapt_agno_message_stream(
|
|
33
|
+
source_stream: AsyncIterator[BaseAgentRunEvent],
|
|
34
|
+
) -> AsyncIterator[Union[Message, Content]]:
|
|
35
|
+
rb = ResponseBuilder()
|
|
36
|
+
mb = None
|
|
37
|
+
cb = None
|
|
38
|
+
mb_type = None
|
|
39
|
+
|
|
40
|
+
should_start_new_message = True
|
|
41
|
+
|
|
42
|
+
async for event in source_stream:
|
|
43
|
+
if isinstance(event, RunStartedEvent):
|
|
44
|
+
should_start_new_message = True
|
|
45
|
+
elif isinstance(event, RunCompletedEvent):
|
|
46
|
+
# Placeholder
|
|
47
|
+
return
|
|
48
|
+
elif isinstance(event, RunContentEvent):
|
|
49
|
+
if event.reasoning_content:
|
|
50
|
+
message_type = MessageType.REASONING
|
|
51
|
+
content = event.reasoning_content
|
|
52
|
+
else:
|
|
53
|
+
message_type = MessageType.MESSAGE
|
|
54
|
+
content = event.content
|
|
55
|
+
|
|
56
|
+
if message_type != mb_type:
|
|
57
|
+
# Complete previous message
|
|
58
|
+
should_start_new_message = True
|
|
59
|
+
mb_type = message_type
|
|
60
|
+
if cb is not None:
|
|
61
|
+
yield cb.complete()
|
|
62
|
+
if mb is not None:
|
|
63
|
+
yield mb.complete()
|
|
64
|
+
|
|
65
|
+
if should_start_new_message:
|
|
66
|
+
should_start_new_message = False
|
|
67
|
+
mb = rb.create_message_builder(
|
|
68
|
+
message_type=message_type,
|
|
69
|
+
role="assistant",
|
|
70
|
+
)
|
|
71
|
+
yield mb.get_message_data()
|
|
72
|
+
|
|
73
|
+
cb = mb.create_content_builder(
|
|
74
|
+
content_type="text",
|
|
75
|
+
)
|
|
76
|
+
yield cb.add_text_delta(content)
|
|
77
|
+
elif isinstance(event, RunContentCompletedEvent):
|
|
78
|
+
yield cb.complete()
|
|
79
|
+
yield mb.complete()
|
|
80
|
+
mb = None
|
|
81
|
+
cb = None
|
|
82
|
+
should_start_new_message = True
|
|
83
|
+
elif isinstance(event, ToolCallStartedEvent):
|
|
84
|
+
json_str = json.dumps(event.tool.tool_args, ensure_ascii=False)
|
|
85
|
+
data = DataContent(
|
|
86
|
+
data=FunctionCall(
|
|
87
|
+
call_id=event.tool.tool_call_id,
|
|
88
|
+
name=event.tool.tool_name,
|
|
89
|
+
arguments=json_str,
|
|
90
|
+
).model_dump(),
|
|
91
|
+
)
|
|
92
|
+
# Not support streaming tool call
|
|
93
|
+
message = Message(
|
|
94
|
+
type=MessageType.PLUGIN_CALL,
|
|
95
|
+
role="assistant",
|
|
96
|
+
content=[data],
|
|
97
|
+
)
|
|
98
|
+
# No stream tool call
|
|
99
|
+
yield message.completed()
|
|
100
|
+
|
|
101
|
+
should_start_new_message = True
|
|
102
|
+
elif isinstance(event, ToolCallCompletedEvent):
|
|
103
|
+
try:
|
|
104
|
+
json_str = json.dumps(event.tool.result, ensure_ascii=False)
|
|
105
|
+
except Exception:
|
|
106
|
+
json_str = str(event.tool.result)
|
|
107
|
+
|
|
108
|
+
data = DataContent(
|
|
109
|
+
data=FunctionCallOutput(
|
|
110
|
+
name=event.tool.tool_name,
|
|
111
|
+
call_id=event.tool.tool_call_id,
|
|
112
|
+
output=json_str,
|
|
113
|
+
).model_dump(),
|
|
114
|
+
)
|
|
115
|
+
message = Message(
|
|
116
|
+
type=MessageType.PLUGIN_CALL_OUTPUT,
|
|
117
|
+
role="tool",
|
|
118
|
+
content=[data],
|
|
119
|
+
)
|
|
120
|
+
yield message.completed()
|
|
121
|
+
|
|
122
|
+
should_start_new_message = True
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""LangGraph adapter for AgentScope runtime."""
|
|
3
|
+
|
|
4
|
+
# todo Message(reasoning) Adapter
|
|
5
|
+
# todo Memory Adapter
|
|
6
|
+
# todo Sandbox Tools Adapter
|
|
7
|
+
from .message import langgraph_msg_to_message, message_to_langgraph_msg
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"langgraph_msg_to_message",
|
|
11
|
+
"message_to_langgraph_msg",
|
|
12
|
+
]
|