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
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint:disable=too-many-branches,too-many-statements,too-many-return-statements
|
|
3
|
+
"""Message conversion between LangGraph and AgentScope runtime."""
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from collections import OrderedDict
|
|
7
|
+
from typing import Union, List
|
|
8
|
+
|
|
9
|
+
from langchain_core.messages import (
|
|
10
|
+
AIMessage,
|
|
11
|
+
HumanMessage,
|
|
12
|
+
SystemMessage,
|
|
13
|
+
ToolMessage,
|
|
14
|
+
BaseMessage,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from ...engine.schemas.agent_schemas import (
|
|
18
|
+
Message,
|
|
19
|
+
FunctionCall,
|
|
20
|
+
MessageType,
|
|
21
|
+
)
|
|
22
|
+
from ...engine.helpers.agent_api_builder import ResponseBuilder
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def langgraph_msg_to_message(
|
|
26
|
+
messages: Union[BaseMessage, List[BaseMessage]],
|
|
27
|
+
) -> List[Message]:
|
|
28
|
+
"""
|
|
29
|
+
Convert LangGraph BaseMessage(s) into one or more runtime Message objects
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
messages: LangGraph message(s) from streaming.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
List[Message]: One or more constructed runtime Message objects.
|
|
36
|
+
"""
|
|
37
|
+
if isinstance(messages, BaseMessage):
|
|
38
|
+
msgs = [messages]
|
|
39
|
+
elif isinstance(messages, list):
|
|
40
|
+
msgs = messages
|
|
41
|
+
else:
|
|
42
|
+
raise TypeError(
|
|
43
|
+
f"Expected BaseMessage or list[BaseMessage], got {type(messages)}",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
results: List[Message] = []
|
|
47
|
+
|
|
48
|
+
for msg in msgs:
|
|
49
|
+
# Map LangGraph roles to runtime roles
|
|
50
|
+
if isinstance(msg, HumanMessage):
|
|
51
|
+
role = "user"
|
|
52
|
+
elif isinstance(msg, AIMessage):
|
|
53
|
+
role = "assistant"
|
|
54
|
+
elif isinstance(msg, SystemMessage):
|
|
55
|
+
role = "system"
|
|
56
|
+
elif isinstance(msg, ToolMessage):
|
|
57
|
+
role = "tool"
|
|
58
|
+
else:
|
|
59
|
+
role = "assistant" # default fallback
|
|
60
|
+
|
|
61
|
+
# Handle tool calls in AIMessage
|
|
62
|
+
if isinstance(msg, AIMessage) and msg.tool_calls:
|
|
63
|
+
# Convert each tool call to a PLUGIN_CALL message
|
|
64
|
+
for tool_call in msg.tool_calls:
|
|
65
|
+
rb = ResponseBuilder()
|
|
66
|
+
mb = rb.create_message_builder(
|
|
67
|
+
role=role,
|
|
68
|
+
message_type=MessageType.PLUGIN_CALL,
|
|
69
|
+
)
|
|
70
|
+
# Add metadata
|
|
71
|
+
mb.message.metadata = {
|
|
72
|
+
"original_id": getattr(msg, "id", None),
|
|
73
|
+
"name": getattr(msg, "name", None),
|
|
74
|
+
"metadata": getattr(msg, "additional_kwargs", {}),
|
|
75
|
+
}
|
|
76
|
+
cb = mb.create_content_builder(content_type="data")
|
|
77
|
+
|
|
78
|
+
call_data = FunctionCall(
|
|
79
|
+
call_id=tool_call.get("id", ""),
|
|
80
|
+
name=tool_call.get("name", ""),
|
|
81
|
+
arguments=json.dumps(tool_call.get("args", {})),
|
|
82
|
+
).model_dump()
|
|
83
|
+
cb.set_data(call_data)
|
|
84
|
+
cb.complete()
|
|
85
|
+
mb.complete()
|
|
86
|
+
results.append(mb.get_message_data())
|
|
87
|
+
|
|
88
|
+
# If there's content in addition to tool calls,
|
|
89
|
+
# create a separate message
|
|
90
|
+
if msg.content:
|
|
91
|
+
rb = ResponseBuilder()
|
|
92
|
+
mb = rb.create_message_builder(
|
|
93
|
+
role=role,
|
|
94
|
+
message_type=MessageType.MESSAGE,
|
|
95
|
+
)
|
|
96
|
+
mb.message.metadata = {
|
|
97
|
+
"original_id": getattr(msg, "id", None),
|
|
98
|
+
"name": getattr(msg, "name", None),
|
|
99
|
+
"metadata": getattr(msg, "additional_kwargs", {}),
|
|
100
|
+
}
|
|
101
|
+
cb = mb.create_content_builder(content_type="text")
|
|
102
|
+
cb.set_text(str(msg.content))
|
|
103
|
+
cb.complete()
|
|
104
|
+
mb.complete()
|
|
105
|
+
results.append(mb.get_message_data())
|
|
106
|
+
else:
|
|
107
|
+
# Regular message conversion
|
|
108
|
+
rb = ResponseBuilder()
|
|
109
|
+
mb = rb.create_message_builder(
|
|
110
|
+
role=role,
|
|
111
|
+
message_type=MessageType.MESSAGE,
|
|
112
|
+
)
|
|
113
|
+
# Add metadata
|
|
114
|
+
mb.message.metadata = {
|
|
115
|
+
"original_id": getattr(msg, "id", None),
|
|
116
|
+
"name": getattr(msg, "name", None),
|
|
117
|
+
"metadata": getattr(msg, "additional_kwargs", {}),
|
|
118
|
+
}
|
|
119
|
+
cb = mb.create_content_builder(content_type="text")
|
|
120
|
+
cb.set_text(str(msg.content) if msg.content else "")
|
|
121
|
+
cb.complete()
|
|
122
|
+
mb.complete()
|
|
123
|
+
results.append(mb.get_message_data())
|
|
124
|
+
|
|
125
|
+
return results
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def message_to_langgraph_msg(
|
|
129
|
+
messages: Union[Message, List[Message]],
|
|
130
|
+
) -> Union[BaseMessage, List[BaseMessage]]:
|
|
131
|
+
"""
|
|
132
|
+
Convert AgentScope runtime Message(s) to LangGraph BaseMessage(s).
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
messages: A single AgentScope runtime Message or list of Messages.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
A single BaseMessage object or a list of BaseMessage objects.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def _convert_one(message: Message) -> BaseMessage:
|
|
142
|
+
# Map runtime roles to LangGraph roles
|
|
143
|
+
role_map = {
|
|
144
|
+
"user": HumanMessage,
|
|
145
|
+
"assistant": AIMessage,
|
|
146
|
+
"system": SystemMessage,
|
|
147
|
+
"tool": ToolMessage,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
message_cls = role_map.get(
|
|
151
|
+
message.role,
|
|
152
|
+
AIMessage,
|
|
153
|
+
) # default to AIMessage
|
|
154
|
+
|
|
155
|
+
# Handle different message types
|
|
156
|
+
if message.type in (
|
|
157
|
+
MessageType.PLUGIN_CALL,
|
|
158
|
+
MessageType.FUNCTION_CALL,
|
|
159
|
+
):
|
|
160
|
+
# Convert PLUGIN_CALL, FUNCTION_CALL to AIMessage with tool_calls
|
|
161
|
+
if message.content and hasattr(message.content[0], "data"):
|
|
162
|
+
try:
|
|
163
|
+
func_call_data = message.content[0].data
|
|
164
|
+
tool_calls = [
|
|
165
|
+
{
|
|
166
|
+
"name": func_call_data.get("name", ""),
|
|
167
|
+
"args": json.loads(
|
|
168
|
+
func_call_data.get("arguments", "{}"),
|
|
169
|
+
),
|
|
170
|
+
"id": func_call_data.get("call_id", ""),
|
|
171
|
+
},
|
|
172
|
+
]
|
|
173
|
+
return AIMessage(content="", tool_calls=tool_calls)
|
|
174
|
+
except (json.JSONDecodeError, KeyError):
|
|
175
|
+
return message_cls(content=str(message.content))
|
|
176
|
+
else:
|
|
177
|
+
return message_cls(content="")
|
|
178
|
+
|
|
179
|
+
elif message.type in (
|
|
180
|
+
MessageType.PLUGIN_CALL_OUTPUT,
|
|
181
|
+
MessageType.FUNCTION_CALL_OUTPUT,
|
|
182
|
+
):
|
|
183
|
+
# Convert PLUGIN_CALL_OUTPUT, FUNCTION_CALL_OUTPUT to ToolMessage
|
|
184
|
+
if message.content and hasattr(message.content[0], "data"):
|
|
185
|
+
try:
|
|
186
|
+
func_output_data = message.content[0].data
|
|
187
|
+
tool_call_id = func_output_data.get("call_id", "")
|
|
188
|
+
content = func_output_data.get("output", "")
|
|
189
|
+
# Try to parse JSON output
|
|
190
|
+
try:
|
|
191
|
+
content = json.loads(content)
|
|
192
|
+
except json.JSONDecodeError:
|
|
193
|
+
pass
|
|
194
|
+
return ToolMessage(
|
|
195
|
+
content=content,
|
|
196
|
+
tool_call_id=tool_call_id,
|
|
197
|
+
)
|
|
198
|
+
except KeyError:
|
|
199
|
+
return message_cls(content=str(message.content))
|
|
200
|
+
else:
|
|
201
|
+
return message_cls(content="")
|
|
202
|
+
|
|
203
|
+
else:
|
|
204
|
+
# Regular message conversion
|
|
205
|
+
content = ""
|
|
206
|
+
if message.content:
|
|
207
|
+
# Concatenate all content parts
|
|
208
|
+
content_parts = []
|
|
209
|
+
for cnt in message.content:
|
|
210
|
+
if hasattr(cnt, "text"):
|
|
211
|
+
content_parts.append(cnt.text)
|
|
212
|
+
elif hasattr(cnt, "data"):
|
|
213
|
+
content_parts.append(str(cnt.data))
|
|
214
|
+
content = (
|
|
215
|
+
"".join(content_parts)
|
|
216
|
+
if content_parts
|
|
217
|
+
else str(message.content)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# For ToolMessage, we need tool_call_id
|
|
221
|
+
if message_cls == ToolMessage:
|
|
222
|
+
tool_call_id = ""
|
|
223
|
+
if hasattr(message, "metadata") and isinstance(
|
|
224
|
+
message.metadata,
|
|
225
|
+
dict,
|
|
226
|
+
):
|
|
227
|
+
tool_call_id = message.metadata.get("tool_call_id", "")
|
|
228
|
+
return ToolMessage(content=content, tool_call_id=tool_call_id)
|
|
229
|
+
|
|
230
|
+
return message_cls(content=content)
|
|
231
|
+
|
|
232
|
+
# Handle single or list input
|
|
233
|
+
if isinstance(messages, Message):
|
|
234
|
+
return _convert_one(messages)
|
|
235
|
+
elif isinstance(messages, list):
|
|
236
|
+
converted_list = [_convert_one(m) for m in messages]
|
|
237
|
+
|
|
238
|
+
# Group by original_id for messages that should be combined
|
|
239
|
+
grouped = OrderedDict()
|
|
240
|
+
for msg, orig_msg in zip(messages, converted_list):
|
|
241
|
+
metadata = getattr(msg, "metadata", {})
|
|
242
|
+
if metadata:
|
|
243
|
+
orig_id = metadata.get("original_id", getattr(msg, "id", None))
|
|
244
|
+
else:
|
|
245
|
+
orig_id = getattr(msg, "id", None)
|
|
246
|
+
|
|
247
|
+
if orig_id and orig_id not in grouped:
|
|
248
|
+
grouped[orig_id] = orig_msg
|
|
249
|
+
# For now, we won't combine messages as LangGraph messages
|
|
250
|
+
# are typically separate,
|
|
251
|
+
# But we keep the structure in case we need it later
|
|
252
|
+
|
|
253
|
+
return list(grouped.values()) if grouped else converted_list
|
|
254
|
+
else:
|
|
255
|
+
raise TypeError(
|
|
256
|
+
f"Expected Message or list[Message], got {type(messages)}",
|
|
257
|
+
)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=too-many-branches,too-many-statements
|
|
3
|
+
# pylint: disable=simplifiable-if-expression
|
|
4
|
+
"""Streaming adapter for LangGraph messages."""
|
|
5
|
+
import json
|
|
6
|
+
from functools import reduce
|
|
7
|
+
|
|
8
|
+
from typing import AsyncIterator, Tuple
|
|
9
|
+
|
|
10
|
+
from langchain_core.messages import (
|
|
11
|
+
BaseMessage,
|
|
12
|
+
AIMessage,
|
|
13
|
+
HumanMessage,
|
|
14
|
+
SystemMessage,
|
|
15
|
+
ToolMessage,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from ...engine.schemas.agent_schemas import (
|
|
19
|
+
Message,
|
|
20
|
+
TextContent,
|
|
21
|
+
DataContent,
|
|
22
|
+
FunctionCall,
|
|
23
|
+
FunctionCallOutput,
|
|
24
|
+
MessageType,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def adapt_langgraph_message_stream(
|
|
29
|
+
source_stream: AsyncIterator[Tuple[BaseMessage, bool]],
|
|
30
|
+
) -> AsyncIterator[Message]:
|
|
31
|
+
"""
|
|
32
|
+
Optimized version of the stream adapter for LangGraph messages.
|
|
33
|
+
Reduces code duplication and improves clarity.
|
|
34
|
+
"""
|
|
35
|
+
# Track message IDs to detect new messages
|
|
36
|
+
msg_id = None
|
|
37
|
+
index = None
|
|
38
|
+
|
|
39
|
+
# Track tool usage
|
|
40
|
+
tool_started = False
|
|
41
|
+
tool_call_chunk_msgs = []
|
|
42
|
+
|
|
43
|
+
async for msg, last in source_stream:
|
|
44
|
+
# Determine message role
|
|
45
|
+
if isinstance(msg, HumanMessage):
|
|
46
|
+
role = "user"
|
|
47
|
+
content = msg.content if hasattr(msg, "content") else None
|
|
48
|
+
if msg_id != getattr(msg, "id"):
|
|
49
|
+
message = Message(type=MessageType.MESSAGE, role=role)
|
|
50
|
+
yield message.in_progress()
|
|
51
|
+
msg_id = getattr(msg, "id")
|
|
52
|
+
if content:
|
|
53
|
+
text_delta_content = TextContent(
|
|
54
|
+
delta=True,
|
|
55
|
+
index=None,
|
|
56
|
+
text=content,
|
|
57
|
+
)
|
|
58
|
+
text_delta_content = message.add_delta_content(
|
|
59
|
+
new_content=text_delta_content,
|
|
60
|
+
)
|
|
61
|
+
yield text_delta_content
|
|
62
|
+
yield message.completed()
|
|
63
|
+
elif isinstance(msg, AIMessage):
|
|
64
|
+
role = "assistant"
|
|
65
|
+
has_tool_call_chunk = (
|
|
66
|
+
True if getattr(msg, "tool_call_chunks") else False
|
|
67
|
+
)
|
|
68
|
+
is_last_chunk = (
|
|
69
|
+
True if getattr(msg, "chunk_position") == "last" else False
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Extract tool calls if present
|
|
73
|
+
if tool_started:
|
|
74
|
+
if has_tool_call_chunk:
|
|
75
|
+
tool_call_chunk_msgs.append(msg)
|
|
76
|
+
if is_last_chunk:
|
|
77
|
+
# tool call finished
|
|
78
|
+
tool_started = False
|
|
79
|
+
result = reduce(lambda x, y: x + y, tool_call_chunk_msgs)
|
|
80
|
+
tool_calls = result.tool_call_chunks
|
|
81
|
+
for tool_call in tool_calls:
|
|
82
|
+
call_id = tool_call.get("id", "")
|
|
83
|
+
# Create new tool call message
|
|
84
|
+
plugin_call_message = Message(
|
|
85
|
+
type=MessageType.PLUGIN_CALL,
|
|
86
|
+
role=role,
|
|
87
|
+
)
|
|
88
|
+
data_content = DataContent(
|
|
89
|
+
index=index,
|
|
90
|
+
data=FunctionCall(
|
|
91
|
+
call_id=call_id,
|
|
92
|
+
name=tool_call.get("name", ""),
|
|
93
|
+
arguments=json.dumps(
|
|
94
|
+
tool_call.get("args", {}),
|
|
95
|
+
ensure_ascii=False,
|
|
96
|
+
),
|
|
97
|
+
).model_dump(),
|
|
98
|
+
delta=True,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
data_content = plugin_call_message.add_delta_content(
|
|
102
|
+
new_content=data_content,
|
|
103
|
+
)
|
|
104
|
+
yield data_content
|
|
105
|
+
yield plugin_call_message.completed()
|
|
106
|
+
else:
|
|
107
|
+
if has_tool_call_chunk:
|
|
108
|
+
# tool call start, collect chunks and continue
|
|
109
|
+
tool_started = True
|
|
110
|
+
tool_call_chunk_msgs.append(msg)
|
|
111
|
+
else:
|
|
112
|
+
# normal message
|
|
113
|
+
content = msg.content if hasattr(msg, "content") else None
|
|
114
|
+
if msg_id != getattr(msg, "id"):
|
|
115
|
+
index = None
|
|
116
|
+
message = Message(type=MessageType.MESSAGE, role=role)
|
|
117
|
+
msg_id = getattr(msg, "id")
|
|
118
|
+
yield message.in_progress()
|
|
119
|
+
|
|
120
|
+
if content:
|
|
121
|
+
# todo support non str content
|
|
122
|
+
text_delta_content = TextContent(
|
|
123
|
+
delta=True,
|
|
124
|
+
index=index,
|
|
125
|
+
text=content,
|
|
126
|
+
)
|
|
127
|
+
text_delta_content = message.add_delta_content(
|
|
128
|
+
new_content=text_delta_content,
|
|
129
|
+
)
|
|
130
|
+
index = text_delta_content.index
|
|
131
|
+
yield text_delta_content
|
|
132
|
+
# Handle final completion
|
|
133
|
+
if last:
|
|
134
|
+
# completed_content = message.content[index]
|
|
135
|
+
# if completed_content.text:
|
|
136
|
+
# yield completed_content.completed()
|
|
137
|
+
yield message.completed()
|
|
138
|
+
elif isinstance(msg, SystemMessage):
|
|
139
|
+
role = "system"
|
|
140
|
+
content = msg.content if hasattr(msg, "content") else None
|
|
141
|
+
if msg_id != getattr(msg, "id"):
|
|
142
|
+
message = Message(type=MessageType.MESSAGE, role=role)
|
|
143
|
+
yield message.in_progress()
|
|
144
|
+
msg_id = getattr(msg, "id")
|
|
145
|
+
if content:
|
|
146
|
+
text_delta_content = TextContent(
|
|
147
|
+
delta=True,
|
|
148
|
+
index=None,
|
|
149
|
+
text=content,
|
|
150
|
+
)
|
|
151
|
+
text_delta_content = message.add_delta_content(
|
|
152
|
+
new_content=text_delta_content,
|
|
153
|
+
)
|
|
154
|
+
yield text_delta_content
|
|
155
|
+
elif isinstance(msg, ToolMessage):
|
|
156
|
+
role = "tool"
|
|
157
|
+
content = msg.content if hasattr(msg, "content") else None
|
|
158
|
+
if msg_id != getattr(msg, "id"):
|
|
159
|
+
message = Message(type=MessageType.MESSAGE, role=role)
|
|
160
|
+
yield message.in_progress()
|
|
161
|
+
msg_id = getattr(msg, "id")
|
|
162
|
+
plugin_output_message = Message(
|
|
163
|
+
type=MessageType.PLUGIN_CALL_OUTPUT,
|
|
164
|
+
role="tool",
|
|
165
|
+
)
|
|
166
|
+
# Create function call output data
|
|
167
|
+
function_output_data = FunctionCallOutput(
|
|
168
|
+
call_id=msg.tool_call_id,
|
|
169
|
+
name=msg.name,
|
|
170
|
+
output=json.dumps(content, ensure_ascii=False),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
data_content = DataContent(
|
|
174
|
+
index=None,
|
|
175
|
+
data=function_output_data.model_dump(),
|
|
176
|
+
)
|
|
177
|
+
plugin_output_message.content = [data_content]
|
|
178
|
+
yield plugin_output_message.completed()
|
|
179
|
+
else:
|
|
180
|
+
role = "assistant"
|
|
181
|
+
content = msg.content if hasattr(msg, "content") else None
|
|
182
|
+
if msg_id != getattr(msg, "id"):
|
|
183
|
+
index = None
|
|
184
|
+
message = Message(type=MessageType.MESSAGE, role=role)
|
|
185
|
+
msg_id = getattr(msg, "id")
|
|
186
|
+
yield message.in_progress()
|
|
187
|
+
|
|
188
|
+
if content:
|
|
189
|
+
# todo support non str content
|
|
190
|
+
text_delta_content = TextContent(
|
|
191
|
+
delta=True,
|
|
192
|
+
index=index,
|
|
193
|
+
text=content,
|
|
194
|
+
)
|
|
195
|
+
text_delta_content = message.add_delta_content(
|
|
196
|
+
new_content=text_delta_content,
|
|
197
|
+
)
|
|
198
|
+
index = text_delta_content.index
|
|
199
|
+
yield text_delta_content
|
|
200
|
+
# Handle final completion
|
|
201
|
+
if last:
|
|
202
|
+
# completed_content = message.content[index]
|
|
203
|
+
# if completed_content.text:
|
|
204
|
+
# yield completed_content.completed()
|
|
205
|
+
yield message.completed()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""AgentScope Runtime CLI - Main entry point."""
|
|
3
|
+
# pylint: disable=no-value-for-parameter
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
# Import command groups (to be registered below)
|
|
10
|
+
from agentscope_runtime.cli.commands import (
|
|
11
|
+
chat,
|
|
12
|
+
run,
|
|
13
|
+
web,
|
|
14
|
+
deploy,
|
|
15
|
+
list_cmd,
|
|
16
|
+
status,
|
|
17
|
+
stop,
|
|
18
|
+
invoke,
|
|
19
|
+
sandbox,
|
|
20
|
+
)
|
|
21
|
+
from agentscope_runtime.version import __version__
|
|
22
|
+
|
|
23
|
+
# Set default environment variable for trace console output
|
|
24
|
+
# This must be set BEFORE importing any runtime modules
|
|
25
|
+
# Individual commands can override this for verbose mode
|
|
26
|
+
if "TRACE_ENABLE_LOG" not in os.environ:
|
|
27
|
+
os.environ.setdefault("TRACE_ENABLE_LOG", "false")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@click.group()
|
|
31
|
+
@click.version_option(version=__version__, prog_name="agentscope")
|
|
32
|
+
@click.pass_context
|
|
33
|
+
def cli(ctx):
|
|
34
|
+
"""
|
|
35
|
+
AgentScope Runtime - Unified CLI for agent lifecycle management.
|
|
36
|
+
|
|
37
|
+
Manage your agent development, deployment, and runtime operations
|
|
38
|
+
from a single command.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
# Ensure context object exists
|
|
42
|
+
ctx.ensure_object(dict)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Register commands
|
|
46
|
+
cli.add_command(chat.chat)
|
|
47
|
+
cli.add_command(run.run)
|
|
48
|
+
cli.add_command(web.web)
|
|
49
|
+
cli.add_command(deploy.deploy)
|
|
50
|
+
cli.add_command(list_cmd.list_deployments)
|
|
51
|
+
cli.add_command(status.status)
|
|
52
|
+
cli.add_command(stop.stop)
|
|
53
|
+
cli.add_command(invoke.invoke)
|
|
54
|
+
cli.add_command(sandbox.sandbox)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main():
|
|
58
|
+
"""Entry point for console script."""
|
|
59
|
+
cli(obj={})
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
main()
|