agentscope-runtime 1.0.1__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.
Files changed (58) hide show
  1. agentscope_runtime/adapters/agentscope/message.py +32 -7
  2. agentscope_runtime/adapters/agentscope/stream.py +121 -91
  3. agentscope_runtime/adapters/agno/__init__.py +0 -0
  4. agentscope_runtime/adapters/agno/message.py +30 -0
  5. agentscope_runtime/adapters/agno/stream.py +122 -0
  6. agentscope_runtime/adapters/langgraph/__init__.py +12 -0
  7. agentscope_runtime/adapters/langgraph/message.py +257 -0
  8. agentscope_runtime/adapters/langgraph/stream.py +205 -0
  9. agentscope_runtime/cli/__init__.py +7 -0
  10. agentscope_runtime/cli/cli.py +63 -0
  11. agentscope_runtime/cli/commands/__init__.py +2 -0
  12. agentscope_runtime/cli/commands/chat.py +815 -0
  13. agentscope_runtime/cli/commands/deploy.py +1062 -0
  14. agentscope_runtime/cli/commands/invoke.py +58 -0
  15. agentscope_runtime/cli/commands/list_cmd.py +103 -0
  16. agentscope_runtime/cli/commands/run.py +176 -0
  17. agentscope_runtime/cli/commands/sandbox.py +128 -0
  18. agentscope_runtime/cli/commands/status.py +60 -0
  19. agentscope_runtime/cli/commands/stop.py +185 -0
  20. agentscope_runtime/cli/commands/web.py +166 -0
  21. agentscope_runtime/cli/loaders/__init__.py +6 -0
  22. agentscope_runtime/cli/loaders/agent_loader.py +295 -0
  23. agentscope_runtime/cli/state/__init__.py +10 -0
  24. agentscope_runtime/cli/utils/__init__.py +18 -0
  25. agentscope_runtime/cli/utils/console.py +378 -0
  26. agentscope_runtime/cli/utils/validators.py +118 -0
  27. agentscope_runtime/engine/app/agent_app.py +7 -4
  28. agentscope_runtime/engine/deployers/__init__.py +1 -0
  29. agentscope_runtime/engine/deployers/agentrun_deployer.py +152 -22
  30. agentscope_runtime/engine/deployers/base.py +27 -2
  31. agentscope_runtime/engine/deployers/kubernetes_deployer.py +158 -31
  32. agentscope_runtime/engine/deployers/local_deployer.py +188 -25
  33. agentscope_runtime/engine/deployers/modelstudio_deployer.py +109 -18
  34. agentscope_runtime/engine/deployers/state/__init__.py +9 -0
  35. agentscope_runtime/engine/deployers/state/manager.py +388 -0
  36. agentscope_runtime/engine/deployers/state/schema.py +96 -0
  37. agentscope_runtime/engine/deployers/utils/build_cache.py +736 -0
  38. agentscope_runtime/engine/deployers/utils/detached_app.py +105 -30
  39. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +31 -10
  40. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +15 -8
  41. agentscope_runtime/engine/deployers/utils/docker_image_utils/image_factory.py +30 -2
  42. agentscope_runtime/engine/deployers/utils/k8s_utils.py +241 -0
  43. agentscope_runtime/engine/deployers/utils/package.py +56 -6
  44. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +16 -2
  45. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +155 -5
  46. agentscope_runtime/engine/deployers/utils/wheel_packager.py +107 -123
  47. agentscope_runtime/engine/runner.py +25 -6
  48. agentscope_runtime/engine/schemas/exception.py +580 -0
  49. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +113 -39
  50. agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +20 -4
  51. agentscope_runtime/sandbox/utils.py +2 -0
  52. agentscope_runtime/version.py +1 -1
  53. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/METADATA +24 -7
  54. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/RECORD +58 -28
  55. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/entry_points.txt +1 -0
  56. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/WHEEL +0 -0
  57. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/licenses/LICENSE +0 -0
  58. {agentscope_runtime-1.0.1.dist-info → agentscope_runtime-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,378 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Console output utilities for CLI using Rich library."""
3
+
4
+ import io
5
+ import json
6
+ from typing import Optional, Any
7
+
8
+ import click
9
+ from rich.console import Console
10
+ from rich.table import Table
11
+ from rich.json import JSON
12
+
13
+
14
+ # Centralized style configuration
15
+ CONSOLE_CONFIG = {
16
+ "success": {
17
+ "emoji": "✓",
18
+ "style": "bold green",
19
+ },
20
+ "error": {
21
+ "emoji": "✗",
22
+ "style": "bold red",
23
+ },
24
+ "warning": {
25
+ "emoji": "⚠",
26
+ "style": "bold yellow",
27
+ },
28
+ "info": {
29
+ "emoji": "ℹ",
30
+ "style": "bold blue",
31
+ },
32
+ }
33
+
34
+ # Module-level console instances (lazy initialization)
35
+ _console = None
36
+ _err_console = None
37
+
38
+
39
+ def _get_console() -> Console:
40
+ """Get or create the shared console instance for stdout."""
41
+ global _console
42
+ if _console is None:
43
+ _console = Console()
44
+ return _console
45
+
46
+
47
+ def _get_err_console() -> Console:
48
+ """Get or create the shared console instance for stderr."""
49
+ global _err_console
50
+ if _err_console is None:
51
+ _err_console = Console(stderr=True)
52
+ return _err_console
53
+
54
+
55
+ def _process_kwargs(kwargs: dict) -> tuple[dict, str]:
56
+ """
57
+ Process kwargs to handle Click-specific parameters.
58
+
59
+ Returns:
60
+ Tuple of (rich_kwargs, end_char)
61
+ """
62
+ # Handle Click's nl parameter
63
+ nl = kwargs.pop("nl", True)
64
+ end = "\n" if nl else ""
65
+
66
+ # Handle Click's err parameter (should be handled by console selection)
67
+ kwargs.pop("err", None)
68
+
69
+ # Click's color parameters - ignore, use theme instead
70
+ kwargs.pop("fg", None)
71
+ kwargs.pop("bg", None)
72
+ kwargs.pop("bold", None)
73
+ kwargs.pop("dim", None)
74
+
75
+ return kwargs, end
76
+
77
+
78
+ def echo_success(message: str, **kwargs) -> None:
79
+ """
80
+ Print success message in green with checkmark.
81
+
82
+ Uses Rich library for enhanced terminal output with automatic
83
+ cross-platform support (including Windows).
84
+
85
+ Args:
86
+ message: Message to display
87
+ **kwargs: Additional Rich Console.print() parameters
88
+ (e.g., highlight=False, markup=False)
89
+
90
+ Note:
91
+ Legacy Click kwargs (nl, err, fg, bold) are supported for
92
+ backward compatibility but are deprecated.
93
+
94
+ Example:
95
+ >>> echo_success("Deployment completed successfully")
96
+ ✓ Deployment completed successfully
97
+ """
98
+ console = _get_console()
99
+ config = CONSOLE_CONFIG["success"]
100
+ kwargs, end = _process_kwargs(kwargs)
101
+
102
+ formatted_message = f"{config['emoji']} {message}"
103
+ console.print(formatted_message, style=config["style"], end=end, **kwargs)
104
+
105
+
106
+ def echo_error(message: str, **kwargs) -> None:
107
+ """
108
+ Print error message in red with X mark to stderr.
109
+
110
+ Uses Rich library for enhanced terminal output with automatic
111
+ cross-platform support (including Windows).
112
+
113
+ Args:
114
+ message: Message to display
115
+ **kwargs: Additional Rich Console.print() parameters
116
+
117
+ Note:
118
+ Legacy Click kwargs (nl, err, fg, bold) are supported for
119
+ backward compatibility but are deprecated.
120
+
121
+ Example:
122
+ >>> echo_error("Deployment failed")
123
+ ✗ Deployment failed
124
+ """
125
+ console = _get_err_console()
126
+ config = CONSOLE_CONFIG["error"]
127
+ kwargs, end = _process_kwargs(kwargs)
128
+
129
+ formatted_message = f"{config['emoji']} {message}"
130
+ console.print(formatted_message, style=config["style"], end=end, **kwargs)
131
+
132
+
133
+ def echo_warning(message: str, **kwargs) -> None:
134
+ """
135
+ Print warning message in yellow with warning symbol.
136
+
137
+ Uses Rich library for enhanced terminal output with automatic
138
+ cross-platform support (including Windows).
139
+
140
+ Args:
141
+ message: Message to display
142
+ **kwargs: Additional Rich Console.print() parameters
143
+
144
+ Note:
145
+ Legacy Click kwargs (nl, err, fg, bold) are supported for
146
+ backward compatibility but are deprecated.
147
+
148
+ Example:
149
+ >>> echo_warning("Configuration file not found, using defaults")
150
+ ⚠ Configuration file not found, using defaults
151
+ """
152
+ console = _get_console()
153
+ config = CONSOLE_CONFIG["warning"]
154
+ kwargs, end = _process_kwargs(kwargs)
155
+
156
+ formatted_message = f"{config['emoji']} {message}"
157
+ console.print(formatted_message, style=config["style"], end=end, **kwargs)
158
+
159
+
160
+ def echo_info(message: str, **kwargs) -> None:
161
+ """
162
+ Print info message in blue with info symbol.
163
+
164
+ Uses Rich library for enhanced terminal output with automatic
165
+ cross-platform support (including Windows).
166
+
167
+ Args:
168
+ message: Message to display
169
+ **kwargs: Additional Rich Console.print() parameters
170
+
171
+ Note:
172
+ Legacy Click kwargs (nl, err, fg, bold) are supported for
173
+ backward compatibility but are deprecated.
174
+
175
+ Example:
176
+ >>> echo_info("Loading configuration...")
177
+ ℹ Loading configuration...
178
+ """
179
+ console = _get_console()
180
+ config = CONSOLE_CONFIG["info"]
181
+ kwargs, end = _process_kwargs(kwargs)
182
+
183
+ formatted_message = f"{config['emoji']} {message}"
184
+ console.print(formatted_message, style=config["style"], end=end, **kwargs)
185
+
186
+
187
+ def echo_header(message: str, **kwargs) -> None:
188
+ """
189
+ Print header message in bold.
190
+
191
+ Args:
192
+ message: Message to display
193
+ **kwargs: Additional Rich Console.print() parameters
194
+
195
+ Example:
196
+ >>> echo_header("Deployment Summary")
197
+ Deployment Summary
198
+ """
199
+ console = _get_console()
200
+ kwargs, end = _process_kwargs(kwargs)
201
+ console.print(message, style="bold", end=end, **kwargs)
202
+
203
+
204
+ def echo_dim(message: str, **kwargs) -> None:
205
+ """
206
+ Print dimmed message.
207
+
208
+ Args:
209
+ message: Message to display
210
+ **kwargs: Additional Rich Console.print() parameters
211
+
212
+ Example:
213
+ >>> echo_dim("Additional details...")
214
+ Additional details...
215
+ """
216
+ console = _get_console()
217
+ kwargs, end = _process_kwargs(kwargs)
218
+ console.print(message, style="dim", end=end, **kwargs)
219
+
220
+
221
+ def format_table(
222
+ headers: list[str],
223
+ rows: list[list[Any]],
224
+ max_width: Optional[int] = None,
225
+ ) -> str:
226
+ """
227
+ Format data as a Rich Table (returns rendered string).
228
+
229
+ Uses Rich library for enhanced table rendering with better alignment
230
+ and visual appeal compared to ASCII tables.
231
+
232
+ Args:
233
+ headers: List of column headers
234
+ rows: List of rows, where each row is a list of cell values
235
+ max_width: Optional maximum width for columns
236
+
237
+ Returns:
238
+ Rendered table as a string for backward compatibility
239
+
240
+ Example:
241
+ >>> headers = ["ID", "Status"]
242
+ >>> rows = [["deploy_1", "running"], ["deploy_2", "stopped"]]
243
+ >>> print(format_table(headers, rows))
244
+ """
245
+ if not rows:
246
+ return "No data to display."
247
+
248
+ # Create Rich table
249
+ table = Table(show_header=True, header_style="bold cyan")
250
+
251
+ # Add columns
252
+ for header in headers:
253
+ table.add_column(header, max_width=max_width)
254
+
255
+ # Add rows
256
+ for row in rows:
257
+ table.add_row(*[str(cell) for cell in row])
258
+
259
+ # Render table to string for backward compatibility
260
+ string_io = io.StringIO()
261
+ temp_console = Console(file=string_io, force_terminal=True)
262
+ temp_console.print(table)
263
+ return string_io.getvalue()
264
+
265
+
266
+ def format_json(data: Any, indent: int = 2) -> str:
267
+ """
268
+ Format data as JSON with syntax highlighting.
269
+
270
+ Uses Rich library for syntax-highlighted JSON output.
271
+
272
+ Args:
273
+ data: Data to format as JSON
274
+ indent: Indentation level (default: 2)
275
+
276
+ Returns:
277
+ Rendered JSON as a string with syntax highlighting
278
+
279
+ Example:
280
+ >>> data = {"key": "value", "number": 123}
281
+ >>> print(format_json(data))
282
+ """
283
+ # Rich's JSON requires a string, not an object
284
+ json_string = json.dumps(data, indent=indent, default=str)
285
+
286
+ # Render to string for backward compatibility
287
+ string_io = io.StringIO()
288
+ temp_console = Console(file=string_io, force_terminal=True)
289
+ temp_console.print(JSON(json_string, indent=indent))
290
+ return string_io.getvalue()
291
+
292
+
293
+ def format_deployment_info(deployment: dict) -> str:
294
+ """
295
+ Format deployment information using Rich Table.
296
+
297
+ Uses Rich library for structured key-value display.
298
+
299
+ Args:
300
+ deployment: Dictionary containing deployment information
301
+
302
+ Returns:
303
+ Rendered deployment info as a string
304
+
305
+ Example:
306
+ >>> deployment = {
307
+ ... "id": "local_123",
308
+ ... "platform": "local",
309
+ ... "status": "running",
310
+ ... "url": "http://localhost:8000",
311
+ ... "created_at": "2025-01-01 12:00:00",
312
+ ... "agent_source": "agent.py"
313
+ ... }
314
+ >>> print(format_deployment_info(deployment))
315
+ """
316
+ # Create table with no header for key-value pairs
317
+ table = Table(show_header=False, box=None, padding=(0, 2))
318
+ table.add_column("Key", style="bold cyan")
319
+ table.add_column("Value", style="white")
320
+
321
+ # Add deployment information
322
+ table.add_row("Deployment ID", deployment["id"])
323
+ table.add_row("Platform", deployment["platform"])
324
+ table.add_row("Status", deployment["status"])
325
+ table.add_row("URL", deployment["url"])
326
+ table.add_row("Created", deployment["created_at"])
327
+ table.add_row("Agent Source", deployment["agent_source"])
328
+
329
+ # Add token if present
330
+ if deployment.get("token"):
331
+ token = deployment["token"]
332
+ display_token = f"{token[:20]}..." if len(token) > 20 else token
333
+ table.add_row("Token", display_token)
334
+
335
+ # Render to string for backward compatibility
336
+ string_io = io.StringIO()
337
+ temp_console = Console(file=string_io, force_terminal=True)
338
+ temp_console.print(table)
339
+ return string_io.getvalue()
340
+
341
+
342
+ def confirm(message: str, default: bool = False) -> bool:
343
+ """
344
+ Prompt user for confirmation.
345
+
346
+ Uses Click's confirm function (unchanged from original implementation).
347
+
348
+ Args:
349
+ message: Confirmation message
350
+ default: Default value if user just presses Enter
351
+
352
+ Returns:
353
+ True if user confirms, False otherwise
354
+
355
+ Example:
356
+ >>> if confirm("Delete deployment?"):
357
+ ... # proceed with deletion
358
+ """
359
+ return click.confirm(message, default=default)
360
+
361
+
362
+ def prompt(message: str, default: Optional[str] = None) -> str:
363
+ """
364
+ Prompt user for input.
365
+
366
+ Uses Click's prompt function (unchanged from original implementation).
367
+
368
+ Args:
369
+ message: Prompt message
370
+ default: Default value if user just presses Enter
371
+
372
+ Returns:
373
+ User input as string
374
+
375
+ Example:
376
+ >>> name = prompt("Enter deployment name")
377
+ """
378
+ return click.prompt(message, default=default)
@@ -0,0 +1,118 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Input validation utilities for CLI."""
3
+
4
+ import os
5
+
6
+ from agentscope_runtime.engine.deployers.state import DeploymentStateManager
7
+
8
+
9
+ class ValidationError(Exception):
10
+ """Raised when validation fails."""
11
+
12
+
13
+ def validate_agent_source(source: str) -> tuple[str, str]:
14
+ """
15
+ Validate and determine the type of agent source.
16
+
17
+ Args:
18
+ source: Path to file/directory or deployment ID
19
+
20
+ Returns:
21
+ Tuple of (source_type, normalized_path/id)
22
+ source_type can be: 'file', 'directory', 'deployment_id'
23
+
24
+ Raises:
25
+ ValidationError: If source is invalid
26
+ """
27
+ if not source:
28
+ raise ValidationError("Agent source cannot be empty")
29
+
30
+ # Check if it's a file
31
+ if os.path.isfile(source):
32
+ if not source.endswith(".py"):
33
+ raise ValidationError(
34
+ f"Agent source file must be a Python file: {source}",
35
+ )
36
+ return ("file", os.path.abspath(source))
37
+
38
+ # Check if it's a directory
39
+ if os.path.isdir(source):
40
+ return ("directory", os.path.abspath(source))
41
+
42
+ # Check if it's a deployment ID by querying state manager
43
+ # This ensures we only accept deployment IDs that actually exist
44
+ # Support both formats: platform_timestamp_id (with underscore) and UUID
45
+ # format
46
+ state_manager = DeploymentStateManager()
47
+ if state_manager.exists(source):
48
+ return ("deployment_id", source)
49
+
50
+ raise ValidationError(
51
+ f"Invalid agent source: {source}\n"
52
+ "Must be a Python file (.py), directory, or deployment ID",
53
+ )
54
+
55
+
56
+ def validate_port(port: int) -> int:
57
+ """Validate port number."""
58
+ if not isinstance(port, int):
59
+ try:
60
+ port = int(port)
61
+ except (ValueError, TypeError) as e:
62
+ raise ValidationError(f"Port must be an integer: {port}") from e
63
+
64
+ if port < 1 or port > 65535:
65
+ raise ValidationError(f"Port must be between 1 and 65535: {port}")
66
+
67
+ return port
68
+
69
+
70
+ def validate_platform(platform: str, supported_platforms: list[str]) -> str:
71
+ """Validate platform name."""
72
+ if platform not in supported_platforms:
73
+ raise ValidationError(
74
+ f"Unsupported platform: {platform}\n"
75
+ f"Supported platforms: {', '.join(supported_platforms)}",
76
+ )
77
+ return platform
78
+
79
+
80
+ def validate_file_exists(file_path: str) -> str:
81
+ """Validate that file exists."""
82
+ if not os.path.isfile(file_path):
83
+ raise ValidationError(f"File not found: {file_path}")
84
+ return os.path.abspath(file_path)
85
+
86
+
87
+ def validate_directory_exists(dir_path: str) -> str:
88
+ """Validate that directory exists."""
89
+ if not os.path.isdir(dir_path):
90
+ raise ValidationError(f"Directory not found: {dir_path}")
91
+ return os.path.abspath(dir_path)
92
+
93
+
94
+ def validate_url(url: str) -> str:
95
+ """Basic URL validation."""
96
+ if not url:
97
+ raise ValidationError("URL cannot be empty")
98
+
99
+ if not (url.startswith("http://") or url.startswith("https://")):
100
+ raise ValidationError(
101
+ f"URL must start with http:// or https://: {url}",
102
+ )
103
+
104
+ return url
105
+
106
+
107
+ def validate_deployment_id(deploy_id: str) -> str:
108
+ """Validate deployment ID format."""
109
+ if not deploy_id:
110
+ raise ValidationError("Deployment ID cannot be empty")
111
+
112
+ if "_" not in deploy_id:
113
+ raise ValidationError(
114
+ f"Invalid deployment ID format: {deploy_id}\n"
115
+ "Expected format: platform_timestamp_id",
116
+ )
117
+
118
+ return deploy_id
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import logging
3
+ import os
3
4
  import types
4
5
  import platform
5
6
  import subprocess
@@ -22,6 +23,8 @@ from ..schemas.agent_schemas import AgentRequest
22
23
  from ...version import __version__
23
24
 
24
25
  logger = logging.getLogger(__name__)
26
+ HOST = os.getenv("HOST", "0.0.0.0")
27
+ PORT = int(os.getenv("PORT", "8080"))
25
28
 
26
29
 
27
30
  class AgentApp(BaseApp):
@@ -150,8 +153,8 @@ class AgentApp(BaseApp):
150
153
 
151
154
  def run(
152
155
  self,
153
- host="0.0.0.0",
154
- port=8090,
156
+ host=HOST,
157
+ port=PORT,
155
158
  web_ui=False,
156
159
  **kwargs,
157
160
  ):
@@ -171,7 +174,7 @@ class AgentApp(BaseApp):
171
174
 
172
175
  Args:
173
176
  host (str): Host address to bind to. Default "0.0.0.0".
174
- port (int): Port number to serve the application on. Default 8090.
177
+ port (int): Port number to serve the application on. Default 8080.
175
178
  web_ui (bool): If True, launches the Agentscope Web UI in a
176
179
  separate process, pointing it to the API endpoint. This
177
180
  allows interactive use via browser. Default False.
@@ -180,7 +183,7 @@ class AgentApp(BaseApp):
180
183
 
181
184
  Example:
182
185
  >>> app = AgentApp(app_name="MyAgent")
183
- >>> app.run(host="127.0.0.1", port=8000, web_ui=True)
186
+ >>> app.chat(host="127.0.0.1", port=8080, web_ui=True)
184
187
  """
185
188
  # Build runner
186
189
  self._build_runner()
@@ -3,6 +3,7 @@ from .base import DeployManager
3
3
  from .local_deployer import LocalDeployManager
4
4
  from .kubernetes_deployer import (
5
5
  KubernetesDeployManager,
6
+ K8sConfig,
6
7
  )
7
8
  from .modelstudio_deployer import (
8
9
  ModelstudioDeployManager,