agentscope-runtime 1.0.2__py3-none-any.whl → 1.0.4__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/stream.py +2 -9
  2. agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
  3. agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
  4. agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
  5. agentscope_runtime/adapters/utils.py +6 -0
  6. agentscope_runtime/cli/commands/deploy.py +383 -0
  7. agentscope_runtime/common/collections/redis_mapping.py +4 -1
  8. agentscope_runtime/common/container_clients/knative_client.py +466 -0
  9. agentscope_runtime/engine/__init__.py +4 -0
  10. agentscope_runtime/engine/app/agent_app.py +48 -5
  11. agentscope_runtime/engine/constant.py +1 -0
  12. agentscope_runtime/engine/deployers/__init__.py +12 -0
  13. agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +31 -1
  14. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +458 -41
  15. agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +76 -0
  16. agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +749 -0
  17. agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
  18. agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
  19. agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
  20. agentscope_runtime/engine/deployers/kubernetes_deployer.py +3 -0
  21. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +8 -2
  22. agentscope_runtime/engine/deployers/utils/docker_image_utils/image_factory.py +5 -0
  23. agentscope_runtime/engine/deployers/utils/net_utils.py +65 -0
  24. agentscope_runtime/engine/runner.py +17 -3
  25. agentscope_runtime/engine/schemas/exception.py +24 -0
  26. agentscope_runtime/engine/services/agent_state/redis_state_service.py +61 -8
  27. agentscope_runtime/engine/services/agent_state/state_service_factory.py +2 -5
  28. agentscope_runtime/engine/services/memory/redis_memory_service.py +129 -25
  29. agentscope_runtime/engine/services/session_history/redis_session_history_service.py +160 -34
  30. agentscope_runtime/engine/tracing/wrapper.py +18 -4
  31. agentscope_runtime/sandbox/__init__.py +14 -6
  32. agentscope_runtime/sandbox/box/base/__init__.py +2 -2
  33. agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
  34. agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
  35. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
  36. agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
  37. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
  38. agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
  39. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
  40. agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
  41. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
  42. agentscope_runtime/sandbox/box/sandbox.py +98 -65
  43. agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
  44. agentscope_runtime/sandbox/build.py +50 -57
  45. agentscope_runtime/sandbox/client/__init__.py +6 -1
  46. agentscope_runtime/sandbox/client/async_http_client.py +339 -0
  47. agentscope_runtime/sandbox/client/base.py +74 -0
  48. agentscope_runtime/sandbox/client/http_client.py +108 -329
  49. agentscope_runtime/sandbox/enums.py +7 -0
  50. agentscope_runtime/sandbox/manager/sandbox_manager.py +264 -4
  51. agentscope_runtime/sandbox/manager/server/app.py +7 -1
  52. agentscope_runtime/version.py +1 -1
  53. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/METADATA +109 -29
  54. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/RECORD +58 -46
  55. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/WHEEL +0 -0
  56. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/entry_points.txt +0 -0
  57. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/licenses/LICENSE +0 -0
  58. {agentscope_runtime-1.0.2.dist-info → agentscope_runtime-1.0.4.dist-info}/top_level.txt +0 -0
@@ -56,6 +56,15 @@ try:
56
56
  except ImportError:
57
57
  K8S_AVAILABLE = False
58
58
 
59
+ try:
60
+ from agentscope_runtime.engine.deployers.knative_deployer import (
61
+ KnativeDeployManager,
62
+ )
63
+
64
+ KNATIVE_AVAILABLE = True
65
+ except ImportError:
66
+ KNATIVE_AVAILABLE = False
67
+
59
68
 
60
69
  def _validate_source(source: str) -> tuple[str, str]:
61
70
  """
@@ -247,6 +256,7 @@ def deploy():
247
256
  - agentrun: Alibaba Cloud AgentRun
248
257
  - k8s: Kubernetes/ACK
249
258
  - local: Local deployment (detached mode)
259
+ - Knative: Knative/ACK Knative
250
260
 
251
261
  Use 'agentscope deploy <platform> --help' for platform-specific options.
252
262
  """
