agentscope-runtime 0.1.4__py3-none-any.whl → 0.1.5b1__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 (43) hide show
  1. agentscope_runtime/engine/agents/agentscope_agent/agent.py +3 -0
  2. agentscope_runtime/engine/deployers/__init__.py +13 -0
  3. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +0 -0
  4. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +2886 -0
  5. agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +51 -0
  6. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +314 -0
  7. agentscope_runtime/engine/deployers/cli_fc_deploy.py +143 -0
  8. agentscope_runtime/engine/deployers/kubernetes_deployer.py +265 -0
  9. agentscope_runtime/engine/deployers/local_deployer.py +356 -501
  10. agentscope_runtime/engine/deployers/modelstudio_deployer.py +626 -0
  11. agentscope_runtime/engine/deployers/utils/__init__.py +0 -0
  12. agentscope_runtime/engine/deployers/utils/deployment_modes.py +14 -0
  13. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +8 -0
  14. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +429 -0
  15. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +240 -0
  16. agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +297 -0
  17. agentscope_runtime/engine/deployers/utils/package_project_utils.py +932 -0
  18. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +9 -0
  19. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +504 -0
  20. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +157 -0
  21. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +268 -0
  22. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +75 -0
  23. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +220 -0
  24. agentscope_runtime/engine/deployers/utils/wheel_packager.py +389 -0
  25. agentscope_runtime/engine/helpers/agent_api_builder.py +651 -0
  26. agentscope_runtime/engine/runner.py +36 -10
  27. agentscope_runtime/engine/schemas/agent_schemas.py +70 -2
  28. agentscope_runtime/engine/schemas/embedding.py +37 -0
  29. agentscope_runtime/engine/schemas/modelstudio_llm.py +310 -0
  30. agentscope_runtime/engine/schemas/oai_llm.py +538 -0
  31. agentscope_runtime/engine/schemas/realtime.py +254 -0
  32. agentscope_runtime/engine/services/mem0_memory_service.py +124 -0
  33. agentscope_runtime/engine/services/memory_service.py +2 -1
  34. agentscope_runtime/engine/services/redis_session_history_service.py +4 -3
  35. agentscope_runtime/engine/services/session_history_service.py +4 -3
  36. agentscope_runtime/sandbox/manager/container_clients/kubernetes_client.py +555 -10
  37. agentscope_runtime/version.py +1 -1
  38. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/METADATA +21 -4
  39. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/RECORD +43 -16
  40. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/entry_points.txt +1 -0
  41. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/WHEEL +0 -0
  42. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/licenses/LICENSE +0 -0
  43. {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- # pylint: disable=too-many-branches
3
- import os
4
- import time
2
+ # pylint: disable=too-many-branches, self-assigning-variable
3
+ # pylint: disable=too-many-statements
4
+
5
5
  import hashlib
6
- import traceback
7
6
  import logging
7
+ import time
8
+ import traceback
9
+ from typing import Optional, Tuple
8
10
 
9
11
  from kubernetes import client
10
12
  from kubernetes import config as k8s_config
@@ -14,12 +16,19 @@ from .base_client import BaseClient
14
16
 
15
17
  logger = logging.getLogger(__name__)
16
18
 
19
+ DEFAULT_IMAGE_REGISTRY = "agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
20
+
17
21
 
18
22
  class KubernetesClient(BaseClient):
19
- def __init__(self, config=None):
23
+ def __init__(
24
+ self,
25
+ config=None,
26
+ image_registry: Optional[str] = DEFAULT_IMAGE_REGISTRY,
27
+ ):
20
28
  self.config = config
21
29
  namespace = self.config.k8s_namespace
22
30
  kubeconfig = self.config.kubeconfig_path
31
+ self.image_registry = image_registry
23
32
  try:
24
33
  if kubeconfig:
25
34
  k8s_config.load_kube_config(config_file=kubeconfig)
@@ -31,6 +40,7 @@ class KubernetesClient(BaseClient):
31
40
  except k8s_config.ConfigException:
32
41
  k8s_config.load_kube_config()
33
42
  self.v1 = client.CoreV1Api()
43
+ self.apps_v1 = client.AppsV1Api() # For Deployments
34
44
  self.namespace = namespace
35
45
  # Test connection
36
46
  self.v1.list_namespace()
@@ -45,6 +55,61 @@ class KubernetesClient(BaseClient):
45
55
  "• For in-cluster: ensure proper RBAC permissions",
46
56
  ) from e
47
57
 
58
+ def _is_local_cluster(self):
59
+ """
60
+ Determine if we're connected to a local Kubernetes cluster.
61
+
62
+ Returns:
63
+ bool: True if connected to a local cluster, False otherwise
64
+ """
65
+ try:
66
+ # Get the current context configuration
67
+ contexts, current_context = k8s_config.list_kube_config_contexts(
68
+ config_file=self.config.kubeconfig_path
69
+ if hasattr(self.config, "kubeconfig_path")
70
+ and self.config.kubeconfig_path
71
+ else None,
72
+ )
73
+
74
+ if current_context and current_context.get("context"):
75
+ cluster_name = current_context["context"].get("cluster", "")
76
+ server = None
77
+
78
+ # Get cluster server URL
79
+ for cluster in contexts.get("clusters", []):
80
+ if cluster["name"] == cluster_name:
81
+ server = cluster.get("cluster", {}).get("server", "")
82
+ break
83
+
84
+ if server:
85
+ # Check for common local cluster patterns
86
+ local_patterns = [
87
+ "localhost",
88
+ "127.0.0.1",
89
+ "0.0.0.0",
90
+ "docker-desktop",
91
+ "kind-", # kind clusters
92
+ "minikube", # minikube
93
+ "k3d-", # k3d clusters
94
+ "colima", # colima
95
+ ]
96
+
97
+ server_lower = server.lower()
98
+ cluster_lower = cluster_name.lower()
99
+
100
+ for pattern in local_patterns:
101
+ if pattern in server_lower or pattern in cluster_lower:
102
+ return True
103
+
104
+ return False
105
+
106
+ except Exception as e:
107
+ logger.debug(
108
+ f"Could not determine cluster type, assuming remote: {e}",
109
+ )
110
+ # If we can't determine, assume remote for safety
111
+ return False
112
+
48
113
  def _parse_port_spec(self, port_spec):
