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
|
@@ -22,12 +22,15 @@ import sys
|
|
|
22
22
|
import time
|
|
23
23
|
import uuid
|
|
24
24
|
from pathlib import Path
|
|
25
|
-
|
|
25
|
+
import os
|
|
26
|
+
from typing import List, Tuple, Optional, Union
|
|
27
|
+
from .detached_app import _parse_pyproject_toml, append_project_requirements
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
def get_user_bundle_appdir(build_root: Path, user_project_dir: Path) -> Path:
|
|
31
|
+
return (
|
|
32
|
+
build_root / "deploy_starter" / "user_bundle" / user_project_dir.name
|
|
33
|
+
)
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def _read_text_file_lines(file_path: Path) -> List[str]:
|
|
@@ -64,72 +67,6 @@ def _parse_requirements_txt(req_path: Path) -> Tuple[List[str], List[str]]:
|
|
|
64
67
|
return standard_requirements, local_wheel_paths
|
|
65
68
|
|
|
66
69
|
|
|
67
|
-
def _parse_pyproject_toml(pyproject_path: Path) -> List[str]:
|
|
68
|
-
deps: List[str] = []
|
|
69
|
-
if not pyproject_path.is_file():
|
|
70
|
-
return deps
|
|
71
|
-
text = pyproject_path.read_text(encoding="utf-8")
|
|
72
|
-
|
|
73
|
-
try:
|
|
74
|
-
# Prefer stdlib tomllib (Python 3.11+)
|
|
75
|
-
if tomllib is None:
|
|
76
|
-
raise RuntimeError("tomllib not available")
|
|
77
|
-
data = tomllib.loads(text)
|
|
78
|
-
# PEP 621
|
|
79
|
-
proj = data.get("project") or {}
|
|
80
|
-
deps.extend(proj.get("dependencies") or [])
|
|
81
|
-
# Poetry fallback
|
|
82
|
-
poetry = (data.get("tool") or {}).get("poetry") or {}
|
|
83
|
-
poetry_deps = poetry.get("dependencies") or {}
|
|
84
|
-
for name, spec in poetry_deps.items():
|
|
85
|
-
if name.lower() == "python":
|
|
86
|
-
continue
|
|
87
|
-
if isinstance(spec, str):
|
|
88
|
-
deps.append(f"{name}{spec if spec.strip() else ''}")
|
|
89
|
-
elif isinstance(spec, dict):
|
|
90
|
-
version = spec.get("version")
|
|
91
|
-
if version:
|
|
92
|
-
deps.append(f"{name}{version}")
|
|
93
|
-
else:
|
|
94
|
-
deps.append(name)
|
|
95
|
-
except Exception:
|
|
96
|
-
# Minimal non-toml parser fallback: try to extract a dependencies = [ ... ] list
|
|
97
|
-
block_match = re.search(
|
|
98
|
-
r"dependencies\s*=\s*\[(.*?)\]",
|
|
99
|
-
text,
|
|
100
|
-
re.S | re.I,
|
|
101
|
-
)
|
|
102
|
-
if block_match:
|
|
103
|
-
block = block_match.group(1)
|
|
104
|
-
for m in re.finditer(r"['\"]([^'\"]+)['\"]", block):
|
|
105
|
-
deps.append(m.group(1))
|
|
106
|
-
# Poetry fallback: very limited, heuristic
|
|
107
|
-
poetry_block = re.search(
|
|
108
|
-
r"\[tool\.poetry\.dependencies\](.*?)\n\[",
|
|
109
|
-
text,
|
|
110
|
-
re.S,
|
|
111
|
-
)
|
|
112
|
-
if poetry_block:
|
|
113
|
-
for line in poetry_block.group(1).splitlines():
|
|
114
|
-
line = line.strip()
|
|
115
|
-
if not line or line.startswith("#"):
|
|
116
|
-
continue
|
|
117
|
-
if ":" in line:
|
|
118
|
-
# name = "^1.2.3"
|
|
119
|
-
m = re.match(
|
|
120
|
-
r"([A-Za-z0-9_.-]+)\s*=\s*['\"]([^'\"]+)['\"]",
|
|
121
|
-
line,
|
|
122
|
-
)
|
|
123
|
-
if m and m.group(1).lower() != "python":
|
|
124
|
-
deps.append(f"{m.group(1)}{m.group(2)}")
|
|
125
|
-
else:
|
|
126
|
-
# name without version
|
|
127
|
-
name = line.split("#")[0].strip()
|
|
128
|
-
if name and name.lower() != "python":
|
|
129
|
-
deps.append(name)
|
|
130
|
-
return deps
|
|
131
|
-
|
|
132
|
-
|
|
133
70
|
def _gather_user_dependencies(
|
|
134
71
|
project_dir: Path,
|
|
135
72
|
) -> Tuple[List[str], List[Path]]:
|
|
@@ -211,6 +148,7 @@ def generate_wrapper_project(
|
|
|
211
148
|
start_cmd: str,
|
|
212
149
|
deploy_name: str,
|
|
213
150
|
telemetry_enabled: bool = True,
|
|
151
|
+
requirements: Optional[Union[str, List[str]]] = None,
|
|
214
152
|
) -> Tuple[Path, Path]:
|
|
215
153
|
"""
|
|
216
154
|
Create a wrapper project under build_root, embedding user project under
|
|
@@ -221,9 +159,8 @@ def generate_wrapper_project(
|
|
|
221
159
|
# 1) Copy user project into wrapper under deploy_starter/user_bundle/<project_basename>
|
|
222
160
|
# Put user code inside the deploy_starter package so wheel includes it and preserves project folder name
|
|
223
161
|
project_basename = user_project_dir.name
|
|
224
|
-
bundle_app_dir = (
|
|
225
|
-
|
|
226
|
-
)
|
|
162
|
+
bundle_app_dir = get_user_bundle_appdir(wrapper_dir, user_project_dir)
|
|
163
|
+
|
|
227
164
|
ignore = shutil.ignore_patterns(
|
|
228
165
|
".git",
|
|
229
166
|
".venv",
|
|
@@ -245,16 +182,6 @@ def generate_wrapper_project(
|
|
|
245
182
|
)
|
|
246
183
|
|
|
247
184
|
# 2) Dependencies
|
|
248
|
-
_, local_wheels = _gather_user_dependencies(user_project_dir)
|
|
249
|
-
|
|
250
|
-
# Copy local wheel files to wrapper project
|
|
251
|
-
if local_wheels:
|
|
252
|
-
wheels_dir = wrapper_dir / "deploy_starter" / "wheels"
|
|
253
|
-
wheels_dir.mkdir(parents=True, exist_ok=True)
|
|
254
|
-
for wheel_file in local_wheels:
|
|
255
|
-
dest = wheels_dir / wheel_file.name
|
|
256
|
-
shutil.copy2(wheel_file, dest)
|
|
257
|
-
|
|
258
185
|
wrapper_deps = [
|
|
259
186
|
"pyyaml",
|
|
260
187
|
"alibabacloud-oss-v2",
|
|
@@ -267,6 +194,30 @@ def generate_wrapper_project(
|
|
|
267
194
|
"jinja2",
|
|
268
195
|
"psutil",
|
|
269
196
|
]
|
|
197
|
+
|
|
198
|
+
_, local_wheels = _gather_user_dependencies(user_project_dir)
|
|
199
|
+
|
|
200
|
+
# gather
|
|
201
|
+
append_project_requirements(
|
|
202
|
+
build_root,
|
|
203
|
+
additional_requirements=requirements,
|
|
204
|
+
use_local_runtime=os.getenv("USE_LOCAL_RUNTIME", "False") == "True",
|
|
205
|
+
)
|
|
206
|
+
_, project_wheels = _gather_user_dependencies(build_root)
|
|
207
|
+
|
|
208
|
+
local_wheels.extend(project_wheels)
|
|
209
|
+
|
|
210
|
+
# Copy local wheel files to wrapper project
|
|
211
|
+
if local_wheels:
|
|
212
|
+
wheels_dir = wrapper_dir / "deploy_starter" / "wheels"
|
|
213
|
+
wheels_dir.mkdir(parents=True, exist_ok=True)
|
|
214
|
+
for wheel_file in local_wheels:
|
|
215
|
+
dest = wheels_dir / wheel_file.name
|
|
216
|
+
shutil.copy2(wheel_file, dest)
|
|
217
|
+
else:
|
|
218
|
+
# if not use local wheel, make sure the agentscope-runtime will be installed
|
|
219
|
+
wrapper_deps.append("agentscope_runtime")
|
|
220
|
+
|
|
270
221
|
# De-duplicate while preserving order
|
|
271
222
|
seen = set()
|
|
272
223
|
standard_reqs, local_wheel_paths = _parse_requirements_txt(
|
|
@@ -280,9 +231,6 @@ def generate_wrapper_project(
|
|
|
280
231
|
seen.add(key)
|
|
281
232
|
install_requires.append(pkg)
|
|
282
233
|
|
|
283
|
-
req_content = "\n".join(install_requires) + "\n"
|
|
284
|
-
req_content += "\n".join(local_wheel_paths) + "\n"
|
|
285
|
-
|
|
286
234
|
# 3) Packaging metadata
|
|
287
235
|
unique_suffix = uuid.uuid4().hex[:8]
|
|
288
236
|
package_name = f"agentscope_runtime_{unique_suffix}"
|
|
@@ -309,28 +257,7 @@ def read_config():
|
|
|
309
257
|
return yaml.safe_load(f) or {{}}
|
|
310
258
|
|
|
311
259
|
|
|
312
|
-
def install_local_wheels():
|
|
313
|
-
\"\"\"Install local wheel files if they exist.\"\"\"
|
|
314
|
-
wheels_dir = Path(__file__).resolve().parent / 'wheels'
|
|
315
|
-
if wheels_dir.exists() and wheels_dir.is_dir():
|
|
316
|
-
wheel_files = list(wheels_dir.glob('*.whl'))
|
|
317
|
-
if wheel_files:
|
|
318
|
-
print(f'[deploy_starter] Installing {{len(wheel_files)}} local wheel(s)...')
|
|
319
|
-
for wheel in wheel_files:
|
|
320
|
-
try:
|
|
321
|
-
subprocess.run(
|
|
322
|
-
['pip', 'install', '--no-deps', str(wheel)],
|
|
323
|
-
check=True,
|
|
324
|
-
capture_output=True,
|
|
325
|
-
)
|
|
326
|
-
print(f'[deploy_starter] Installed: {{wheel.name}}')
|
|
327
|
-
except subprocess.CalledProcessError as e:
|
|
328
|
-
print(f'[deploy_starter] Warning: Failed to install {{wheel.name}}: {{e}}', file=sys.stderr)
|
|
329
|
-
|
|
330
|
-
|
|
331
260
|
def main():
|
|
332
|
-
# Install local wheels first
|
|
333
|
-
install_local_wheels()
|
|
334
261
|
|
|
335
262
|
cfg = read_config()
|
|
336
263
|
subdir = cfg.get('APP_SUBDIR_NAME')
|
|
@@ -419,22 +346,76 @@ APP_SUBDIR_NAME: "{project_basename}"
|
|
|
419
346
|
|
|
420
347
|
setup_py = f"""
|
|
421
348
|
from setuptools import setup, find_packages
|
|
422
|
-
import
|
|
423
|
-
import
|
|
424
|
-
import
|
|
349
|
+
from setuptools.command.build_py import build_py
|
|
350
|
+
import zipfile
|
|
351
|
+
import shutil
|
|
425
352
|
from pathlib import Path
|
|
426
|
-
from
|
|
427
|
-
|
|
353
|
+
from email.parser import Parser
|
|
354
|
+
import tempfile
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class BuildPyWithWheelMerge(build_py):
|
|
358
|
+
\"\"\"Merge bundled wheel packages into the final wheel at build time\"\"\"
|
|
359
|
+
|
|
360
|
+
def run(self):
|
|
361
|
+
build_py.run(self)
|
|
362
|
+
self._merge_wheels()
|
|
428
363
|
|
|
429
|
-
def
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
364
|
+
def _merge_wheels(self):
|
|
365
|
+
\"\"\"Extract and merge all wheel files from the wheels directory\"\"\"
|
|
366
|
+
wheels_dir = Path("deploy_starter/wheels")
|
|
367
|
+
if not wheels_dir.exists():
|
|
368
|
+
return
|
|
369
|
+
|
|
370
|
+
whl_files = list(wheels_dir.glob("*.whl"))
|
|
371
|
+
if not whl_files:
|
|
372
|
+
return
|
|
373
|
+
|
|
374
|
+
print(f"\\n{{'='*60}}\\nMerging {{len(whl_files)}} wheel(s)...\\n{{'='*60}}\\n")
|
|
375
|
+
|
|
376
|
+
for whl_file in whl_files:
|
|
377
|
+
self._extract_wheel(whl_file, Path(self.build_lib))
|
|
378
|
+
|
|
379
|
+
print(f"{{'='*60}}\\nMerge completed!\\n{{'='*60}}\\n")
|
|
380
|
+
|
|
381
|
+
def _extract_wheel(self, whl_path, build_lib):
|
|
382
|
+
\"\"\"Extract wheel contents to build directory\"\"\"
|
|
383
|
+
with tempfile.TemporaryDirectory() as tmpdir, zipfile.ZipFile(whl_path) as zf:
|
|
384
|
+
zf.extractall(tmpdir)
|
|
385
|
+
|
|
386
|
+
for item in Path(tmpdir).iterdir():
|
|
387
|
+
if item.suffix in ['.dist-info', '.egg-info']:
|
|
388
|
+
continue
|
|
389
|
+
|
|
390
|
+
dest = build_lib / item.name
|
|
391
|
+
if dest.exists():
|
|
392
|
+
shutil.rmtree(dest) if dest.is_dir() else dest.unlink()
|
|
393
|
+
|
|
394
|
+
shutil.copytree(item, dest) if item.is_dir() else shutil.copy2(item, dest)
|
|
395
|
+
print(f" Merged: {{item.name}}")
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def extract_wheel_dependencies():
|
|
399
|
+
\"\"\"Extract dependency declarations from wheel files\"\"\"
|
|
400
|
+
deps = []
|
|
401
|
+
wheels_dir = Path("deploy_starter/wheels")
|
|
402
|
+
|
|
403
|
+
if not wheels_dir.exists():
|
|
404
|
+
return deps
|
|
405
|
+
|
|
406
|
+
for whl in wheels_dir.glob("*.whl"):
|
|
407
|
+
try:
|
|
408
|
+
with zipfile.ZipFile(whl) as zf:
|
|
409
|
+
metadata_file = next((f for f in zf.namelist() if f.endswith('/METADATA')), None)
|
|
410
|
+
if metadata_file:
|
|
411
|
+
content = zf.read(metadata_file).decode('utf-8')
|
|
412
|
+
metadata = Parser().parsestr(content)
|
|
413
|
+
deps.extend([v.split(';')[0].strip() for k, v in metadata.items()
|
|
414
|
+
if k == 'Requires-Dist' and v.split(';')[0].strip() not in deps])
|
|
415
|
+
except Exception as e:
|
|
416
|
+
print(f"Warning: Failed to extract deps from {{whl.name}}: {{e}}")
|
|
417
|
+
|
|
418
|
+
return deps
|
|
438
419
|
|
|
439
420
|
|
|
440
421
|
setup(
|
|
@@ -442,7 +423,10 @@ setup(
|
|
|
442
423
|
version='{version}',
|
|
443
424
|
packages=find_packages(),
|
|
444
425
|
include_package_data=True,
|
|
445
|
-
install_requires={install_requires!r},
|
|
426
|
+
install_requires={install_requires!r} + extract_wheel_dependencies(),
|
|
427
|
+
cmdclass={{
|
|
428
|
+
'build_py': BuildPyWithWheelMerge,
|
|
429
|
+
}},
|
|
446
430
|
)
|
|
447
431
|
"""
|
|
448
432
|
_write_file(wrapper_dir / "setup.py", setup_py)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# pylint: disable=not-callable
|
|
2
|
+
# pylint: disable=not-callable,too-many-statements,too-many-branches
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
import inspect
|
|
@@ -29,6 +29,7 @@ from .schemas.agent_schemas import (
|
|
|
29
29
|
SequenceNumberGenerator,
|
|
30
30
|
Error,
|
|
31
31
|
)
|
|
32
|
+
from .schemas.exception import AppBaseException, UnknownAgentException
|
|
32
33
|
from .tracing import TraceType
|
|
33
34
|
from .tracing.wrapper import trace
|
|
34
35
|
from .tracing.message_util import (
|
|
@@ -216,22 +217,23 @@ class Runner:
|
|
|
216
217
|
if isinstance(request, dict):
|
|
217
218
|
request = AgentRequest(**request)
|
|
218
219
|
|
|
220
|
+
# Assign session ID
|
|
221
|
+
request.session_id = request.session_id or str(uuid.uuid4())
|
|
222
|
+
|
|
223
|
+
# Assign user ID
|
|
224
|
+
request.user_id = request.user_id or request.session_id
|
|
225
|
+
|
|
219
226
|
seq_gen = SequenceNumberGenerator()
|
|
220
227
|
|
|
221
228
|
# Initial response
|
|
222
229
|
response = AgentResponse(id=request.id)
|
|
230
|
+
response.session_id = request.session_id
|
|
223
231
|
yield seq_gen.yield_with_sequence(response)
|
|
224
232
|
|
|
225
233
|
# Set to in-progress status
|
|
226
234
|
response.in_progress()
|
|
227
235
|
yield seq_gen.yield_with_sequence(response)
|
|
228
236
|
|
|
229
|
-
# Assign session ID
|
|
230
|
-
request.session_id = request.session_id or str(uuid.uuid4())
|
|
231
|
-
|
|
232
|
-
# Assign user ID
|
|
233
|
-
request.user_id = request.session_id or request.session_id
|
|
234
|
-
|
|
235
237
|
query_kwargs = {
|
|
236
238
|
"request": request,
|
|
237
239
|
}
|
|
@@ -250,6 +252,26 @@ class Runner:
|
|
|
250
252
|
kwargs.update(
|
|
251
253
|
{"msgs": message_to_agentscope_msg(request.input)},
|
|
252
254
|
)
|
|
255
|
+
elif self.framework_type == "langgraph":
|
|
256
|
+
from ..adapters.langgraph.stream import (
|
|
257
|
+
adapt_langgraph_message_stream,
|
|
258
|
+
)
|
|
259
|
+
from ..adapters.langgraph.message import message_to_langgraph_msg
|
|
260
|
+
|
|
261
|
+
stream_adapter = adapt_langgraph_message_stream
|
|
262
|
+
kwargs.update(
|
|
263
|
+
{"msgs": message_to_langgraph_msg(request.input)},
|
|
264
|
+
)
|
|
265
|
+
elif self.framework_type == "agno":
|
|
266
|
+
from ..adapters.agno.stream import (
|
|
267
|
+
adapt_agno_message_stream,
|
|
268
|
+
)
|
|
269
|
+
from ..adapters.agno.message import message_to_agno_message
|
|
270
|
+
|
|
271
|
+
stream_adapter = adapt_agno_message_stream
|
|
272
|
+
kwargs.update(
|
|
273
|
+
{"msgs": await message_to_agno_message(request.input)},
|
|
274
|
+
)
|
|
253
275
|
# TODO: support other frameworks
|
|
254
276
|
else:
|
|
255
277
|
|
|
@@ -275,11 +297,9 @@ class Runner:
|
|
|
275
297
|
response.add_new_message(event)
|
|
276
298
|
yield seq_gen.yield_with_sequence(event)
|
|
277
299
|
except Exception as e:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
message=f"Error happens in `query_handler`: {e}",
|
|
282
|
-
)
|
|
300
|
+
if not isinstance(e, AppBaseException):
|
|
301
|
+
e = UnknownAgentException(original_exception=e)
|
|
302
|
+
error = Error(code=e.code, message=e.message)
|
|
283
303
|
logger.error(f"{error.model_dump()}: {traceback.format_exc()}")
|
|
284
304
|
yield seq_gen.yield_with_sequence(response.failed(error))
|
|
285
305
|
return
|
|
@@ -27,6 +27,7 @@ class MessageType:
|
|
|
27
27
|
MCP_APPROVAL_REQUEST = "mcp_approval_request"
|
|
28
28
|
MCP_TOOL_CALL = "mcp_call"
|
|
29
29
|
MCP_APPROVAL_RESPONSE = "mcp_approval_response"
|
|
30
|
+
MCP_TOOL_CALL_OUTPUT = "mcp_call_output"
|
|
30
31
|
REASONING = "reasoning"
|
|
31
32
|
HEARTBEAT = "heartbeat"
|
|
32
33
|
ERROR = "error"
|
|
@@ -152,22 +153,35 @@ class FunctionCallOutput(BaseModel):
|
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
class McpCall(BaseModel):
|
|
155
|
-
|
|
156
|
+
"""
|
|
157
|
+
MCP TOOL CALL MESSAGE BODY
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
call_id: Optional[str] = None
|
|
156
161
|
"""The unique ID of the tool call."""
|
|
157
162
|
|
|
158
|
-
arguments: str
|
|
163
|
+
arguments: Optional[str] = None
|
|
159
164
|
"""A JSON string of the arguments passed to the tool."""
|
|
160
165
|
|
|
161
|
-
name: str
|
|
166
|
+
name: Optional[str] = None
|
|
162
167
|
"""The name of the tool that was run."""
|
|
163
168
|
|
|
164
|
-
server_label: str
|
|
169
|
+
server_label: Optional[str] = None
|
|
165
170
|
"""The label of the MCP server running the tool."""
|
|
166
171
|
|
|
167
|
-
error: Optional[str] = None
|
|
168
|
-
"""The error from the tool call, if any."""
|
|
169
172
|
|
|
170
|
-
|
|
173
|
+
class McpCallOutput(BaseModel):
|
|
174
|
+
"""
|
|
175
|
+
MCP TOOL CALL OUTPUT MESSAGE BODY
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
call_id: str
|
|
179
|
+
"""The unique ID of the tool call."""
|
|
180
|
+
|
|
181
|
+
name: Optional[str] = None
|
|
182
|
+
"""The name of the tool call."""
|
|
183
|
+
|
|
184
|
+
output: str
|
|
171
185
|
"""The output from the tool call."""
|
|
172
186
|
|
|
173
187
|
|