@@ -828,6 +838,13 @@ def agentrun(
828
838
  help="Target platform (e.g., 'linux/amd64', 'linux/arm64')",
829
839
  default="linux/amd64",
830
840
  )
841
+ @click.option(
842
+ "--pypi-mirror",
843
+ help="PyPI mirror URL for pip package installation (e.g., "
844
+ "https://pypi.tuna.tsinghua.edu.cn/simple). If not specified, "
845
+ "uses pip default.",
846
+ default=None,
847
+ )
831
848
  def k8s(
832
849
  source: str,
833
850
  name: str,
@@ -854,6 +871,7 @@ def k8s(
854
871
  deploy_timeout: int,
855
872
  health_check: bool,
856
873
  platform: str,
874
+ pypi_mirror: str,
857
875
  ):
858
876
  """
859
877
  Deploy to Kubernetes/ACK.
@@ -898,6 +916,7 @@ def k8s(
898
916
  "deploy_timeout": deploy_timeout,
899
917
  "health_check": health_check,
900
918
  "platform": platform,
919
+ "pypi_mirror": pypi_mirror,
901
920
  }
902
921
  merged_config = _merge_config(config_dict, cli_params)
903
922
 
@@ -918,6 +937,7 @@ def k8s(
918
937
  deploy_timeout = merged_config.get("deploy_timeout", 300)
919
938
  health_check = merged_config.get("health_check", True)
920
939
  platform = merged_config.get("platform")
940
+ pypi_mirror = merged_config.get("pypi_mirror")
921
941
 
922
942
  # Handle requirements (can be comma-separated string, list, or file
923
943
  # path)
@@ -1033,6 +1053,8 @@ def k8s(
1033
1053
  deploy_params["health_check"] = health_check
1034
1054
  if platform:
1035
1055
  deploy_params["platform"] = platform
1056
+ if pypi_mirror:
1057
+ deploy_params["pypi_mirror"] = pypi_mirror
1036
1058
 
1037
1059
  # Add agent_source for state saving
1038
1060
  deploy_params["agent_source"] = abs_source
@@ -1058,5 +1080,366 @@ def k8s(
1058
1080
  sys.exit(1)
1059
1081
 
1060
1082
 
1083
+ @deploy.command()
1084
+ @click.argument("source", required=True)
1085
+ @click.option("--name", help="Deployment name", default=None)
1086
+ @click.option(
1087
+ "--namespace",
1088
+ help="Kubernetes namespace",
1089
+ default="agentscope-runtime",
1090
+ )
1091
+ @click.option(
1092
+ "--kube-config-path",
1093
+ "-c",
1094
+ type=click.Path(exists=True),
1095
+ help="Path to knative service config file (.json, .yaml, or .yml)",
1096
+ )
1097
+ @click.option(
1098
+ "--port",
1099
+ help="Container port",
1100
+ type=int,
1101
+ default=8080,
1102
+ )
1103
+ @click.option(
1104
+ "--image-name",
1105
+ help="Docker image name",
1106
+ default="agent_app",
1107
+ )
1108
+ @click.option(
1109
+ "--image-tag",
1110
+ help="Docker image tag",
1111
+ default="linux-amd64",
1112
+ )
1113
+ @click.option(
1114
+ "--registry-url",
1115
+ help="Remote registry url",
1116
+ default="localhost",
1117
+ )
1118
+ @click.option(
1119
+ "--registry-namespace",
1120
+ help="Remote registry namespace",
1121
+ default="agentscope-runtime",
1122
+ )
1123
+ @click.option(
1124
+ "--push",
1125
+ is_flag=True,
1126
+ help="Push image to registry",
1127
+ )
1128
+ @click.option(
1129
+ "--entrypoint",
1130
+ "-e",
1131
+ help="Entrypoint file name for directory sources (e.g., 'app.py', "
1132
+ "'main.py')",
1133
+ default=None,
1134
+ )
1135
+ @click.option(
1136
+ "--env",
1137
+ "-E",
1138
+ multiple=True,
1139
+ help="Environment variable in KEY=VALUE format (can be repeated)",
1140
+ )
1141
+ @click.option(
1142
+ "--env-file",
1143
+ type=click.Path(exists=True),
1144
+ help="Path to .env file with environment variables",
1145
+ )
1146
+ @click.option(
1147
+ "--config",
1148
+ "-c",
1149
+ type=click.Path(exists=True),
1150
+ help="Path to knative service config file (.json, .yaml, or .yml)",
1151
+ )
1152
+ @click.option(
1153
+ "--base-image",
1154
+ help="Base Docker image",
1155
+ default="python:3.10-slim-bookworm",
1156
+ )
1157
+ @click.option(
1158
+ "--requirements",
1159
+ help="Python requirements (comma-separated or file path)",
1160
+ default=None,
1161
+ )
1162
+ @click.option(
1163
+ "--cpu-request",
1164
+ help="CPU resource request (e.g., '200m', '1')",
1165
+ default="200m",
1166
+ )
1167
+ @click.option(
1168
+ "--cpu-limit",
1169
+ help="CPU resource limit (e.g., '1000m', '2')",
1170
+ default="1000m",
1171
+ )
1172
+ @click.option(
1173
+ "--memory-request",
1174
+ help="Memory resource request (e.g., '512Mi', '1Gi')",
1175
+ default="512Mi",
1176
+ )
1177
+ @click.option(
1178
+ "--memory-limit",
1179
+ help="Memory resource limit (e.g., '2Gi', '4Gi')",
1180
+ default="2Gi",
1181
+ )
1182
+ @click.option(
1183
+ "--image-pull-policy",
1184
+ help="Image pull policy",
1185
+ type=click.Choice(["Always", "IfNotPresent", "Never"]),
1186
+ default="IfNotPresent",
1187
+ )
1188
+ @click.option(
1189
+ "--deploy-timeout",
1190
+ help="Deployment timeout in seconds",
1191
+ type=int,
1192
+ default=300,
1193
+ )
1194
+ @click.option(
1195
+ "--health-check",
1196
+ is_flag=True,
1197
+ help="Enable/disable health check",
1198
+ )
1199
+ @click.option(
1200
+ "--platform",
1201
+ help="Target platform (e.g., 'linux/amd64', 'linux/arm64')",
1202
+ default="linux/amd64",
1203
+ )
1204
+ @click.option(
1205
+ "--pypi-mirror",
1206
+ help="PyPI mirror URL for pip package installation (e.g., "
1207
+ "https://pypi.tuna.tsinghua.edu.cn/simple). If not specified, "
1208
+ "uses pip default.",
1209
+ default=None,
1210
+ )
1211
+ def knative(
1212
+ source: str,
1213
+ name: str,
1214
+ namespace: str,
1215
+ kube_config_path: str,
1216
+ port: int,
1217
+ image_name: str,
1218
+ image_tag: str,
1219
+ registry_url: str,
1220
+ registry_namespace: str,
1221
+ push: bool,
1222
+ entrypoint: str,
1223
+ env: tuple,
1224
+ env_file: str,
1225
+ config: str,
1226
+ base_image: str,
1227
+ requirements: str,
1228
+ cpu_request: str,
1229
+ cpu_limit: str,
1230
+ memory_request: str,
1231
+ memory_limit: str,
1232
+ image_pull_policy: str,
1233
+ deploy_timeout: int,
1234
+ health_check: bool,
1235
+ platform: str,
1236
+ pypi_mirror: str,
1237
+ ):
1238
+ """
1239
+ Deploy to Knative/ACK Knative.
1240
+
1241
+ SOURCE can be a Python file or project directory containing an agent.
1242
+
1243
+ This will build a Docker image and deploy it to your Knative cluster.
1244
+ """
1245
+ if not KNATIVE_AVAILABLE:
1246
+ echo_error("Knative deployer is not available")
1247
+ echo_info("Please ensure Knative are available")
1248
+ sys.exit(1)
1249
+
1250
+ try:
1251
+ echo_info(f"Preparing deployment from {source}...")
1252
+
1253
+ # Load config file if provided
1254
+ config_dict = {}
1255
+ if config:
1256
+ echo_info(f"Loading configuration from {config}...")
1257
+ config_dict = _load_config_file(config)
1258
+
1259
+ # make sure not to push if use local registry_url
1260
+ if registry_url == "localhost":
1261
+ push = False
1262
+
1263
+ # Merge CLI parameters with config (CLI takes precedence)
1264
+ cli_params = {
1265
+ "name": name,
1266
+ "namespace": namespace,
1267
+ "port": port,
1268
+ "image_name": image_name,
1269
+ "image_tag": image_tag,
1270
+ "registry_url": registry_url,
1271
+ "registry_namespace": registry_namespace,
1272
+ "push_to_registry": push if push else None,
1273
+ "entrypoint": entrypoint,
1274
+ "base_image": base_image,
1275
+ "requirements": requirements,
1276
+ "image_pull_policy": image_pull_policy,
1277
+ "deploy_timeout": deploy_timeout,
1278
+ "health_check": health_check,
1279
+ "platform": platform,
1280
+ "pypi_mirror": pypi_mirror,
1281
+ }
1282
+ merged_config = _merge_config(config_dict, cli_params)
1283
+
1284
+ # Extract parameters with defaults
1285
+ namespace = merged_config.get("namespace", "agentscope-runtime")
1286
+ port = merged_config.get("port", 8080)
1287
+ image_name = merged_config.get("image_name", "agent_llm")
1288
+ image_tag = merged_config.get("image_tag", "latest")
1289
+ registry_url = merged_config.get("registry_url", "localhost")
1290
+ registry_namespace = merged_config.get(
1291
+ "registry_namespace",
1292
+ "agentscope-runtime",
1293
+ )
1294
+ push_to_registry = merged_config.get("push_to_registry", False)
1295
+ entrypoint = merged_config.get("entrypoint")
1296
+ base_image = merged_config.get("base_image")
1297
+ deploy_timeout = merged_config.get("deploy_timeout", 300)
1298
+ health_check = merged_config.get("health_check", True)
1299
+ platform = merged_config.get("platform")
1300
+ pypi_mirror = merged_config.get("pypi_mirror")
1301
+
1302
+ # Handle requirements (can be comma-separated string, list, or file
1303
+ # path)
1304
+ requirements = merged_config.get("requirements")
1305
+ if requirements:
1306
+ if isinstance(requirements, str):
1307
+ # Check if it's a file path
1308
+ if os.path.isfile(requirements):
1309
+ with open(requirements, "r", encoding="utf-8") as f:
1310
+ requirements = [
1311
+ line.strip()
1312
+ for line in f
1313
+ if line.strip() and not line.startswith("#")
1314
+ ]
1315
+ else:
1316
+ # Treat as comma-separated string
1317
+ requirements = [r.strip() for r in requirements.split(",")]
1318
+
1319
+ # Handle extra_packages
1320
+ extra_packages = merged_config.get("extra_packages", [])
1321
+
1322
+ # Handle image_pull_policy
1323
+ image_pull_policy = merged_config.get("image_pull_policy")
1324
+
1325
+ # Build runtime_config from resource parameters
1326
+ runtime_config = merged_config.get("runtime_config", {})
1327
+ if not runtime_config.get("resources"):
1328
+ resources = {}
1329
+ if cpu_request or memory_request:
1330
+ resources["requests"] = {}
1331
+ if cpu_request:
1332
+ resources["requests"]["cpu"] = cpu_request
1333
+ if memory_request:
1334
+ resources["requests"]["memory"] = memory_request
1335
+ if cpu_limit or memory_limit:
1336
+ resources["limits"] = {}
1337
+ if cpu_limit:
1338
+ resources["limits"]["cpu"] = cpu_limit
1339
+ if memory_limit:
1340
+ resources["limits"]["memory"] = memory_limit
1341
+ if resources:
1342
+ runtime_config["resources"] = resources
1343
+
1344
+ if image_pull_policy and "image_pull_policy" not in runtime_config:
1345
+ runtime_config["image_pull_policy"] = image_pull_policy
1346
+
1347
+ # Validate source
1348
+ abs_source, source_type = _validate_source(source)
1349
+
1350
+ # Parse environment variables (from config, env_file, and CLI)
1351
+ environment = merged_config.get("environment", {}).copy()
1352
+ cli_env = _parse_environment(env, env_file)
1353
+ environment.update(cli_env) # CLI env overrides config env
1354
+
1355
+ if environment:
1356
+ echo_info(f"Using {len(environment)} environment variable(s)")
1357
+
1358
+ # Create deployer
1359
+ k8s_config = K8sConfig(
1360
+ k8s_namespace=namespace,
1361
+ kubeconfig_path=kube_config_path,
1362
+ )
1363
+ registry_config = RegistryConfig(
1364
+ registry_url=registry_url,
1365
+ namespace=registry_namespace,
1366
+ )
1367
+ deployer = KnativeDeployManager(
1368
+ kube_config=k8s_config,
1369
+ registry_config=registry_config,
1370
+ )
1371
+
1372
+ # Prepare entrypoint specification
1373
+ if source_type == "directory":
1374
+ # For directory: find entrypoint and create path
1375
+ project_dir = abs_source
1376
+ entry_script = _find_entrypoint(project_dir, entrypoint)
1377
+ entrypoint_spec = os.path.join(project_dir, entry_script)
1378
+
1379
+ echo_info(f"Using project directory: {project_dir}")
1380
+ echo_info(f"Entry script: {entry_script}")
1381
+ else:
1382
+ # For single file: use file path directly
1383
+ entrypoint_spec = abs_source
1384
+
1385
+ echo_info(f"Using file: {abs_source}")
1386
+
1387
+ # Deploy to Knative using entrypoint
1388
+ echo_info("Deploying to Knative...")
1389
+
1390
+ # Build deploy parameters
1391
+ deploy_params = {
1392
+ "entrypoint": entrypoint_spec,
1393
+ "port": port,
1394
+ "image_name": image_name,
1395
+ "image_tag": image_tag,
1396
+ "push_to_registry": push_to_registry,
1397
+ "environment": environment if environment else None,
1398
+ }
1399
+
1400
+ # Add optional parameters if provided
1401
+ if base_image:
1402
+ deploy_params["base_image"] = base_image
1403
+ if requirements:
1404
+ deploy_params["requirements"] = requirements
1405
+ if extra_packages:
1406
+ deploy_params["extra_packages"] = extra_packages
1407
+ if runtime_config:
1408
+ deploy_params["runtime_config"] = runtime_config
1409
+ if deploy_timeout:
1410
+ deploy_params["deploy_timeout"] = deploy_timeout
1411
+ if health_check is not None:
1412
+ deploy_params["health_check"] = health_check
1413
+ if platform:
1414
+ deploy_params["platform"] = platform
1415
+ if pypi_mirror:
1416
+ deploy_params["pypi_mirror"] = pypi_mirror
1417
+
1418
+ # Add agent_source for state saving
1419
+ deploy_params["agent_source"] = abs_source
1420
+ deploy_params["labels"] = {
1421
+ "app": "agent-ksvc",
1422
+ }
1423
+
1424
+ result = asyncio.run(deployer.deploy(**deploy_params))
1425
+
1426
+ deploy_id = result.get("deploy_id")
1427
+ url = result.get("url")
1428
+ resource_name = result.get("resource_name")
1429
+
1430
+ echo_success("Deployment successful!")
1431
+ echo_info(f"Deployment ID: {deploy_id}")
1432
+ echo_info(f"Resource Name: {resource_name}")
1433
+ echo_info(f"URL: {url}")
1434
+ echo_info(f"Namespace: {namespace}")
1435
+
1436
+ except Exception as e:
1437
+ echo_error(f"Deployment failed: {e}")
1438
+ import traceback
1439
+
1440
+ echo_error(traceback.format_exc())
1441
+ sys.exit(1)
1442
+
1443
+
1061
1444
  if __name__ == "__main__":
1062
1445
  deploy()
@@ -38,7 +38,10 @@ class RedisMapping(Mapping):
38
38
  match=search_pattern,
39
39
  )
40
40
  for key in keys:
41
- decoded_key = key.decode("utf-8")
41
+ if isinstance(key, bytes):
42
+ decoded_key = key.decode("utf-8")
43
+ else:
44
+ decoded_key = str(key)
42
45
  yield self._strip_prefix(decoded_key)
43
46
 
44
47
  if cursor == 0: