agentscope-runtime 0.2.0b2__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 (184) 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/utils/__init__.py +0 -0
  20. agentscope_runtime/common/utils/lazy_loader.py +57 -0
  21. agentscope_runtime/engine/__init__.py +25 -18
  22. agentscope_runtime/engine/app/agent_app.py +161 -91
  23. agentscope_runtime/engine/app/base_app.py +4 -118
  24. agentscope_runtime/engine/constant.py +8 -0
  25. agentscope_runtime/engine/deployers/__init__.py +8 -0
  26. agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
  27. agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
  28. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
  29. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
  30. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
  31. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
  32. agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
  33. agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
  34. agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
  35. agentscope_runtime/engine/deployers/local_deployer.py +47 -74
  36. agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
  37. agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
  38. agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
  39. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
  40. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
  41. agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
  42. agentscope_runtime/engine/deployers/utils/package.py +693 -0
  43. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
  44. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +301 -282
  45. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
  46. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
  47. agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
  48. agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
  49. agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
  50. agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
  51. agentscope_runtime/engine/helpers/runner.py +40 -0
  52. agentscope_runtime/engine/runner.py +171 -130
  53. agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
  54. agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
  55. agentscope_runtime/engine/schemas/oai_llm.py +23 -23
  56. agentscope_runtime/engine/schemas/response_api.py +65 -0
  57. agentscope_runtime/engine/schemas/session.py +24 -0
  58. agentscope_runtime/engine/services/__init__.py +0 -9
  59. agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
  60. agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
  61. agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
  62. agentscope_runtime/engine/services/memory/__init__.py +24 -0
  63. agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
  64. agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
  65. agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
  66. agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
  67. agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
  68. agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
  69. agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
  70. agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
  71. agentscope_runtime/engine/services/session_history/__init__.py +23 -0
  72. agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
  73. agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
  74. agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
  75. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
  76. agentscope_runtime/engine/tracing/base.py +10 -9
  77. agentscope_runtime/engine/tracing/message_util.py +1 -1
  78. agentscope_runtime/engine/tracing/tracing_util.py +7 -2
  79. agentscope_runtime/engine/tracing/wrapper.py +49 -31
  80. agentscope_runtime/sandbox/__init__.py +10 -2
  81. agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
  82. agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
  83. agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
  84. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
  85. agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
  86. agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
  87. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
  88. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
  89. agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
  90. agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
  91. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
  92. agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
  93. agentscope_runtime/sandbox/client/http_client.py +1 -0
  94. agentscope_runtime/sandbox/enums.py +2 -0
  95. agentscope_runtime/sandbox/manager/sandbox_manager.py +15 -2
  96. agentscope_runtime/sandbox/manager/server/app.py +12 -0
  97. agentscope_runtime/sandbox/manager/server/config.py +19 -0
  98. agentscope_runtime/sandbox/model/manager_config.py +79 -2
  99. agentscope_runtime/sandbox/utils.py +0 -18
  100. agentscope_runtime/tools/RAGs/__init__.py +0 -0
  101. agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
  102. agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
  103. agentscope_runtime/tools/__init__.py +119 -0
  104. agentscope_runtime/tools/_constants.py +18 -0
  105. agentscope_runtime/tools/alipay/__init__.py +4 -0
  106. agentscope_runtime/tools/alipay/base.py +334 -0
  107. agentscope_runtime/tools/alipay/payment.py +835 -0
  108. agentscope_runtime/tools/alipay/subscribe.py +551 -0
  109. agentscope_runtime/tools/base.py +264 -0
  110. agentscope_runtime/tools/cli/__init__.py +0 -0
  111. agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
  112. agentscope_runtime/tools/generations/__init__.py +75 -0
  113. agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
  114. agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
  115. agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
  116. agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
  117. agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
  118. agentscope_runtime/tools/generations/image_edit.py +208 -0
  119. agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
  120. agentscope_runtime/tools/generations/image_generation.py +202 -0
  121. agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
  122. agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
  123. agentscope_runtime/tools/generations/image_to_video.py +233 -0
  124. agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
  125. agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
  126. agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
  127. agentscope_runtime/tools/generations/speech_to_text.py +260 -0
  128. agentscope_runtime/tools/generations/speech_to_video.py +314 -0
  129. agentscope_runtime/tools/generations/text_to_video.py +221 -0
  130. agentscope_runtime/tools/mcp_wrapper.py +215 -0
  131. agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
  132. agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
  133. agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
  134. agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
  135. agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
  136. agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
  137. agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
  138. agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
  139. agentscope_runtime/tools/searches/__init__.py +3 -0
  140. agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
  141. agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
  142. agentscope_runtime/tools/utils/__init__.py +0 -0
  143. agentscope_runtime/tools/utils/api_key_util.py +45 -0
  144. agentscope_runtime/tools/utils/crypto_utils.py +99 -0
  145. agentscope_runtime/tools/utils/mcp_util.py +35 -0
  146. agentscope_runtime/version.py +1 -1
  147. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/METADATA +240 -168
  148. agentscope_runtime-1.0.0.dist-info/RECORD +240 -0
  149. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/entry_points.txt +1 -0
  150. agentscope_runtime/engine/agents/__init__.py +0 -2
  151. agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
  152. agentscope_runtime/engine/agents/agno_agent.py +0 -220
  153. agentscope_runtime/engine/agents/autogen_agent.py +0 -250
  154. agentscope_runtime/engine/agents/base_agent.py +0 -29
  155. agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
  156. agentscope_runtime/engine/agents/utils.py +0 -53
  157. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
  158. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  159. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  160. agentscope_runtime/engine/helpers/helper.py +0 -179
  161. agentscope_runtime/engine/schemas/context.py +0 -54
  162. agentscope_runtime/engine/services/context_manager.py +0 -164
  163. agentscope_runtime/engine/services/environment_manager.py +0 -50
  164. agentscope_runtime/engine/services/manager.py +0 -174
  165. agentscope_runtime/engine/services/rag_service.py +0 -195
  166. agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
  167. agentscope_runtime/sandbox/tools/__init__.py +0 -12
  168. agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
  169. agentscope_runtime/sandbox/tools/base/tool.py +0 -52
  170. agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
  171. agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
  172. agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
  173. agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
  174. agentscope_runtime/sandbox/tools/function_tool.py +0 -321
  175. agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
  176. agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
  177. agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
  178. agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
  179. agentscope_runtime/sandbox/tools/tool.py +0 -238
  180. agentscope_runtime/sandbox/tools/utils.py +0 -68
  181. agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
  182. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/WHEEL +0 -0
  183. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/licenses/LICENSE +0 -0
  184. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,21 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # pylint: disable=not-callable
3
+ import asyncio
4
+ import logging
5
+ import inspect
6
+ import traceback
2
7
  import uuid
3
8
  from contextlib import AsyncExitStack
4
- from typing import Optional, List, AsyncGenerator, Any, Union, Dict
5
-
6
- from agentscope_runtime.engine.deployers.utils.service_utils import (
7
- ServicesConfig,
9
+ from typing import (
10
+ Optional,
11
+ List,
12
+ AsyncGenerator,
13
+ Any,
14
+ Union,
15
+ Dict,
16
+ AsyncIterator,
8
17
  )
9
- from .agents import Agent
18
+
10
19
  from .deployers import (
11
20
  DeployManager,
12
21
  LocalDeployManager,
@@ -18,67 +27,93 @@ from .schemas.agent_schemas import (
18
27
  RunStatus,
19
28
  AgentResponse,
20
29
  SequenceNumberGenerator,
30
+ Error,
21
31
  )
22
- from .schemas.context import Context
23
- from .services.context_manager import ContextManager
24
- from .services.environment_manager import EnvironmentManager
25
32
  from .tracing import TraceType
26
33
  from .tracing.wrapper import trace
27
34
  from .tracing.message_util import (
28
35
  merge_agent_response,
29
36
  get_agent_response_finish_reason,
30
37
  )
38
+ from .constant import ALLOWED_FRAMEWORK_TYPES
39
+
40
+
41
+ logger = logging.getLogger(__name__)
31
42
 
32
43
 
33
44
  class Runner:
34
- def __init__(
35
- self,
36
- agent: Agent,
37
- environment_manager: Optional[EnvironmentManager] = None,
38
- context_manager: Optional[ContextManager] = None,
39
- ) -> None:
45
+ def __init__(self) -> None:
40
46
  """
41
- Initializes a runner as core function.
42
- Args:
43
- agent: The agent to run.
44
- environment_manager: The environment manager
45
- context_manager: The context manager
46
- """
47
- self._agent = agent
48
- self._environment_manager = environment_manager
49
- self._context_manager = (
50
- context_manager or ContextManager()
51
- ) # Add default context manager
47
+ Initializes a runner as core instance.
48
+ """
49
+ self.framework_type = None
50
+
52
51
  self._deploy_managers = {}
52
+ self._health = False
53
53
  self._exit_stack = AsyncExitStack()
54
54
 
55
- async def __aenter__(self) -> "Runner":
55
+ async def query_handler(self, *args, **kwargs):
56
56
  """
57
- Initializes the runner and ensures context/environment managers
58
- are fully entered so that attributes like compose_session are
59
- available.
57
+ Handle agent query.
60
58
  """
61
- if self._environment_manager:
62
- # enter_async_context returns the "real" object
63
- self._environment_manager = (
64
- await self._exit_stack.enter_async_context(
65
- self._environment_manager,
66
- )
67
- )
59
+ raise NotImplementedError("query_handler not implemented")
68
60
 
69
- if self._context_manager:
70
- self._context_manager = await self._exit_stack.enter_async_context(
71
- self._context_manager,
72
- )
61
+ async def init_handler(self, *args, **kwargs):
62
+ """
63
+ Init handler.
64
+ """
73
65
 
66
+ async def shutdown_handler(self, *args, **kwargs):
67
+ """
68
+ Shutdown handler.
69
+ """
70
+
71
+ async def start(self):
72
+ init_fn = getattr(self, "init_handler", None)
73
+ if callable(init_fn):
74
+ if inspect.iscoroutinefunction(init_fn):
75
+ await init_fn()
76
+ else:
77
+ init_fn()
78
+ else:
79
+ logger.warning("[Runner] init_handler is not callable")
80
+ self._health = True
74
81
  return self
75
82
 
76
- async def __aexit__(self, exc_type, exc_val, exc_tb):
83
+ async def stop(self):
84
+ shutdown_fn = getattr(self, "shutdown_handler", None)
85
+ try:
86
+ if callable(shutdown_fn):
87
+ if inspect.iscoroutinefunction(shutdown_fn):
88
+ await shutdown_fn()
89
+ else:
90
+ shutdown_fn()
91
+ except Exception as e:
92
+ logger.warning(f"[Runner] Exception in shutdown handler: {e}")
77
93
  try:
78
94
  await self._exit_stack.aclose()
79
95
  except Exception:
80
96
  pass
81
97
 
98
+ self._health = False
99
+
100
+ async def __aenter__(self) -> "Runner":
101
+ """
102
+ Initializes the runner
103
+ """
104
+ await self.start()
105
+ return self
106
+
107
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
108
+ await self.stop()
109
+
110
+ if hasattr(self, "_deploy_manager") and self._deploy_manager:
111
+ for deploy_id in self._deploy_manager:
112
+ await self._deploy_manager[deploy_id].stop()
113
+ else:
114
+ # No deploy manager found, nothing to stop
115
+ pass
116
+
82
117
  async def deploy(
83
118
  self,
84
119
  deploy_manager: DeployManager = LocalDeployManager(),
@@ -90,7 +125,6 @@ class Runner:
90
125
  base_image: str = "python:3.9-slim",
91
126
  environment: Optional[Dict[str, str]] = None,
92
127
  runtime_config: Optional[Dict] = None,
93
- services_config: Optional[Union[ServicesConfig, dict]] = None,
94
128
  **kwargs,
95
129
  ):
96
130
  """
@@ -106,7 +140,6 @@ class Runner:
106
140
  base_image: Docker base image (for containerized deployment)
107
141
  environment: Environment variables dict
108
142
  runtime_config: Runtime configuration dict
109
- services_config: Services configuration dict
110
143
  **kwargs: Additional arguments passed to deployment manager
111
144
  Returns:
112
145
  URL of the deployed service
@@ -124,14 +157,34 @@ class Runner:
124
157
  base_image=base_image,
125
158
  environment=environment,
126
159
  runtime_config=runtime_config,
127
- services_config=services_config,
128
160
  **kwargs,
129
161
  )
130
162
 
131
- # TODO: add redis or other persistant method
163
+ # TODO: add redis or other persistent method
132
164
  self._deploy_managers[deploy_manager.deploy_id] = deploy_result
133
165
  return deploy_result
134
166
 
167
+ async def _call_handler_streaming(self, handler, *args, **kwargs):
168
+ """
169
+ Call handler and yield results in streaming fashion, async or sync.
170
+ """
171
+ result = handler(*args, **kwargs)
172
+
173
+ if inspect.isasyncgenfunction(handler):
174
+ async for item in result:
175
+ yield item
176
+
177
+ elif inspect.isgenerator(result):
178
+ for item in result:
179
+ yield item
180
+
181
+ elif asyncio.iscoroutine(result):
182
+ res = await result
183
+ yield res
184
+
185
+ else:
186
+ yield result
187
+
135
188
  @trace(
136
189
  TraceType.AGENT_STEP,
137
190
  trace_name="agent_step",
@@ -141,115 +194,103 @@ class Runner:
141
194
  async def stream_query( # pylint:disable=unused-argument
142
195
  self,
143
196
  request: Union[AgentRequest, dict],
144
- user_id: Optional[str] = None,
145
- tools: Optional[List] = None,
146
197
  **kwargs: Any,
147
198
  ) -> AsyncGenerator[Event, None]:
148
199
  """
149
200
  Streams the agent.
150
201
  """
202
+ if self.framework_type not in ALLOWED_FRAMEWORK_TYPES:
203
+ raise RuntimeError(
204
+ f"Framework type '{self.framework_type}' is invalid or not "
205
+ f"set. Please set `self.framework_type` to one of:"
206
+ f" {', '.join(ALLOWED_FRAMEWORK_TYPES)}.",
207
+ )
208
+
209
+ if not self._health:
210
+ raise RuntimeError(
211
+ "Runner has not been started. "
212
+ "Please call 'await runner.start()' or use 'async with "
213
+ "Runner()' before calling 'stream_query'.",
214
+ )
215
+
151
216
  if isinstance(request, dict):
152
217
  request = AgentRequest(**request)
153
218
 
219
+ # Assign session ID
220
+ request.session_id = request.session_id or str(uuid.uuid4())
221
+
222
+ # Assign user ID
223
+ request.user_id = request.user_id or request.session_id
224
+
154
225
  seq_gen = SequenceNumberGenerator()
155
226
 
156
227
  # Initial response
157
- response = AgentResponse()
228
+ response = AgentResponse(id=request.id)
229
+ response.session_id = request.session_id
158
230
  yield seq_gen.yield_with_sequence(response)
159
231
 
160
232
  # Set to in-progress status
161
233
  response.in_progress()
162
234
  yield seq_gen.yield_with_sequence(response)
163
235
 
164
- user_id = user_id or str(uuid.uuid4())
165
- session_id = request.session_id or str(uuid.uuid4())
166
- request_input = request.input
167
- session = await self._context_manager.compose_session(
168
- user_id=user_id,
169
- session_id=session_id,
170
- )
236
+ query_kwargs = {
237
+ "request": request,
238
+ }
171
239
 
172
- context = Context(
173
- user_id=session.user_id,
174
- session=session,
175
- request=request,
176
- current_messages=request_input,
177
- context_manager=self._context_manager,
178
- environment_manager=self._environment_manager,
179
- agent=self._agent,
180
- )
240
+ if self.framework_type == "text":
241
+ from ..adapters.text.stream import adapt_text_stream
181
242
 
182
- # TODO: Update activate tools into the context (not schema only)
183
- tools = tools or getattr(self._agent, "tools", None)
184
- if tools:
185
- # Lazy import
186
- from ..sandbox.tools.utils import setup_tools
187
-
188
- activated_tools, schemas = setup_tools(
189
- tools=tools,
190
- environment_manager=context.environment_manager,
191
- session_id=session.id,
192
- user_id=session.user_id,
193
- include_schemas=True,
243
+ stream_adapter = adapt_text_stream
244
+ elif self.framework_type == "agentscope":
245
+ from ..adapters.agentscope.stream import (
246
+ adapt_agentscope_message_stream,
194
247
  )
248
+ from ..adapters.agentscope.message import message_to_agentscope_msg
195
249
 
196
- # update the context
197
- context.activate_tools = activated_tools
250
+ stream_adapter = adapt_agentscope_message_stream
251
+ kwargs.update(
252
+ {"msgs": message_to_agentscope_msg(request.input)},
253
+ )
254
+ # TODO: support other frameworks
255
+ else:
198
256
 
199
- # convert schema to a function call tool lists
200
- # TODO: use pydantic model
201
- if hasattr(context.request, "tools") and context.request.tools:
202
- context.request.tools.extend(schemas)
257
+ def identity_stream_adapter(
258
+ source_stream: AsyncIterator[Any],
259
+ ) -> AsyncIterator[Any]:
260
+ return source_stream
203
261
 
204
- # update message in session
205
- await context.context_manager.compose_context(
206
- session=context.session,
207
- request_input=request_input,
208
- )
262
+ stream_adapter = identity_stream_adapter
209
263
 
210
- async for event in context.agent.run_async(context):
211
- if (
212
- event.status == RunStatus.Completed
213
- and event.object == "message"
264
+ try:
265
+ async for event in stream_adapter(
266
+ source_stream=self._call_handler_streaming(
267
+ self.query_handler,
268
+ **query_kwargs,
269
+ **kwargs,
270
+ ),
214
271
  ):
215
- response.add_new_message(event)
216
- yield seq_gen.yield_with_sequence(event)
217
-
218
- await context.context_manager.append(
219
- session=context.session,
220
- event_output=response.output,
221
- )
222
- yield seq_gen.yield_with_sequence(response.completed())
223
-
224
- # TODO: will be added before 2025/11/30
225
- # @trace(TraceType.AGENT_STEP)
226
- # async def query( # pylint:disable=unused-argument
227
- # self,
228
- # message: List[dict],
229
- # session_id: Optional[str] = None,
230
- # **kwargs: Any,
231
- # ) -> ChatCompletion:
232
- # """
233
- # Streams the agent.
234
- # """
235
- # return self._agent.query(message, session_id)
236
-
237
- # TODO: should be sync method?
238
- async def stop(
239
- self,
240
- deploy_id: str,
241
- ) -> None:
242
- """
243
- Stops the agent service.
244
-
245
- Args:
246
- deploy_id: Optional deploy ID (not used for service shutdown)
272
+ if (
273
+ event.status == RunStatus.Completed
274
+ and event.object == "message"
275
+ ):
276
+ response.add_new_message(event)
277
+ yield seq_gen.yield_with_sequence(event)
278
+ except Exception as e:
279
+ # TODO: fix code
280
+ error = Error(
281
+ code="500",
282
+ message=f"Error happens in `query_handler`: {e}",
283
+ )
284
+ logger.error(f"{error.model_dump()}: {traceback.format_exc()}")
285
+ yield seq_gen.yield_with_sequence(response.failed(error))
286
+ return
247
287
 
248
- Raises:
249
- RuntimeError: If stopping fails
250
- """
251
- if hasattr(self, "_deploy_manager") and self._deploy_manager:
252
- await self._deploy_manager[deploy_id].stop()
253
- else:
254
- # No deploy manager found, nothing to stop
288
+ # Obtain token usage
289
+ try:
290
+ if response.output:
291
+ response.usage = response.output[-1].usage
292
+ except IndexError:
293
+ # Avoid empty message
255
294
  pass
295
+
296
+ yield seq_gen.yield_with_sequence(response.completed())
@@ -11,7 +11,7 @@ except ImportError:
11
11
  from typing_extensions import Self
12
12
  from uuid import uuid4
13
13
 
14
- from pydantic import BaseModel, Field, field_validator
14
+ from pydantic import BaseModel, Field, field_validator, ConfigDict
15
15
  from openai.types.chat import ChatCompletionChunk
16
16
 
17
17
 
@@ -144,10 +144,79 @@ class FunctionCallOutput(BaseModel):
144
144
  call_id: str
145
145
  """The ID of the tool call."""
146
146
 
147
+ name: Optional[str] = None
148
+ """The name of the tool call."""
149
+
147
150
  output: str
148
151
  """The result of the function."""
149
152
 
150
153
 
154
+ class McpCall(BaseModel):
155
+ id: str
156
+ """The unique ID of the tool call."""
157
+
158
+ arguments: str
159
+ """A JSON string of the arguments passed to the tool."""
160
+
161
+ name: str
162
+ """The name of the tool that was run."""
163
+
164
+ server_label: str
165
+ """The label of the MCP server running the tool."""
166
+
167
+ error: Optional[str] = None
168
+ """The error from the tool call, if any."""
169
+
170
+ output: Optional[str] = None
171
+ """The output from the tool call."""
172
+
173
+
174
+ class McpListToolsTool(BaseModel):
175
+ input_schema: object
176
+ """The JSON schema describing the tool's input."""
177
+
178
+ name: str
179
+ """The name of the tool."""
180
+
181
+ annotations: Optional[object] = None
182
+ """Additional annotations about the tool."""
183
+
184
+ description: Optional[str] = None
185
+ """The description of the tool."""
186
+
187
+
188
+ class McpListTools(BaseModel):
189
+ id: str
190
+ """The unique ID of the list."""
191
+
192
+ server_label: str
193
+ """The label of the MCP server."""
194
+
195
+ tools: List[McpListToolsTool]
196
+ """The tools available on the server."""
197
+
198
+ error: Optional[str] = None
199
+ """Error message if the server could not list tools."""
200
+
201
+
202
+ class McpApprovalRequest(BaseModel):
203
+ """
204
+ mcp approval request
205
+ """
206
+
207
+ id: str
208
+ """The unique ID of the approval request."""
209
+
210
+ arguments: str
211
+ """A json string of arguments for the tool."""
212
+
213
+ name: str
214
+ """The name of the tool to run."""
215
+
216
+ server_label: str
217
+ """The label of the mcp server making the request."""
218
+
219
+
151
220
  class Error(BaseModel):
152
221
  code: str
153
222
  """The error code of the message."""
@@ -393,6 +462,8 @@ class Message(Event):
393
462
  usage: Optional[Dict] = None
394
463
  """response usage for output"""
395
464
 
465
+ metadata: Optional[Dict] = None
466
+
396
467
  @staticmethod
397
468
  def from_openai_message(message: Union[BaseModel, dict]) -> "Message":
398
469
  """Create a message object from an openai message."""
@@ -627,10 +698,50 @@ class BaseRequest(BaseModel):
627
698
  stream: bool = True
628
699
  """If set, partial message deltas will be sent, like in ChatGPT. """
629
700
 
701
+ id: Optional[str] = None
702
+ """request unique id"""
703
+
630
704
 
631
705
  class AgentRequest(BaseRequest):
632
706
  """agent request"""
633
707
 
708
+ model_config = ConfigDict(
709
+ extra="allow",
710
+ json_schema_extra={
711
+ "example": {
712
+ "input": [
713
+ {
714
+ "role": "user",
715
+ "type": "message",
716
+ "content": [{"type": "text", "text": "hello"}],
717
+ },
718
+ {
719
+ "type": "message",
720
+ "role": "assistant",
721
+ "content": [
722
+ {
723
+ "object": "content",
724
+ "type": "text",
725
+ "text": "Hello! How can I assist you today?",
726
+ },
727
+ ],
728
+ },
729
+ {
730
+ "role": "user",
731
+ "type": "message",
732
+ "content": [
733
+ {
734
+ "type": "text",
735
+ "text": "What is the capital of France?",
736
+ },
737
+ ],
738
+ },
739
+ ],
740
+ "session_id": "1764056632961",
741
+ },
742
+ },
743
+ )
744
+
634
745
  model: Optional[str] = None
635
746
  """
636
747
  model id
@@ -702,8 +813,8 @@ class AgentRequest(BaseRequest):
702
813
  session_id: Optional[str] = None
703
814
  """conversation id for dialog"""
704
815
 
705
- response_id: Optional[str] = None
706
- """response unique id"""
816
+ user_id: Optional[str] = None
817
+ """User id for dialog"""
707
818
 
708
819
 
709
820
  class BaseResponse(Event):
@@ -220,7 +220,8 @@ class RagOptions(BaseModel):
220
220
  """Whether to enable hybrid generations."""
221
221
 
222
222
  @field_validator("prompt_strategy")
223
- def prompt_strategy_check(self, value: str) -> str:
223
+ @classmethod
224
+ def prompt_strategy_check(cls, value: str) -> str:
224
225
  if value:
225
226
  value = value.lower()
226
227
  if value in ["topk", "top_k"]:
@@ -228,7 +229,8 @@ class RagOptions(BaseModel):
228
229
  return value
229
230
 
230
231
  @field_validator("maximum_allowed_chunk_num")
231
- def maximum_allowed_chunk_num_check(self, value: int) -> int:
232
+ @classmethod
233
+ def maximum_allowed_chunk_num_check(cls, value: int) -> int:
232
234
  if value < int(PARAM_MAXIMUM_ALLOWED_CHUNK_NUM_MIN) or value > int(
233
235
  PARAM_MAXIMUM_ALLOWED_CHUNK_NUM_MAX,
234
236
  ):
@@ -116,7 +116,7 @@ class OpenAIMessage(BaseModel):
116
116
  """The role of the messages author, should be in `user`,`system`,
117
117
  'assistant', 'tool'."""
118
118
 
119
- content: Optional[Union[str, List[ChatCompletionMessage]]] = None
119
+ content: Optional[Union[List[ChatCompletionMessage], str]] = None
120
120
  """The contents of the message.
121
121
 
122
122
  Can be a string, a list of content parts for multimodal messages.
@@ -137,7 +137,7 @@ class OpenAIMessage(BaseModel):
137
137
  Extract the first text content from the message.
138
138
 
139
139
  :return: First text string found in the content, or None if no text
140
- content
140
+ content.
141
141
  """
142
142
  if self.content is None:
143
143
  return None
@@ -158,7 +158,7 @@ class OpenAIMessage(BaseModel):
158
158
  Extract all image content (URLs or base64 data) from the message.
159
159
 
160
160
  :return: List of image URLs or base64 encoded strings found in the
161
- content
161
+ content.
162
162
  """
163
163
  images = []
164
164
 
@@ -183,7 +183,7 @@ class OpenAIMessage(BaseModel):
183
183
  Extract all audio content (URLs or base64 data) from the message.
184
184
 
185
185
  :return: List of audio URLs or base64 encoded strings found in the
186
- content
186
+ content.
187
187
  """
188
188
  audios = []
189
189
 
@@ -307,34 +307,34 @@ class ResponseFormat(BaseModel):
307
307
  """The type of response format being defined.
308
308
 
309
309
  - `text`: The default response format, which can be either text or any
310
- value needed.
310
+ value needed.
311
311
  - `json_object`: Enables JSON mode, which guarantees the message the model
312
- generates is valid JSON.
312
+ generates is valid JSON.
313
313
  - `json_schema`: Enables Structured Outputs which guarantees the model will
314
- match your supplied JSON schema.
314
+ match your supplied JSON schema.
315
315
  """
316
316
 
317
317
  json_schema: Optional[JsonSchema] = None
318
318
  """The JSON schema for the response format."""
319
319
 
320
- @model_validator(mode="before")
321
- def validate_schema(self, values: dict) -> dict:
322
- if not isinstance(values, dict) or "type" not in values:
323
- raise ValueError(f"Json schema not valid with type {type(values)}")
324
- format_type = values.get("type")
325
- json_schema = values.get("json_schema")
326
-
327
- if format_type in ["text", "json_object"] and json_schema is not None:
320
+ @model_validator(mode="after")
321
+ def validate_schema(self) -> "ResponseFormat":
322
+ if (
323
+ self.type
324
+ in [
325
+ "text",
326
+ "json_object",
327
+ ]
328
+ and self.json_schema is not None
329
+ ):
328
330
  raise ValueError(
329
- f"Json schema is not allowed for type {format_type}",
331
+ f"Json schema is not allowed for type {self.type}",
330
332
  )
331
-
332
- if format_type == "json_schema":
333
- if json_schema is None:
334
- raise ValueError(
335
- f"Json schema is required for type {format_type}",
336
- )
337
- return values
333
+ if self.type == "json_schema" and self.json_schema is None:
334
+ raise ValueError(
335
+ f"Json schema is required for type {self.type}",
336
+ )
337
+ return self
338
338
 
339
339
 
340
340
  class ToolChoiceInputFunction(BaseModel):