49
114
  """
50
115
  Parse port specification.
@@ -93,10 +158,15 @@ class KubernetesClient(BaseClient):
93
158
 
94
159
  # Container specification
95
160
  # TODO: use image from docker registry first
161
+
162
+ if not self.image_registry:
163
+ image = image
164
+ else:
165
+ image = f"{self.image_registry}/{image}"
166
+
96
167
  container = client.V1Container(
97
168
  name=container_name,
98
- image=f"agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
99
- f"/{image}",
169
+ image=image,
100
170
  image_pull_policy=runtime_config.get(
101
171
  "image_pull_policy",
102
172
  "IfNotPresent",
@@ -564,9 +634,8 @@ class KubernetesClient(BaseClient):
564
634
  def _get_pod_node_ip(self, pod_name):
565
635
  """Get the IP of the node where the pod is running"""
566
636
 
567
- # Check if we are running in Colima, where pod runs in VM
568
- docker_host = os.getenv("DOCKER_HOST", "")
569
- if "colima" in docker_host.lower():
637
+ # Check if we are using a local Kubernetes cluster
638
+ if self._is_local_cluster():
570
639
  return "localhost"
571
640
 
572
641
  try:
@@ -603,3 +672,479 @@ class KubernetesClient(BaseClient):
603
672
  except Exception as e:
604
673
  logger.error(f"Failed to get pod node IP: {e}")
605
674
  return None
675
+
676
+ def _create_deployment_spec(
677
+ self,
678
+ image,
679
+ name,
680
+ ports=None,
681
+ volumes=None,
682
+ environment=None,
683
+ runtime_config=None,
684
+ replicas=1,
685
+ ):
686
+ """Create a Kubernetes Deployment specification."""
687
+ if runtime_config is None:
688
+ runtime_config = {}
689
+
690
+ container_name = name or "main-container"
691
+
692
+ # Use image registry if configured
693
+ if not self.image_registry:
694
+ full_image = image
695
+ else:
696
+ full_image = f"{self.image_registry}/{image}"
697
+
698
+ # Create container spec (reuse the existing pod spec logic)
699
+ container = client.V1Container(
700
+ name=container_name,
701
+ image=full_image,
702
+ image_pull_policy=runtime_config.get(
703
+ "image_pull_policy",
704
+ "IfNotPresent",
705
+ ),
706
+ )
707
+
708
+ # Configure ports
709
+ if ports:
710
+ container_ports = []
711
+ for port_spec in ports:
712
+ port_info = self._parse_port_spec(port_spec)
713
+ if port_info:
714
+ container_ports.append(
715
+ client.V1ContainerPort(
716
+ container_port=port_info["port"],
717
+ protocol=port_info["protocol"],
718
+ ),
719
+ )
720
+ if container_ports:
721
+ container.ports = container_ports
722
+
723
+ # Configure environment variables
724
+ if environment:
725
+ env_vars = []
726
+ for key, value in environment.items():
727
+ env_vars.append(client.V1EnvVar(name=key, value=str(value)))
728
+ container.env = env_vars
729
+
730
+ # Configure volume mounts and volumes
731
+ volume_mounts = []
732
+ pod_volumes = []
733
+ if volumes:
734
+ for volume_idx, (host_path, mount_info) in enumerate(
735
+ volumes.items(),
736
+ ):
737
+ if isinstance(mount_info, dict):
738
+ container_path = mount_info["bind"]
739
+ mode = mount_info.get("mode", "rw")
740
+ else:
741
+ container_path = mount_info
742
+ mode = "rw"
743
+ volume_name = f"vol-{volume_idx}"
744
+
745
+ # Create volume mount
746
+ volume_mounts.append(
747
+ client.V1VolumeMount(
748
+ name=volume_name,
749
+ mount_path=container_path,
750
+ read_only=(mode == "ro"),
751
+ ),
752
+ )
753
+ # Create host path volume
754
+ pod_volumes.append(
755
+ client.V1Volume(
756
+ name=volume_name,
757
+ host_path=client.V1HostPathVolumeSource(
758
+ path=host_path,
759
+ ),
760
+ ),
761
+ )
762
+
763
+ if volume_mounts:
764
+ container.volume_mounts = volume_mounts
765
+
766
+ # Apply runtime config to container
767
+ if "resources" in runtime_config:
768
+ container.resources = client.V1ResourceRequirements(
769
+ **runtime_config["resources"],
770
+ )
771
+
772
+ if "security_context" in runtime_config:
773
+ container.security_context = client.V1SecurityContext(
774
+ **runtime_config["security_context"],
775
+ )
776
+
777
+ # Pod template specification
778
+ pod_spec = client.V1PodSpec(
779
+ containers=[container],
780
+ restart_policy=runtime_config.get(
781
+ "restart_policy",
782
+ "Always",
783
+ ), # Deployments typically use Always
784
+ )
785
+
786
+ if pod_volumes:
787
+ pod_spec.volumes = pod_volumes
788
+
789
+ if "node_selector" in runtime_config:
790
+ pod_spec.node_selector = runtime_config["node_selector"]
791
+
792
+ if "tolerations" in runtime_config:
793
+ pod_spec.tolerations = runtime_config["tolerations"]
794
+
795
+ # Handle image pull secrets
796
+ image_pull_secrets = runtime_config.get("image_pull_secrets", [])
797
+ if image_pull_secrets:
798
+ secrets = []
799
+ for secret_name in image_pull_secrets:
800
+ secrets.append(client.V1LocalObjectReference(name=secret_name))
801
+ pod_spec.image_pull_secrets = secrets
802
+
803
+ # Pod template
804
+ pod_template = client.V1PodTemplateSpec(
805
+ metadata=client.V1ObjectMeta(
806
+ labels={
807
+ "app": name,
808
+ "created-by": "kubernetes-client",
809
+ },
810
+ ),
811
+ spec=pod_spec,
812
+ )
813
+
814
+ # Deployment specification
815
+ deployment_spec = client.V1DeploymentSpec(
816
+ replicas=replicas,
817
+ selector=client.V1LabelSelector(
818
+ match_labels={"app": name},
819
+ ),
820
+ template=pod_template,
821
+ )
822
+
823
+ return deployment_spec
824
+
825
+ def _create_loadbalancer_service(self, deployment_name, port_list):
826
+ """Create a LoadBalancer service for the deployment."""
827
+ try:
828
+ service_name = f"{deployment_name}-lb-service"
829
+ selector = {"app": deployment_name}
830
+
831
+ # Construct multi-port configuration
832
+ service_ports = []
833
+ for port_info in port_list:
834
+ port = port_info["port"]
835
+ protocol = port_info["protocol"]
836
+ service_ports.append(
837
+ client.V1ServicePort(
838
+ name=f"port-{port}",
839
+ port=port,
840
+ target_port=port,
841
+ protocol=protocol,
842
+ ),
843
+ )
844
+
845
+ service_spec = client.V1ServiceSpec(
846
+ selector=selector,
847
+ ports=service_ports,
848
+ type="LoadBalancer",
849
+ )
850
+
851
+ service = client.V1Service(
852
+ api_version="v1",
853
+ kind="Service",
854
+ metadata=client.V1ObjectMeta(
855
+ name=service_name,
856
+ namespace=self.namespace,
857
+ ),
858
+ spec=service_spec,
859
+ )
860
+
861
+ # Create the service
862
+ self.v1.create_namespaced_service(
863
+ namespace=self.namespace,
864
+ body=service,
865
+ )
866
+
867
+ logger.debug(
868
+ f"LoadBalancer service '{service_name}' created successfully",
869
+ )
870
+ return True, service_name
871
+ except Exception as e:
872
+ logger.error(
873
+ f"Failed to create LoadBalancer service for deployment "
874
+ f"{deployment_name}: "
875
+ f"{e}, {traceback.format_exc()}",
876
+ )
877
+ return False, None
878
+
879
+ def create_deployment(
880
+ self,
881
+ image,
882
+ name=None,
883
+ ports=None,
884
+ volumes=None,
885
+ environment=None,
886
+ runtime_config=None,
887
+ replicas=1,
888
+ create_service=True,
889
+ ) -> Tuple[str, list, str] | Tuple[None, None, None]:
890
+ """
891
+ Create a new Kubernetes Deployment with LoadBalancer service.
892
+
893
+ Args:
894
+ image: Container image name
895
+ name: Deployment name (auto-generated if None)
896
+ ports: List of ports to expose
897
+ volumes: Volume mounts dictionary
898
+ environment: Environment variables dictionary
899
+ runtime_config: Runtime configuration dictionary
900
+ replicas: Number of replicas for the deployment
901
+ create_service: Whether to create LoadBalancer service
902
+
903
+ Returns:
904
+ Tuple of (deployment_name, ports, load_balancer_ip)
905
+ """
906
+ if not name:
907
+ name = f"deploy-{hashlib.md5(image.encode()).hexdigest()[:8]}"
908
+
909
+ try:
910
+ # Create deployment specification
911
+ deployment_spec = self._create_deployment_spec(
912
+ image,
913
+ name,
914
+ ports,
915
+ volumes,
916
+ environment,
917
+ runtime_config,
918
+ replicas,
919
+ )
920
+
921
+ # Create deployment metadata
922
+ metadata = client.V1ObjectMeta(
923
+ name=name,
924
+ namespace=self.namespace,
925
+ labels={
926
+ "created-by": "kubernetes-client",
927
+ "app": name,
928
+ },
929
+ )
930
+
931
+ # Create deployment object
932
+ deployment = client.V1Deployment(
933
+ api_version="apps/v1",
934
+ kind="Deployment",
935
+ metadata=metadata,
936
+ spec=deployment_spec,
937
+ )
938
+
939
+ # Create the deployment
940
+ self.apps_v1.create_namespaced_deployment(
941
+ namespace=self.namespace,
942
+ body=deployment,
943
+ )
944
+
945
+ logger.debug(
946
+ f"Deployment '{name}' created successfully in namespace "
947
+ f"'{self.namespace}' with {replicas} replicas",
948
+ )
949
+
950
+ service_info = None
951
+ load_balancer_ip = None
952
+
953
+ # Create LoadBalancer service if requested and ports are specified
954
+ if create_service and ports:
955
+ parsed_ports = []
956
+ for port_spec in ports:
957
+ port_info = self._parse_port_spec(port_spec)
958
+ if port_info:
959
+ parsed_ports.append(port_info)
960
+
961
+ if parsed_ports:
962
+ (
963
+ service_created,
964
+ service_name,
965
+ ) = self._create_loadbalancer_service(
966
+ name,
967
+ parsed_ports,
968
+ )
969
+ if service_created:
970
+ service_info = {
971
+ "name": service_name,
972
+ "type": "LoadBalancer",
973
+ "ports": [p["port"] for p in parsed_ports],
974
+ }
975
+ # Wait a bit and try to get LoadBalancer IP
976
+ time.sleep(2)
977
+ load_balancer_ip = self._get_loadbalancer_ip(
978
+ service_name,
979
+ )
980
+
981
+ # Wait for deployment to be ready
982
+ if not self.wait_for_deployment_ready(name, timeout=120):
983
+ logger.warning(f"Deployment '{name}' may not be fully ready")
984
+
985
+ logger.debug(
986
+ f"Deployment '{name}' created successfully with service: "
987
+ f"{service_info}",
988
+ )
989
+
990
+ return (
991
+ name,
992
+ service_info["ports"] if service_info else [],
993
+ load_balancer_ip or "",
994
+ )
995
+
996
+ except Exception as e:
997
+ logger.error(
998
+ f"Failed to create deployment: {e}, {traceback.format_exc()}",
999
+ )
1000
+ return None, None, None
1001
+
1002
+ def wait_for_deployment_ready(self, deployment_name, timeout=300):
1003
+ """Wait for a deployment to be ready."""
1004
+ start_time = time.time()
1005
+ while time.time() - start_time < timeout:
1006
+ try:
1007
+ deployment = self.apps_v1.read_namespaced_deployment(
1008
+ name=deployment_name,
1009
+ namespace=self.namespace,
1010
+ )
1011
+
1012
+ # Check if deployment is ready
1013
+ if (
1014
+ deployment.status.ready_replicas
1015
+ and deployment.status.ready_replicas
1016
+ == deployment.spec.replicas
1017
+ ):
1018
+ return True
1019
+
1020
+ time.sleep(3)
1021
+ except ApiException as e:
1022
+ if e.status == 404:
1023
+ return False
1024
+ time.sleep(3)
1025
+ return False
1026
+
1027
+ def _get_loadbalancer_ip(self, service_name, timeout=30):
1028
+ """Get LoadBalancer external IP address."""
1029
+ start_time = time.time()
1030
+ while time.time() - start_time < timeout:
1031
+ try:
1032
+ service = self.v1.read_namespaced_service(
1033
+ name=service_name,
1034
+ namespace=self.namespace,
1035
+ )
1036
+
1037
+ if (
1038
+ service.status.load_balancer
1039
+ and service.status.load_balancer.ingress
1040
+ ):
1041
+ ingress = service.status.load_balancer.ingress[0]
1042
+ # Return IP or hostname
1043
+ return ingress.ip or ingress.hostname
1044
+
1045
+ time.sleep(2)
1046
+ except Exception as e:
1047
+ logger.debug(f"Waiting for LoadBalancer IP: {e}")
1048
+ time.sleep(2)
1049
+
1050
+ logger.debug(
1051
+ f"LoadBalancer IP not available for service {service_name}",
1052
+ )
1053
+ return None
1054
+
1055
+ def remove_deployment(self, deployment_name, remove_service=True):
1056
+ """Remove a Kubernetes Deployment and optionally its service."""
1057
+ try:
1058
+ # Remove associated LoadBalancer service first if requested
1059
+ if remove_service:
1060
+ service_name = f"{deployment_name}-lb-service"
1061
+ try:
1062
+ self.v1.delete_namespaced_service(
1063
+ name=service_name,
1064
+ namespace=self.namespace,
1065
+ )
1066
+ logger.debug(
1067
+ f"Removed LoadBalancer service {service_name}",
1068
+ )
1069
+ except ApiException as e:
1070
+ if e.status != 404:
1071
+ logger.warning(
1072
+ f"Failed to remove service {service_name}: {e}",
1073
+ )
1074
+
1075
+ # Remove the deployment
1076
+ self.apps_v1.delete_namespaced_deployment(
1077
+ name=deployment_name,
1078
+ namespace=self.namespace,
1079
+ body=client.V1DeleteOptions(
1080
+ propagation_policy="Foreground",
1081
+ ),
1082
+ )
1083
+
1084
+ logger.debug(
1085
+ f"Deployment '{deployment_name}' removed successfully",
1086
+ )
1087
+ return True
1088
+
1089
+ except ApiException as e:
1090
+ if e.status == 404:
1091
+ logger.warning(f"Deployment '{deployment_name}' not found")
1092
+ return True
1093
+ logger.error(f"Failed to remove deployment: {e.reason}")
1094
+ return False
1095
+ except Exception as e:
1096
+ logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1097
+ return False
1098
+
1099
+ def get_deployment_status(self, deployment_name):
1100
+ """Get the current status of the specified deployment."""
1101
+ try:
1102
+ deployment = self.apps_v1.read_namespaced_deployment(
1103
+ name=deployment_name,
1104
+ namespace=self.namespace,
1105
+ )
1106
+
1107
+ return {
1108
+ "name": deployment_name,
1109
+ "replicas": deployment.spec.replicas,
1110
+ "ready_replicas": deployment.status.ready_replicas or 0,
1111
+ "available_replicas": deployment.status.available_replicas
1112
+ or 0,
1113
+ "unavailable_replicas": deployment.status.unavailable_replicas
1114
+ or 0,
1115
+ "conditions": [
1116
+ {
1117
+ "type": condition.type,
1118
+ "status": condition.status,
1119
+ "reason": condition.reason,
1120
+ "message": condition.message,
1121
+ }
1122
+ for condition in (deployment.status.conditions or [])
1123
+ ],
1124
+ }
1125
+ except ApiException as e:
1126
+ if e.status == 404:
1127
+ logger.warning(f"Deployment '{deployment_name}' not found")
1128
+ else:
1129
+ logger.error(f"Failed to get deployment status: {e.reason}")
1130
+ return None
1131
+ except Exception as e:
1132
+ logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1133
+ return None
1134
+
1135
+ def list_deployments(self, label_selector=None):
1136
+ """List deployments in the namespace."""
1137
+ try:
1138
+ deployments = self.apps_v1.list_namespaced_deployment(
1139
+ namespace=self.namespace,
1140
+ label_selector=label_selector,
1141
+ )
1142
+ return [
1143
+ deployment.metadata.name for deployment in deployments.items
1144
+ ]
1145
+ except ApiException as e:
1146
+ logger.error(f"Failed to list deployments: {e.reason}")
1147
+ return []
1148
+ except Exception as e:
1149
+ logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1150
+ return []
@@ -1,2 +1,2 @@
1
1
  # -*- coding: utf-8 -*-
2
- __version__ = "v0.1.4"
2
+ __version__ = "0.1.5b1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentscope-runtime
3
- Version: 0.1.4
3
+ Version: 0.1.5b1
4
4
  Summary: A production-ready runtime framework for agent applications, providing secure sandboxed execution environments and scalable deployment solutions with multi-framework support.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -8,7 +8,7 @@ License-File: LICENSE
8
8
  Requires-Dist: mcp>=1.13
9
9
  Requires-Dist: fastapi>=0.104.0
10
10
  Requires-Dist: uvicorn[standard]>=0.24.0
11
- Requires-Dist: openai
11
+ Requires-Dist: openai>=1.108.1
12
12
  Requires-Dist: pydantic>=2.11.7
13
13
  Requires-Dist: requests>=2.32.4
14
14
  Provides-Extra: dev
@@ -56,6 +56,22 @@ Requires-Dist: langchain-community>=0.3.27; extra == "llamaindex-rag"
56
56
  Requires-Dist: bs4>=0.0.2; extra == "llamaindex-rag"
57
57
  Provides-Extra: memory-ext
58
58
  Requires-Dist: reme-ai==0.1.9; python_full_version >= "3.12" and extra == "memory-ext"
59
+ Requires-Dist: mem0ai>=0.1.117; extra == "memory-ext"
60
+ Provides-Extra: deployment
61
+ Requires-Dist: alibabacloud-oss-v2; extra == "deployment"
62
+ Requires-Dist: alibabacloud-bailian20231229>=2.5.0; extra == "deployment"
63
+ Requires-Dist: build; extra == "deployment"
64
+ Requires-Dist: setuptools>=40.8.0; extra == "deployment"
65
+ Requires-Dist: wheel; extra == "deployment"
66
+ Requires-Dist: steel-sdk>=0.1.0; extra == "deployment"
67
+ Requires-Dist: alibabacloud-credentials; extra == "deployment"
68
+ Requires-Dist: jinja2; extra == "deployment"
69
+ Requires-Dist: psutil; extra == "deployment"
70
+ Requires-Dist: shortuuid>=1.0.13; extra == "deployment"
71
+ Requires-Dist: docker>=7.1.0; extra == "deployment"
72
+ Requires-Dist: kubernetes>=33.1.0; extra == "deployment"
73
+ Requires-Dist: PyYAML; extra == "deployment"
74
+ Requires-Dist: oss2>=2.19.1; extra == "deployment"
59
75
  Dynamic: license-file
60
76
 
61
77
  <div align="center">
@@ -405,7 +421,7 @@ limitations under the License.
405
421
 
406
422
  ## Contributors ✨
407
423
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
408
- [![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors-)
424
+ [![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-)
409
425
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
410
426
 
411
427
  Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -425,7 +441,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
425
441
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/jinliyl"><img src="https://avatars.githubusercontent.com/u/6469360?v=4?s=100" width="100px;" alt="jinliyl"/><br /><sub><b>jinliyl</b></sub></a><br /><a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=jinliyl" title="Code">💻</a> <a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=jinliyl" title="Documentation">📖</a></td>
426
442
  </tr>
427
443
  <tr>
428
- <td align="center" valign="top" width="14.28%"><a href="https://github.com/Osier-Yi"><img src="https://avatars.githubusercontent.com/u/8287381?v=4?s=100" width="100px;" alt="Osier-Yi"/><br /><sub><b>Osier-Yi</b></sub></a><br /><a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=Osier-Yi" title="Code">💻</a></td>
444
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Osier-Yi"><img src="https://avatars.githubusercontent.com/u/8287381?v=4?s=100" width="100px;" alt="Osier-Yi"/><br /><sub><b>Osier-Yi</b></sub></a><br /><a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=Osier-Yi" title="Code">💻</a> <a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=Osier-Yi" title="Documentation">📖</a></td>
445
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/kevinlin09"><img src="https://avatars.githubusercontent.com/u/26913335?v=4?s=100" width="100px;" alt="Kevin Lin"/><br /><sub><b>Kevin Lin</b></sub></a><br /><a href="https://github.com/agentscope-ai/agentscope-runtime/commits?author=kevinlin09" title="Code">💻</a></td>
429
446
  </tr>
430
447
  </tbody>
431
448
  <tfoot>