agentscope-runtime 0.2.0b2__py3-none-any.whl → 1.0.0b1__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/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/_long_term_memory_adapter.py +258 -0
- agentscope_runtime/adapters/agentscope/memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/memory/_memory_adapter.py +152 -0
- agentscope_runtime/adapters/agentscope/message.py +535 -0
- agentscope_runtime/adapters/agentscope/stream.py +474 -0
- agentscope_runtime/adapters/agentscope/tool/__init__.py +9 -0
- agentscope_runtime/adapters/agentscope/tool/sandbox_tool.py +69 -0
- agentscope_runtime/adapters/agentscope/tool/tool.py +233 -0
- agentscope_runtime/adapters/autogen/__init__.py +0 -0
- agentscope_runtime/adapters/autogen/tool/__init__.py +7 -0
- agentscope_runtime/adapters/autogen/tool/tool.py +211 -0
- agentscope_runtime/adapters/text/__init__.py +0 -0
- agentscope_runtime/adapters/text/stream.py +29 -0
- agentscope_runtime/common/collections/redis_mapping.py +4 -1
- agentscope_runtime/common/container_clients/fc_client.py +855 -0
- agentscope_runtime/common/utils/__init__.py +0 -0
- agentscope_runtime/common/utils/lazy_loader.py +57 -0
- agentscope_runtime/engine/__init__.py +25 -18
- agentscope_runtime/engine/app/agent_app.py +161 -91
- agentscope_runtime/engine/app/base_app.py +4 -118
- agentscope_runtime/engine/constant.py +8 -0
- agentscope_runtime/engine/deployers/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
- agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
- agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
- agentscope_runtime/engine/deployers/local_deployer.py +47 -74
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
- agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
- agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
- agentscope_runtime/engine/deployers/utils/package.py +693 -0
- agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +256 -282
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
- agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
- agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
- agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
- agentscope_runtime/engine/helpers/runner.py +40 -0
- agentscope_runtime/engine/runner.py +170 -130
- agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
- agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
- agentscope_runtime/engine/schemas/oai_llm.py +23 -23
- agentscope_runtime/engine/schemas/response_api.py +65 -0
- agentscope_runtime/engine/schemas/session.py +24 -0
- agentscope_runtime/engine/services/__init__.py +0 -9
- agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
- agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
- agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
- agentscope_runtime/engine/services/memory/__init__.py +24 -0
- agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
- agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
- agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
- agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
- agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
- agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
- agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
- agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
- agentscope_runtime/engine/services/session_history/__init__.py +23 -0
- agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
- agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
- agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
- agentscope_runtime/engine/tracing/base.py +10 -9
- agentscope_runtime/engine/tracing/message_util.py +1 -1
- agentscope_runtime/engine/tracing/tracing_util.py +7 -2
- agentscope_runtime/sandbox/__init__.py +10 -2
- agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
- agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
- agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
- agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
- agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
- agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
- agentscope_runtime/sandbox/client/http_client.py +1 -0
- agentscope_runtime/sandbox/enums.py +2 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +18 -2
- agentscope_runtime/sandbox/manager/server/app.py +12 -0
- agentscope_runtime/sandbox/manager/server/config.py +19 -0
- agentscope_runtime/sandbox/model/manager_config.py +79 -2
- agentscope_runtime/sandbox/utils.py +0 -18
- agentscope_runtime/tools/RAGs/__init__.py +0 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
- agentscope_runtime/tools/__init__.py +119 -0
- agentscope_runtime/tools/_constants.py +18 -0
- agentscope_runtime/tools/alipay/__init__.py +4 -0
- agentscope_runtime/tools/alipay/base.py +334 -0
- agentscope_runtime/tools/alipay/payment.py +835 -0
- agentscope_runtime/tools/alipay/subscribe.py +551 -0
- agentscope_runtime/tools/base.py +264 -0
- agentscope_runtime/tools/cli/__init__.py +0 -0
- agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
- agentscope_runtime/tools/generations/__init__.py +75 -0
- agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
- agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
- agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
- agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
- agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
- agentscope_runtime/tools/generations/image_edit.py +208 -0
- agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
- agentscope_runtime/tools/generations/image_generation.py +202 -0
- agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
- agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
- agentscope_runtime/tools/generations/image_to_video.py +233 -0
- agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
- agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
- agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
- agentscope_runtime/tools/generations/speech_to_text.py +260 -0
- agentscope_runtime/tools/generations/speech_to_video.py +314 -0
- agentscope_runtime/tools/generations/text_to_video.py +221 -0
- agentscope_runtime/tools/mcp_wrapper.py +215 -0
- agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
- agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
- agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
- agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
- agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
- agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
- agentscope_runtime/tools/searches/__init__.py +3 -0
- agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
- agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
- agentscope_runtime/tools/utils/__init__.py +0 -0
- agentscope_runtime/tools/utils/api_key_util.py +45 -0
- agentscope_runtime/tools/utils/crypto_utils.py +99 -0
- agentscope_runtime/tools/utils/mcp_util.py +35 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/METADATA +234 -165
- agentscope_runtime-1.0.0b1.dist-info/RECORD +240 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/entry_points.txt +1 -0
- agentscope_runtime/engine/agents/__init__.py +0 -2
- agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
- agentscope_runtime/engine/agents/agno_agent.py +0 -220
- agentscope_runtime/engine/agents/autogen_agent.py +0 -250
- agentscope_runtime/engine/agents/base_agent.py +0 -29
- agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
- agentscope_runtime/engine/agents/utils.py +0 -53
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
- agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
- agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
- agentscope_runtime/engine/helpers/helper.py +0 -179
- agentscope_runtime/engine/schemas/context.py +0 -54
- agentscope_runtime/engine/services/context_manager.py +0 -164
- agentscope_runtime/engine/services/environment_manager.py +0 -50
- agentscope_runtime/engine/services/manager.py +0 -174
- agentscope_runtime/engine/services/rag_service.py +0 -195
- agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
- agentscope_runtime/sandbox/tools/__init__.py +0 -12
- agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
- agentscope_runtime/sandbox/tools/base/tool.py +0 -52
- agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
- agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
- agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
- agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
- agentscope_runtime/sandbox/tools/function_tool.py +0 -321
- agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
- agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
- agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
- agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
- agentscope_runtime/sandbox/tools/tool.py +0 -238
- agentscope_runtime/sandbox/tools/utils.py +0 -68
- agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/top_level.txt +0 -0
|
@@ -1,22 +1,95 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# pylint:disable=too-many-branches, unused-argument, too-many-return-statements
|
|
3
|
-
|
|
3
|
+
# pylint:disable=protected-access
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import functools
|
|
6
7
|
import inspect
|
|
7
8
|
import json
|
|
9
|
+
import logging
|
|
8
10
|
from contextlib import asynccontextmanager
|
|
11
|
+
from dataclasses import asdict, is_dataclass
|
|
9
12
|
from typing import Optional, Callable, Type, Any, List, Dict
|
|
10
13
|
|
|
14
|
+
from a2a.types import A2ARequest
|
|
11
15
|
from fastapi import FastAPI, Request
|
|
12
16
|
from fastapi.middleware.cors import CORSMiddleware
|
|
13
17
|
from fastapi.responses import StreamingResponse, JSONResponse
|
|
14
18
|
from pydantic import BaseModel
|
|
15
19
|
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
20
|
+
from agentscope_runtime.engine.schemas.agent_schemas import AgentRequest
|
|
21
|
+
from agentscope_runtime.engine.schemas.response_api import ResponseAPI
|
|
18
22
|
from ..deployment_modes import DeploymentMode
|
|
23
|
+
from ...adapter.a2a.a2a_protocol_adapter import A2AFastAPIDefaultAdapter
|
|
19
24
|
from ...adapter.protocol_adapter import ProtocolAdapter
|
|
25
|
+
from ...adapter.responses.response_api_protocol_adapter import (
|
|
26
|
+
ResponseAPIDefaultAdapter,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _WrappedFastAPI(FastAPI):
|
|
33
|
+
"""FastAPI subclass that can dynamically augment OpenAPI schemas."""
|
|
34
|
+
|
|
35
|
+
_REF_TEMPLATE = "#/components/schemas/{model}"
|
|
36
|
+
|
|
37
|
+
def openapi(self) -> dict[str, Any]:
|
|
38
|
+
"""Generate OpenAPI schema with protocol-specific components."""
|
|
39
|
+
openapi_schema = super().openapi()
|
|
40
|
+
protocol_adapters = (
|
|
41
|
+
getattr(self.state, "protocol_adapters", None) or []
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if protocol_adapters:
|
|
45
|
+
if any(
|
|
46
|
+
isinstance(adapter, A2AFastAPIDefaultAdapter)
|
|
47
|
+
for adapter in protocol_adapters
|
|
48
|
+
):
|
|
49
|
+
self._inject_schema(
|
|
50
|
+
openapi_schema,
|
|
51
|
+
"A2ARequest",
|
|
52
|
+
A2ARequest.model_json_schema(
|
|
53
|
+
ref_template=self._REF_TEMPLATE,
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
if any(
|
|
57
|
+
isinstance(adapter, ResponseAPIDefaultAdapter)
|
|
58
|
+
for adapter in protocol_adapters
|
|
59
|
+
):
|
|
60
|
+
self._inject_schema(
|
|
61
|
+
openapi_schema,
|
|
62
|
+
"ResponseAPI",
|
|
63
|
+
ResponseAPI.model_json_schema(
|
|
64
|
+
ref_template=self._REF_TEMPLATE,
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
self._inject_schema(
|
|
69
|
+
openapi_schema,
|
|
70
|
+
"AgentRequest",
|
|
71
|
+
AgentRequest.model_json_schema(
|
|
72
|
+
ref_template=self._REF_TEMPLATE,
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return openapi_schema
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _inject_schema(
|
|
80
|
+
openapi_schema: dict[str, Any],
|
|
81
|
+
schema_name: str,
|
|
82
|
+
schema_definition: dict[str, Any],
|
|
83
|
+
) -> None:
|
|
84
|
+
"""Insert schema definition (and nested defs) into OpenAPI."""
|
|
85
|
+
components = openapi_schema.setdefault("components", {})
|
|
86
|
+
component_schemas = components.setdefault("schemas", {})
|
|
87
|
+
|
|
88
|
+
defs = schema_definition.pop("$defs", {})
|
|
89
|
+
for def_name, def_schema in defs.items():
|
|
90
|
+
component_schemas.setdefault(def_name, def_schema)
|
|
91
|
+
|
|
92
|
+
component_schemas[schema_name] = schema_definition
|
|
20
93
|
|
|
21
94
|
|
|
22
95
|
async def error_stream(e):
|
|
@@ -40,7 +113,6 @@ class FastAPIAppFactory:
|
|
|
40
113
|
before_start: Optional[Callable] = None,
|
|
41
114
|
after_finish: Optional[Callable] = None,
|
|
42
115
|
mode: DeploymentMode = DeploymentMode.DAEMON_THREAD,
|
|
43
|
-
services_config: Optional[ServicesConfig] = None,
|
|
44
116
|
protocol_adapters: Optional[list[ProtocolAdapter]] = None,
|
|
45
117
|
custom_endpoints: Optional[
|
|
46
118
|
List[Dict]
|
|
@@ -49,6 +121,7 @@ class FastAPIAppFactory:
|
|
|
49
121
|
broker_url: Optional[str] = None,
|
|
50
122
|
backend_url: Optional[str] = None,
|
|
51
123
|
enable_embedded_worker: bool = False,
|
|
124
|
+
app_kwargs: Optional[Dict] = None,
|
|
52
125
|
**kwargs: Any,
|
|
53
126
|
) -> FastAPI:
|
|
54
127
|
"""Create a FastAPI application with unified architecture.
|
|
@@ -63,20 +136,17 @@ class FastAPIAppFactory:
|
|
|
63
136
|
before_start: Callback function called before server starts
|
|
64
137
|
after_finish: Callback function called after server finishes
|
|
65
138
|
mode: Deployment mode
|
|
66
|
-
services_config: Services configuration
|
|
67
139
|
protocol_adapters: Protocol adapters
|
|
68
140
|
custom_endpoints: List of custom endpoint configurations
|
|
69
141
|
broker_url: Celery broker URL
|
|
70
142
|
backend_url: Celery backend URL
|
|
71
143
|
enable_embedded_worker: Whether to run embedded Celery worker
|
|
144
|
+
app_kwargs: Additional keyword arguments for the FastAPI app
|
|
72
145
|
**kwargs: Additional keyword arguments
|
|
73
146
|
|
|
74
147
|
Returns:
|
|
75
148
|
FastAPI application instance
|
|
76
149
|
"""
|
|
77
|
-
# Use default services config if not provided
|
|
78
|
-
if services_config is None:
|
|
79
|
-
services_config = DEFAULT_SERVICES_CONFIG
|
|
80
150
|
|
|
81
151
|
# Initialize Celery mixin if broker and backend URLs are provided
|
|
82
152
|
celery_mixin = None
|
|
@@ -101,7 +171,6 @@ class FastAPIAppFactory:
|
|
|
101
171
|
await FastAPIAppFactory._handle_startup(
|
|
102
172
|
app,
|
|
103
173
|
mode,
|
|
104
|
-
services_config,
|
|
105
174
|
runner,
|
|
106
175
|
before_start,
|
|
107
176
|
**kwargs,
|
|
@@ -116,15 +185,14 @@ class FastAPIAppFactory:
|
|
|
116
185
|
)
|
|
117
186
|
|
|
118
187
|
# Create FastAPI app
|
|
119
|
-
app =
|
|
188
|
+
app = _WrappedFastAPI(lifespan=lifespan, **(app_kwargs or {}))
|
|
120
189
|
|
|
121
190
|
# Store configuration in app state
|
|
122
191
|
app.state.deployment_mode = mode
|
|
123
|
-
app.state.services_config = services_config
|
|
124
192
|
app.state.stream_enabled = stream
|
|
125
|
-
app.state.response_type = response_type
|
|
126
193
|
app.state.custom_func = func
|
|
127
|
-
app.state.
|
|
194
|
+
app.state.runner = runner
|
|
195
|
+
app.state.response_type = response_type
|
|
128
196
|
app.state.endpoint_path = endpoint_path
|
|
129
197
|
app.state.protocol_adapters = protocol_adapters # Store for later use
|
|
130
198
|
app.state.custom_endpoints = (
|
|
@@ -158,27 +226,20 @@ class FastAPIAppFactory:
|
|
|
158
226
|
async def _handle_startup(
|
|
159
227
|
app: FastAPI,
|
|
160
228
|
mode: DeploymentMode,
|
|
161
|
-
services_config: ServicesConfig,
|
|
162
229
|
external_runner: Optional[Any],
|
|
163
230
|
before_start: Optional[Callable],
|
|
164
231
|
**kwargs,
|
|
165
232
|
):
|
|
166
233
|
"""Handle application startup."""
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
#
|
|
170
|
-
app.state.runner
|
|
171
|
-
app.state.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
DeploymentMode.STANDALONE,
|
|
176
|
-
]:
|
|
177
|
-
# Create internal runner
|
|
178
|
-
app.state.runner = await FastAPIAppFactory._create_internal_runner(
|
|
179
|
-
services_config,
|
|
234
|
+
try:
|
|
235
|
+
# aexit any possible running instances before set up
|
|
236
|
+
# runner
|
|
237
|
+
await app.state.runner.__aexit__(None, None, None)
|
|
238
|
+
await app.state.runner.__aenter__()
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.error(
|
|
241
|
+
f"Warning: Error during runner setup: {e}",
|
|
180
242
|
)
|
|
181
|
-
app.state.runner_managed_externally = False
|
|
182
243
|
|
|
183
244
|
# Call custom startup callback
|
|
184
245
|
if before_start:
|
|
@@ -243,9 +304,6 @@ class FastAPIAppFactory:
|
|
|
243
304
|
queues=queues,
|
|
244
305
|
)
|
|
245
306
|
except Exception as e:
|
|
246
|
-
import logging
|
|
247
|
-
|
|
248
|
-
logger = logging.getLogger(__name__)
|
|
249
307
|
logger.error(f"Failed to start Celery worker: {e}")
|
|
250
308
|
|
|
251
309
|
worker_thread = threading.Thread(
|
|
@@ -269,39 +327,23 @@ class FastAPIAppFactory:
|
|
|
269
327
|
after_finish(app, **kwargs)
|
|
270
328
|
|
|
271
329
|
# Cleanup internal runner
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
# Clean up runner
|
|
280
|
-
await runner.__aexit__(None, None, None)
|
|
281
|
-
except Exception as e:
|
|
282
|
-
print(f"Warning: Error during runner cleanup: {e}")
|
|
330
|
+
runner = app.state.runner
|
|
331
|
+
if runner:
|
|
332
|
+
try:
|
|
333
|
+
# Clean up runner
|
|
334
|
+
await runner.__aexit__(None, None, None)
|
|
335
|
+
except Exception as e:
|
|
336
|
+
logger.error(f"Warning: Error during runner cleanup: {e}")
|
|
283
337
|
|
|
284
338
|
@staticmethod
|
|
285
|
-
async def _create_internal_runner(
|
|
339
|
+
async def _create_internal_runner():
|
|
286
340
|
"""Create internal runner with configured services."""
|
|
287
341
|
from agentscope_runtime.engine import Runner
|
|
288
|
-
from agentscope_runtime.engine.services.context_manager import (
|
|
289
|
-
ContextManager,
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
# Create services
|
|
293
|
-
services = ServiceFactory.create_services_from_config(services_config)
|
|
294
|
-
|
|
295
|
-
# Create context manager
|
|
296
|
-
context_manager = ContextManager(
|
|
297
|
-
session_history_service=services["session_history"],
|
|
298
|
-
memory_service=services["memory"],
|
|
299
|
-
)
|
|
300
342
|
|
|
301
343
|
# Create runner (agent will be set later)
|
|
302
344
|
runner = Runner(
|
|
303
|
-
agent=None, # Will be set by the specific deployment
|
|
304
|
-
context_manager=context_manager,
|
|
345
|
+
# agent=None, # Will be set by the specific deployment
|
|
346
|
+
# context_manager=context_manager,
|
|
305
347
|
)
|
|
306
348
|
|
|
307
349
|
# Initialize runner
|
|
@@ -364,14 +406,36 @@ class FastAPIAppFactory:
|
|
|
364
406
|
|
|
365
407
|
return status
|
|
366
408
|
|
|
367
|
-
#
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
409
|
+
# Agent API endpoint
|
|
410
|
+
@app.post(
|
|
411
|
+
endpoint_path,
|
|
412
|
+
openapi_extra={
|
|
413
|
+
"requestBody": {
|
|
414
|
+
"content": {
|
|
415
|
+
"application/json": {
|
|
416
|
+
"schema": {
|
|
417
|
+
"$ref": "#/components/schemas/AgentRequest",
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
"required": True,
|
|
422
|
+
"description": "Agent API Request Format."
|
|
423
|
+
"See https://runtime.agentscope.io/en/protocol.html for "
|
|
424
|
+
"more details.",
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
tags=["agent-api"],
|
|
428
|
+
)
|
|
429
|
+
async def agent_api(request: dict):
|
|
430
|
+
"""
|
|
431
|
+
Agent API endpoint, see
|
|
432
|
+
<https://runtime.agentscope.io/en/protocol.html> for more details.
|
|
433
|
+
"""
|
|
373
434
|
return StreamingResponse(
|
|
374
|
-
FastAPIAppFactory._create_stream_generator(
|
|
435
|
+
FastAPIAppFactory._create_stream_generator(
|
|
436
|
+
app,
|
|
437
|
+
request=request,
|
|
438
|
+
),
|
|
375
439
|
media_type="text/event-stream",
|
|
376
440
|
headers={
|
|
377
441
|
"Cache-Control": "no-cache",
|
|
@@ -398,9 +462,9 @@ class FastAPIAppFactory:
|
|
|
398
462
|
"mode": mode.value,
|
|
399
463
|
"endpoints": {
|
|
400
464
|
"process": endpoint_path,
|
|
401
|
-
"stream":
|
|
402
|
-
|
|
403
|
-
|
|
465
|
+
"stream": (
|
|
466
|
+
f"{endpoint_path}/stream" if stream_enabled else None
|
|
467
|
+
),
|
|
404
468
|
"health": "/health",
|
|
405
469
|
},
|
|
406
470
|
}
|
|
@@ -408,8 +472,6 @@ class FastAPIAppFactory:
|
|
|
408
472
|
# Mode-specific endpoints
|
|
409
473
|
if mode == DeploymentMode.DETACHED_PROCESS:
|
|
410
474
|
FastAPIAppFactory._add_process_control_endpoints(app)
|
|
411
|
-
elif mode == DeploymentMode.STANDALONE:
|
|
412
|
-
FastAPIAppFactory._add_configuration_endpoints(app)
|
|
413
475
|
|
|
414
476
|
@staticmethod
|
|
415
477
|
def _add_process_control_endpoints(app: FastAPI):
|
|
@@ -445,38 +507,6 @@ class FastAPIAppFactory:
|
|
|
445
507
|
"uptime": process.create_time(),
|
|
446
508
|
}
|
|
447
509
|
|
|
448
|
-
@staticmethod
|
|
449
|
-
def _add_configuration_endpoints(app: FastAPI):
|
|
450
|
-
"""Add configuration endpoints for standalone mode."""
|
|
451
|
-
|
|
452
|
-
@app.get("/config")
|
|
453
|
-
async def get_configuration():
|
|
454
|
-
"""Get current service configuration."""
|
|
455
|
-
return {
|
|
456
|
-
"services_config": app.state.services_config.model_dump(),
|
|
457
|
-
"deployment_mode": app.state.deployment_mode.value,
|
|
458
|
-
"stream_enabled": app.state.stream_enabled,
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
@app.get("/config/services")
|
|
462
|
-
async def get_services_status():
|
|
463
|
-
"""Get services status."""
|
|
464
|
-
status = {}
|
|
465
|
-
if hasattr(app.state, "runner") and app.state.runner:
|
|
466
|
-
runner = app.state.runner
|
|
467
|
-
if hasattr(runner, "context_manager"):
|
|
468
|
-
cm = runner.context_manager
|
|
469
|
-
status["memory_service"] = (
|
|
470
|
-
"connected" if cm.memory_service else "disconnected"
|
|
471
|
-
)
|
|
472
|
-
status["session_history_service"] = (
|
|
473
|
-
"connected"
|
|
474
|
-
if cm.session_history_service
|
|
475
|
-
else "disconnected"
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
return {"services": status}
|
|
479
|
-
|
|
480
510
|
@staticmethod
|
|
481
511
|
async def _handle_request(
|
|
482
512
|
app: FastAPI,
|
|
@@ -591,193 +621,135 @@ class FastAPIAppFactory:
|
|
|
591
621
|
return None
|
|
592
622
|
|
|
593
623
|
@staticmethod
|
|
594
|
-
def
|
|
595
|
-
"""Create a wrapper
|
|
596
|
-
signature.
|
|
624
|
+
def _create_handler_wrapper(handler: Callable):
|
|
625
|
+
"""Create a wrapper for a handler that preserves function signature.
|
|
597
626
|
|
|
598
|
-
This
|
|
599
|
-
|
|
600
|
-
|
|
627
|
+
This wrapper maintains the handler's signature to enable FastAPI's
|
|
628
|
+
automatic parameter parsing and dependency injection. For async
|
|
629
|
+
handlers, it returns an async wrapper; for sync handlers,
|
|
630
|
+
it returns a sync wrapper.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
handler: The handler function to wrap
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
A wrapped handler that preserves the original function signature
|
|
601
637
|
"""
|
|
602
|
-
try:
|
|
603
|
-
sig = inspect.signature(handler)
|
|
604
|
-
params = list(sig.parameters.values())
|
|
605
638
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
return handler
|
|
639
|
+
is_awaitable = inspect.iscoroutinefunction(handler)
|
|
640
|
+
if is_awaitable:
|
|
609
641
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
642
|
+
@functools.wraps(handler)
|
|
643
|
+
async def wrapped_handler(*args, **kwargs):
|
|
644
|
+
return await handler(*args, **kwargs)
|
|
613
645
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
646
|
+
wrapped_handler.__signature__ = inspect.signature(handler)
|
|
647
|
+
return wrapped_handler
|
|
648
|
+
else:
|
|
617
649
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
BaseModel,
|
|
622
|
-
):
|
|
623
|
-
# Create wrapper that parses JSON to Pydantic model
|
|
624
|
-
if inspect.iscoroutinefunction(handler):
|
|
625
|
-
|
|
626
|
-
async def async_pydantic_wrapper(request: Request):
|
|
627
|
-
try:
|
|
628
|
-
body = await request.json()
|
|
629
|
-
parsed_param = param_annotation(**body)
|
|
630
|
-
return await handler(parsed_param)
|
|
631
|
-
except Exception as e:
|
|
632
|
-
return JSONResponse(
|
|
633
|
-
status_code=422,
|
|
634
|
-
content={
|
|
635
|
-
"detail": f"Request parsing error: "
|
|
636
|
-
f"{str(e)}",
|
|
637
|
-
},
|
|
638
|
-
)
|
|
650
|
+
@functools.wraps(handler)
|
|
651
|
+
def wrapped_handler(*args, **kwargs):
|
|
652
|
+
return handler(*args, **kwargs)
|
|
639
653
|
|
|
640
|
-
|
|
641
|
-
|
|
654
|
+
wrapped_handler.__signature__ = inspect.signature(handler)
|
|
655
|
+
return wrapped_handler
|
|
642
656
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
parsed_param = param_annotation(**body)
|
|
647
|
-
return handler(parsed_param)
|
|
648
|
-
except Exception as e:
|
|
649
|
-
return JSONResponse(
|
|
650
|
-
status_code=422,
|
|
651
|
-
content={
|
|
652
|
-
"detail": f"Request parsing error: "
|
|
653
|
-
f"{str(e)}",
|
|
654
|
-
},
|
|
655
|
-
)
|
|
657
|
+
@staticmethod
|
|
658
|
+
def _to_sse_event(item: Any) -> str:
|
|
659
|
+
"""Normalize streaming items into JSON-serializable structures."""
|
|
656
660
|
|
|
657
|
-
|
|
661
|
+
def _serialize(value: Any, depth: int = 0):
|
|
662
|
+
if depth > 20:
|
|
663
|
+
return f"<too-deep-level-{depth}-{str(value)}>"
|
|
658
664
|
|
|
659
|
-
|
|
660
|
-
|
|
665
|
+
if isinstance(value, (list, tuple, set)):
|
|
666
|
+
return [_serialize(i, depth=depth + 1) for i in value]
|
|
667
|
+
elif isinstance(value, dict):
|
|
668
|
+
return {
|
|
669
|
+
k: _serialize(v, depth=depth + 1) for k, v in value.items()
|
|
670
|
+
}
|
|
671
|
+
elif isinstance(value, (str, int, float, bool, type(None))):
|
|
672
|
+
return value
|
|
673
|
+
elif isinstance(value, BaseModel):
|
|
674
|
+
return value.model_dump()
|
|
675
|
+
elif is_dataclass(value):
|
|
676
|
+
return asdict(value)
|
|
661
677
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
678
|
+
for attr in ("to_map", "to_dict"):
|
|
679
|
+
method = getattr(value, attr, None)
|
|
680
|
+
if callable(method):
|
|
681
|
+
return method()
|
|
682
|
+
return str(value)
|
|
683
|
+
|
|
684
|
+
serialized = _serialize(item, depth=0)
|
|
685
|
+
|
|
686
|
+
return f"data: {json.dumps(serialized, ensure_ascii=False)}\n\n"
|
|
666
687
|
|
|
667
688
|
@staticmethod
|
|
668
689
|
def _create_streaming_parameter_wrapper(
|
|
669
690
|
handler: Callable,
|
|
670
|
-
is_async_gen: bool = False,
|
|
671
691
|
):
|
|
672
692
|
"""Create a wrapper for streaming handlers that handles parameter
|
|
673
693
|
parsing."""
|
|
674
|
-
|
|
675
|
-
sig = inspect.signature(handler)
|
|
676
|
-
params = list(sig.parameters.values())
|
|
677
|
-
no_params = False
|
|
678
|
-
param_annotation = None
|
|
679
|
-
|
|
680
|
-
if not params:
|
|
681
|
-
no_params = True
|
|
682
|
-
else:
|
|
683
|
-
# Get the first parameter
|
|
684
|
-
first_param = params[0]
|
|
685
|
-
param_annotation = first_param.annotation
|
|
686
|
-
|
|
687
|
-
# If no annotation or annotation is Request, goto no params
|
|
688
|
-
# logic
|
|
689
|
-
if param_annotation in [inspect.Parameter.empty, Request]:
|
|
690
|
-
no_params = True
|
|
691
|
-
|
|
692
|
-
if no_params:
|
|
693
|
-
if is_async_gen:
|
|
694
|
-
|
|
695
|
-
async def async_no_param_wrapper():
|
|
696
|
-
async def generate():
|
|
697
|
-
async for chunk in handler():
|
|
698
|
-
yield str(chunk)
|
|
699
|
-
|
|
700
|
-
return StreamingResponse(
|
|
701
|
-
generate(),
|
|
702
|
-
media_type="text/plain",
|
|
703
|
-
)
|
|
694
|
+
is_async_gen = inspect.isasyncgenfunction(handler)
|
|
704
695
|
|
|
705
|
-
|
|
706
|
-
else:
|
|
707
|
-
|
|
708
|
-
async def sync_no_param_wrapper():
|
|
709
|
-
def generate():
|
|
710
|
-
for chunk in handler():
|
|
711
|
-
yield str(chunk)
|
|
712
|
-
|
|
713
|
-
return StreamingResponse(
|
|
714
|
-
generate(),
|
|
715
|
-
media_type="text/plain",
|
|
716
|
-
)
|
|
717
|
-
|
|
718
|
-
return sync_no_param_wrapper
|
|
696
|
+
if is_async_gen:
|
|
719
697
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
async def async_stream_pydantic_wrapper(
|
|
728
|
-
request: Request,
|
|
729
|
-
):
|
|
730
|
-
try:
|
|
731
|
-
body = await request.json()
|
|
732
|
-
parsed_param = param_annotation(**body)
|
|
733
|
-
|
|
734
|
-
async def generate():
|
|
735
|
-
async for chunk in handler(parsed_param):
|
|
736
|
-
yield str(chunk)
|
|
737
|
-
|
|
738
|
-
return StreamingResponse(
|
|
739
|
-
generate(),
|
|
740
|
-
media_type="text/plain",
|
|
698
|
+
@functools.wraps(handler)
|
|
699
|
+
async def wrapped_handler(*args, **kwargs):
|
|
700
|
+
async def generate():
|
|
701
|
+
try:
|
|
702
|
+
async for chunk in handler(*args, **kwargs):
|
|
703
|
+
yield FastAPIAppFactory._to_sse_event(
|
|
704
|
+
chunk,
|
|
741
705
|
)
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
706
|
+
except Exception as e:
|
|
707
|
+
logger.error(
|
|
708
|
+
f"Error in streaming handler: {e}",
|
|
709
|
+
exc_info=True,
|
|
710
|
+
)
|
|
711
|
+
err_event = {
|
|
712
|
+
"error": str(e),
|
|
713
|
+
"error_type": e.__class__.__name__,
|
|
714
|
+
"message": "Error in streaming generator",
|
|
715
|
+
}
|
|
716
|
+
yield FastAPIAppFactory._to_sse_event(err_event)
|
|
717
|
+
|
|
718
|
+
return StreamingResponse(
|
|
719
|
+
generate(),
|
|
720
|
+
media_type="text/event-stream",
|
|
721
|
+
)
|
|
757
722
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
yield str(chunk)
|
|
723
|
+
wrapped_handler.__signature__ = inspect.signature(handler)
|
|
724
|
+
return wrapped_handler
|
|
761
725
|
|
|
762
|
-
|
|
763
|
-
generate(),
|
|
764
|
-
media_type="text/plain",
|
|
765
|
-
)
|
|
766
|
-
except Exception as e:
|
|
767
|
-
return JSONResponse(
|
|
768
|
-
status_code=422,
|
|
769
|
-
content={
|
|
770
|
-
"detail": f"Request parsing error:"
|
|
771
|
-
f" {str(e)}",
|
|
772
|
-
},
|
|
773
|
-
)
|
|
774
|
-
|
|
775
|
-
return sync_stream_pydantic_wrapper
|
|
726
|
+
else:
|
|
776
727
|
|
|
777
|
-
|
|
728
|
+
@functools.wraps(handler)
|
|
729
|
+
def wrapped_handler(*args, **kwargs):
|
|
730
|
+
def generate():
|
|
731
|
+
try:
|
|
732
|
+
for chunk in handler(*args, **kwargs):
|
|
733
|
+
yield FastAPIAppFactory._to_sse_event(chunk)
|
|
734
|
+
except Exception as e:
|
|
735
|
+
logger.error(
|
|
736
|
+
f"Error in streaming handler: {e}",
|
|
737
|
+
exc_info=True,
|
|
738
|
+
)
|
|
739
|
+
err_event = {
|
|
740
|
+
"error": str(e),
|
|
741
|
+
"error_type": e.__class__.__name__,
|
|
742
|
+
"message": "Error in streaming generator",
|
|
743
|
+
}
|
|
744
|
+
yield FastAPIAppFactory._to_sse_event(err_event)
|
|
745
|
+
|
|
746
|
+
return StreamingResponse(
|
|
747
|
+
generate(),
|
|
748
|
+
media_type="text/event-stream",
|
|
749
|
+
)
|
|
778
750
|
|
|
779
|
-
|
|
780
|
-
return
|
|
751
|
+
wrapped_handler.__signature__ = inspect.signature(handler)
|
|
752
|
+
return wrapped_handler
|
|
781
753
|
|
|
782
754
|
@staticmethod
|
|
783
755
|
def _add_custom_endpoints(app: FastAPI):
|
|
@@ -808,6 +780,8 @@ class FastAPIAppFactory:
|
|
|
808
780
|
"""Register a single custom endpoint with proper async/sync
|
|
809
781
|
handling."""
|
|
810
782
|
|
|
783
|
+
tags = ["custom"]
|
|
784
|
+
|
|
811
785
|
for method in methods:
|
|
812
786
|
# Check if this is a task endpoint
|
|
813
787
|
if endpoint_config and endpoint_config.get("task_type"):
|
|
@@ -817,7 +791,12 @@ class FastAPIAppFactory:
|
|
|
817
791
|
handler,
|
|
818
792
|
endpoint_config.get("queue", "default"),
|
|
819
793
|
)
|
|
820
|
-
app.add_api_route(
|
|
794
|
+
app.add_api_route(
|
|
795
|
+
path,
|
|
796
|
+
task_handler,
|
|
797
|
+
methods=[method],
|
|
798
|
+
tags=tags,
|
|
799
|
+
)
|
|
821
800
|
|
|
822
801
|
# Add task status endpoint - align with BaseApp pattern
|
|
823
802
|
status_path = f"{path}/{{task_id}}"
|
|
@@ -828,47 +807,42 @@ class FastAPIAppFactory:
|
|
|
828
807
|
status_path,
|
|
829
808
|
status_handler,
|
|
830
809
|
methods=["GET"],
|
|
810
|
+
tags=tags,
|
|
831
811
|
)
|
|
832
812
|
|
|
833
813
|
else:
|
|
834
814
|
# Regular endpoint handling with automatic parameter parsing
|
|
835
815
|
# Check in the correct order: async gen > sync gen > async &
|
|
836
816
|
# sync
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
817
|
+
|
|
818
|
+
if inspect.isasyncgenfunction(
|
|
819
|
+
handler,
|
|
820
|
+
) or inspect.isgeneratorfunction(handler):
|
|
840
821
|
wrapped_handler = (
|
|
841
822
|
FastAPIAppFactory._create_streaming_parameter_wrapper(
|
|
842
823
|
handler,
|
|
843
|
-
is_async_gen=True,
|
|
844
824
|
)
|
|
845
825
|
)
|
|
846
|
-
|
|
847
826
|
app.add_api_route(
|
|
848
827
|
path,
|
|
849
828
|
wrapped_handler,
|
|
850
829
|
methods=[method],
|
|
830
|
+
tags=tags,
|
|
831
|
+
response_model=None,
|
|
851
832
|
)
|
|
852
|
-
|
|
853
|
-
#
|
|
854
|
-
#
|
|
833
|
+
else:
|
|
834
|
+
# Non-streaming endpoint -> wrapper that preserves
|
|
835
|
+
# handler signature
|
|
855
836
|
wrapped_handler = (
|
|
856
|
-
FastAPIAppFactory.
|
|
857
|
-
handler,
|
|
858
|
-
is_async_gen=False,
|
|
859
|
-
)
|
|
837
|
+
FastAPIAppFactory._create_handler_wrapper(handler)
|
|
860
838
|
)
|
|
861
839
|
app.add_api_route(
|
|
862
840
|
path,
|
|
863
841
|
wrapped_handler,
|
|
864
842
|
methods=[method],
|
|
843
|
+
response_model=None,
|
|
844
|
+
tags=tags,
|
|
865
845
|
)
|
|
866
|
-
else:
|
|
867
|
-
# Sync function -> Async wrapper with parameter parsing
|
|
868
|
-
wrapped_handler = (
|
|
869
|
-
FastAPIAppFactory._create_parameter_wrapper(handler)
|
|
870
|
-
)
|
|
871
|
-
app.add_api_route(path, wrapped_handler, methods=[method])
|
|
872
846
|
|
|
873
847
|
@staticmethod
|
|
874
848
|
def _create_task_handler(app: FastAPI, task_func: Callable, queue: str):
|