agentscope-runtime 1.0.4a1__py3-none-any.whl → 1.0.5__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/stream.py +2 -8
- agentscope_runtime/adapters/langgraph/stream.py +120 -70
- agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
- agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
- agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
- agentscope_runtime/adapters/utils.py +6 -0
- agentscope_runtime/cli/commands/deploy.py +836 -1
- agentscope_runtime/cli/commands/stop.py +16 -0
- agentscope_runtime/common/container_clients/__init__.py +52 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +6 -4
- agentscope_runtime/common/container_clients/boxlite_client.py +442 -0
- agentscope_runtime/common/container_clients/docker_client.py +0 -20
- agentscope_runtime/common/container_clients/fc_client.py +6 -4
- agentscope_runtime/common/container_clients/gvisor_client.py +38 -0
- agentscope_runtime/common/container_clients/knative_client.py +467 -0
- agentscope_runtime/common/utils/deprecation.py +164 -0
- agentscope_runtime/engine/__init__.py +4 -0
- agentscope_runtime/engine/app/agent_app.py +16 -4
- agentscope_runtime/engine/constant.py +1 -0
- agentscope_runtime/engine/deployers/__init__.py +34 -11
- agentscope_runtime/engine/deployers/adapter/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +26 -51
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +23 -13
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +4 -201
- agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +152 -25
- agentscope_runtime/engine/deployers/adapter/agui/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_adapter_utils.py +652 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_protocol_adapter.py +225 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
- agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
- agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
- agentscope_runtime/engine/deployers/pai_deployer.py +2335 -0
- agentscope_runtime/engine/deployers/utils/net_utils.py +37 -0
- agentscope_runtime/engine/deployers/utils/oss_utils.py +38 -0
- agentscope_runtime/engine/deployers/utils/package.py +46 -42
- agentscope_runtime/engine/helpers/agent_api_client.py +372 -0
- agentscope_runtime/engine/runner.py +13 -0
- agentscope_runtime/engine/schemas/agent_schemas.py +9 -3
- agentscope_runtime/engine/services/agent_state/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/redis_memory_service.py +15 -16
- agentscope_runtime/engine/services/session_history/__init__.py +7 -0
- agentscope_runtime/engine/tracing/local_logging_handler.py +2 -3
- agentscope_runtime/engine/tracing/wrapper.py +18 -4
- agentscope_runtime/sandbox/__init__.py +14 -6
- agentscope_runtime/sandbox/box/base/__init__.py +2 -2
- agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
- agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
- agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
- agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
- agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
- agentscope_runtime/sandbox/box/sandbox.py +102 -65
- agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
- agentscope_runtime/sandbox/client/__init__.py +6 -1
- agentscope_runtime/sandbox/client/async_http_client.py +339 -0
- agentscope_runtime/sandbox/client/base.py +74 -0
- agentscope_runtime/sandbox/client/http_client.py +108 -329
- agentscope_runtime/sandbox/enums.py +7 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +275 -29
- agentscope_runtime/sandbox/manager/server/app.py +7 -1
- agentscope_runtime/sandbox/manager/server/config.py +3 -1
- agentscope_runtime/sandbox/model/manager_config.py +11 -9
- agentscope_runtime/tools/modelstudio_memory/__init__.py +106 -0
- agentscope_runtime/tools/modelstudio_memory/base.py +220 -0
- agentscope_runtime/tools/modelstudio_memory/config.py +86 -0
- agentscope_runtime/tools/modelstudio_memory/core.py +594 -0
- agentscope_runtime/tools/modelstudio_memory/exceptions.py +60 -0
- agentscope_runtime/tools/modelstudio_memory/schemas.py +253 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/METADATA +186 -73
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/RECORD +79 -55
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/WHEEL +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""agentscope deploy command - Deploy agents to various platforms."""
|
|
3
3
|
# pylint: disable=too-many-statements, too-many-branches
|
|
4
|
+
# pylint: disable=too-many-nested-blocks
|
|
4
5
|
|
|
5
6
|
import asyncio
|
|
6
7
|
import json
|
|
7
8
|
import os
|
|
8
9
|
import sys
|
|
10
|
+
from typing import Optional
|
|
9
11
|
|
|
10
12
|
import click
|
|
11
13
|
import yaml
|
|
@@ -56,6 +58,26 @@ try:
|
|
|
56
58
|
except ImportError:
|
|
57
59
|
K8S_AVAILABLE = False
|
|
58
60
|
|
|
61
|
+
try:
|
|
62
|
+
from agentscope_runtime.engine.deployers.knative_deployer import (
|
|
63
|
+
KnativeDeployManager,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
KNATIVE_AVAILABLE = True
|
|
67
|
+
except ImportError:
|
|
68
|
+
KNATIVE_AVAILABLE = False
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
from agentscope_runtime.engine.deployers.pai_deployer import (
|
|
72
|
+
PAI_AVAILABLE,
|
|
73
|
+
PAIDeployConfig,
|
|
74
|
+
PAIDeployManager,
|
|
75
|
+
)
|
|
76
|
+
except ImportError:
|
|
77
|
+
PAI_AVAILABLE = False
|
|
78
|
+
PAIDeployConfig = None
|
|
79
|
+
PAIDeployManager = None
|
|
80
|
+
|
|
59
81
|
|
|
60
82
|
def _validate_source(source: str) -> tuple[str, str]:
|
|
61
83
|
"""
|
|
@@ -81,7 +103,10 @@ def _validate_source(source: str) -> tuple[str, str]:
|
|
|
81
103
|
raise ValueError(f"Source must be a file or directory: {abs_source}")
|
|
82
104
|
|
|
83
105
|
|
|
84
|
-
def _find_entrypoint(
|
|
106
|
+
def _find_entrypoint(
|
|
107
|
+
project_dir: str,
|
|
108
|
+
entrypoint: Optional[str] = None,
|
|
109
|
+
) -> str:
|
|
85
110
|
"""
|
|
86
111
|
Find or validate entrypoint file in project directory.
|
|
87
112
|
|
|
@@ -176,6 +201,33 @@ def _merge_config(config_dict: dict, cli_params: dict) -> dict:
|
|
|
176
201
|
return merged
|
|
177
202
|
|
|
178
203
|
|
|
204
|
+
def _parse_tags(tag_tuples: tuple) -> dict:
|
|
205
|
+
"""
|
|
206
|
+
Parse tags from --tag options.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
tag_tuples: Tuple of KEY=VALUE strings from --tag options
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Dictionary of tags
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
ValueError: If tag format is invalid
|
|
216
|
+
"""
|
|
217
|
+
tags = {}
|
|
218
|
+
|
|
219
|
+
for tag_pair in tag_tuples:
|
|
220
|
+
if "=" not in tag_pair:
|
|
221
|
+
raise ValueError(
|
|
222
|
+
f"Invalid tag format: '{tag_pair}'. Use KEY=VALUE format",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
key, value = tag_pair.split("=", 1)
|
|
226
|
+
tags[key.strip()] = value.strip()
|
|
227
|
+
|
|
228
|
+
return tags
|
|
229
|
+
|
|
230
|
+
|
|
179
231
|
def _parse_environment(env_tuples: tuple, env_file: str = None) -> dict:
|
|
180
232
|
"""
|
|
181
233
|
Parse environment variables from --env options and --env-file.
|
|
@@ -245,8 +297,10 @@ def deploy():
|
|
|
245
297
|
\b
|
|
246
298
|
- modelstudio: Alibaba Cloud ModelStudio
|
|
247
299
|
- agentrun: Alibaba Cloud AgentRun
|
|
300
|
+
- pai: Alibaba Cloud PAI (Platform for AI)
|
|
248
301
|
- k8s: Kubernetes/ACK
|
|
249
302
|
- local: Local deployment (detached mode)
|
|
303
|
+
- Knative: Knative/ACK Knative
|
|
250
304
|
|
|
251
305
|
Use 'agentscope deploy <platform> --help' for platform-specific options.
|
|
252
306
|
"""
|
|
@@ -701,6 +755,426 @@ def agentrun(
|
|
|
701
755
|
sys.exit(1)
|
|
702
756
|
|
|
703
757
|
|
|
758
|
+
@deploy.command()
|
|
759
|
+
@click.argument("source", required=False, default=None)
|
|
760
|
+
@click.option(
|
|
761
|
+
"--config",
|
|
762
|
+
"-c",
|
|
763
|
+
type=click.Path(exists=True),
|
|
764
|
+
help="Path to deployment config file (.yaml or .yml). "
|
|
765
|
+
"See pai_deploy_config.yaml for example.",
|
|
766
|
+
)
|
|
767
|
+
@click.option("--name", help="Service name (required)", default=None)
|
|
768
|
+
@click.option(
|
|
769
|
+
"--workspace-id",
|
|
770
|
+
help="PAI workspace ID (or PAI_WORKSPACE_ID env var)",
|
|
771
|
+
default=None,
|
|
772
|
+
)
|
|
773
|
+
@click.option(
|
|
774
|
+
"--region",
|
|
775
|
+
help="Region ID (e.g., cn-hangzhou)",
|
|
776
|
+
default=None,
|
|
777
|
+
)
|
|
778
|
+
@click.option(
|
|
779
|
+
"--entrypoint",
|
|
780
|
+
help="Entrypoint file name (default: app.py, agent.py, or main.py)",
|
|
781
|
+
default=None,
|
|
782
|
+
)
|
|
783
|
+
@click.option(
|
|
784
|
+
"--oss-path",
|
|
785
|
+
help="OSS work directory (e.g., oss://bucket/path/)",
|
|
786
|
+
default=None,
|
|
787
|
+
)
|
|
788
|
+
@click.option(
|
|
789
|
+
"--instance-type",
|
|
790
|
+
help="Instance type for public resource (e.g., ecs.c6.large)",
|
|
791
|
+
default=None,
|
|
792
|
+
)
|
|
793
|
+
@click.option(
|
|
794
|
+
"--instance-count",
|
|
795
|
+
help="Number of instances",
|
|
796
|
+
type=int,
|
|
797
|
+
default=None,
|
|
798
|
+
)
|
|
799
|
+
@click.option(
|
|
800
|
+
"--resource-id",
|
|
801
|
+
help="EAS resource group ID (for resource mode)",
|
|
802
|
+
default=None,
|
|
803
|
+
)
|
|
804
|
+
@click.option(
|
|
805
|
+
"--quota-id",
|
|
806
|
+
help="PAI quota ID (for quota mode)",
|
|
807
|
+
default=None,
|
|
808
|
+
)
|
|
809
|
+
@click.option("--cpu", help="CPU cores", type=int, default=None)
|
|
810
|
+
@click.option("--memory", help="Memory in MB", type=int, default=None)
|
|
811
|
+
@click.option("--service-group", help="Service group name", default=None)
|
|
812
|
+
@click.option(
|
|
813
|
+
"--resource-type",
|
|
814
|
+
type=click.Choice(["public", "resource", "quota"]),
|
|
815
|
+
help="Resource type: public (instance), resource (EAS group), quota",
|
|
816
|
+
default=None,
|
|
817
|
+
)
|
|
818
|
+
@click.option(
|
|
819
|
+
"--vpc-id",
|
|
820
|
+
help="VPC ID for network configuration",
|
|
821
|
+
default=None,
|
|
822
|
+
)
|
|
823
|
+
@click.option(
|
|
824
|
+
"--vswitch-id",
|
|
825
|
+
help="VSwitch ID for network configuration",
|
|
826
|
+
default=None,
|
|
827
|
+
)
|
|
828
|
+
@click.option(
|
|
829
|
+
"--security-group-id",
|
|
830
|
+
help="Security group ID for network configuration",
|
|
831
|
+
default=None,
|
|
832
|
+
)
|
|
833
|
+
@click.option("--ram-role-arn", help="RAM role ARN", default=None)
|
|
834
|
+
@click.option(
|
|
835
|
+
"--enable-trace/--no-trace",
|
|
836
|
+
help="Enable/disable tracing",
|
|
837
|
+
default=None,
|
|
838
|
+
)
|
|
839
|
+
@click.option(
|
|
840
|
+
"--wait/--no-wait",
|
|
841
|
+
help="Wait for deployment to complete",
|
|
842
|
+
default=None,
|
|
843
|
+
)
|
|
844
|
+
@click.option(
|
|
845
|
+
"--timeout",
|
|
846
|
+
help="Deployment timeout in seconds",
|
|
847
|
+
type=int,
|
|
848
|
+
default=None,
|
|
849
|
+
)
|
|
850
|
+
@click.option(
|
|
851
|
+
"--auto-approve/--no-auto-approve",
|
|
852
|
+
help="Auto approve the deployment",
|
|
853
|
+
default=None,
|
|
854
|
+
)
|
|
855
|
+
@click.option(
|
|
856
|
+
"--env",
|
|
857
|
+
"-E",
|
|
858
|
+
multiple=True,
|
|
859
|
+
help="Environment variable in KEY=VALUE format (can be repeated)",
|
|
860
|
+
)
|
|
861
|
+
@click.option(
|
|
862
|
+
"--env-file",
|
|
863
|
+
type=click.Path(exists=True),
|
|
864
|
+
help="Path to .env file with environment variables",
|
|
865
|
+
)
|
|
866
|
+
@click.option(
|
|
867
|
+
"--tag",
|
|
868
|
+
"-T",
|
|
869
|
+
multiple=True,
|
|
870
|
+
help="Tag in KEY=VALUE format (can be repeated)",
|
|
871
|
+
)
|
|
872
|
+
def pai(
|
|
873
|
+
source: str,
|
|
874
|
+
config: str,
|
|
875
|
+
name: str,
|
|
876
|
+
workspace_id: str,
|
|
877
|
+
region: str,
|
|
878
|
+
entrypoint: str,
|
|
879
|
+
oss_path: str,
|
|
880
|
+
instance_type: str,
|
|
881
|
+
instance_count: int,
|
|
882
|
+
resource_id: str,
|
|
883
|
+
quota_id: str,
|
|
884
|
+
cpu: int,
|
|
885
|
+
memory: int,
|
|
886
|
+
service_group: str,
|
|
887
|
+
resource_type: str,
|
|
888
|
+
vpc_id: str,
|
|
889
|
+
vswitch_id: str,
|
|
890
|
+
security_group_id: str,
|
|
891
|
+
ram_role_arn: str,
|
|
892
|
+
enable_trace: bool,
|
|
893
|
+
wait: bool,
|
|
894
|
+
timeout: int,
|
|
895
|
+
auto_approve: bool,
|
|
896
|
+
env: tuple,
|
|
897
|
+
env_file: str,
|
|
898
|
+
tag: tuple,
|
|
899
|
+
):
|
|
900
|
+
"""
|
|
901
|
+
Deploy to Alibaba Cloud PAI (Platform for AI).
|
|
902
|
+
|
|
903
|
+
\b
|
|
904
|
+
Usage:
|
|
905
|
+
# Using config file (recommended)
|
|
906
|
+
agentscope deploy pai --config pai_deploy_config.yaml
|
|
907
|
+
|
|
908
|
+
# Using config file with CLI overrides
|
|
909
|
+
agentscope deploy pai --config pai_deploy_config.yaml --name new-name
|
|
910
|
+
|
|
911
|
+
# Using CLI only
|
|
912
|
+
agentscope deploy pai ./my_agent --name my-service --workspace-id 12345
|
|
913
|
+
|
|
914
|
+
\b
|
|
915
|
+
Required:
|
|
916
|
+
- Service name (--name or spec.name in config)
|
|
917
|
+
- Source directory (SOURCE argument or spec.code.source_dir in config)
|
|
918
|
+
- Workspace ID (--workspace-id, context.workspace_id, or env)
|
|
919
|
+
|
|
920
|
+
\b
|
|
921
|
+
Environment variables:
|
|
922
|
+
- ALIBABA_CLOUD_ACCESS_KEY_ID
|
|
923
|
+
- ALIBABA_CLOUD_ACCESS_KEY_SECRET
|
|
924
|
+
- PAI_WORKSPACE_ID (optional if --workspace-id provided)
|
|
925
|
+
- REGION_ID or ALIBABA_CLOUD_REGION_ID (optional)
|
|
926
|
+
"""
|
|
927
|
+
if not PAI_AVAILABLE:
|
|
928
|
+
echo_error("PAI deployer is not available")
|
|
929
|
+
echo_info(
|
|
930
|
+
"Please install required dependencies via "
|
|
931
|
+
"pip install 'agentscope-runtime[ext]'",
|
|
932
|
+
)
|
|
933
|
+
sys.exit(1)
|
|
934
|
+
|
|
935
|
+
try:
|
|
936
|
+
# Step 1: Build configuration from config file or defaults
|
|
937
|
+
if config:
|
|
938
|
+
echo_info(f"Loading configuration from {config}...")
|
|
939
|
+
deploy_config = PAIDeployConfig.from_yaml(config)
|
|
940
|
+
else:
|
|
941
|
+
deploy_config = PAIDeployConfig()
|
|
942
|
+
|
|
943
|
+
# Step 2: Parse CLI environment variables and tags
|
|
944
|
+
cli_env = _parse_environment(env, env_file)
|
|
945
|
+
cli_tags = _parse_tags(tag)
|
|
946
|
+
|
|
947
|
+
# Step 3: Resolve source path
|
|
948
|
+
resolved_source = None
|
|
949
|
+
if source:
|
|
950
|
+
abs_source, source_type = _validate_source(source)
|
|
951
|
+
if source_type == "file":
|
|
952
|
+
# For single file: use parent directory as project_dir
|
|
953
|
+
resolved_source = os.path.dirname(abs_source)
|
|
954
|
+
if not entrypoint:
|
|
955
|
+
entrypoint = os.path.basename(abs_source)
|
|
956
|
+
else:
|
|
957
|
+
resolved_source = abs_source
|
|
958
|
+
|
|
959
|
+
# Step 4: Merge CLI parameters (CLI takes precedence)
|
|
960
|
+
deploy_config = deploy_config.merge_cli(
|
|
961
|
+
source=resolved_source,
|
|
962
|
+
name=name,
|
|
963
|
+
entrypoint=entrypoint,
|
|
964
|
+
workspace_id=workspace_id,
|
|
965
|
+
region=region,
|
|
966
|
+
oss_path=oss_path,
|
|
967
|
+
instance_type=instance_type,
|
|
968
|
+
instance_count=instance_count,
|
|
969
|
+
resource_id=resource_id,
|
|
970
|
+
quota_id=quota_id,
|
|
971
|
+
cpu=cpu,
|
|
972
|
+
memory=memory,
|
|
973
|
+
service_group=service_group,
|
|
974
|
+
resource_type=resource_type,
|
|
975
|
+
vpc_id=vpc_id,
|
|
976
|
+
vswitch_id=vswitch_id,
|
|
977
|
+
security_group_id=security_group_id,
|
|
978
|
+
ram_role_arn=ram_role_arn,
|
|
979
|
+
enable_trace=enable_trace,
|
|
980
|
+
wait=wait,
|
|
981
|
+
timeout=timeout,
|
|
982
|
+
auto_approve=auto_approve,
|
|
983
|
+
environment=cli_env if cli_env else None,
|
|
984
|
+
tags=cli_tags if cli_tags else None,
|
|
985
|
+
)
|
|
986
|
+
|
|
987
|
+
# Step 5: Resolve source_dir to absolute path
|
|
988
|
+
if deploy_config.spec.code.source_dir:
|
|
989
|
+
source_dir = deploy_config.spec.code.source_dir
|
|
990
|
+
if not os.path.isabs(source_dir):
|
|
991
|
+
# If config file provided, resolve relative to config file dir
|
|
992
|
+
if config:
|
|
993
|
+
base_dir = os.path.dirname(os.path.abspath(config))
|
|
994
|
+
source_dir = os.path.join(base_dir, source_dir)
|
|
995
|
+
else:
|
|
996
|
+
source_dir = os.path.abspath(source_dir)
|
|
997
|
+
# Update with resolved path
|
|
998
|
+
deploy_config.spec.code.source_dir = source_dir
|
|
999
|
+
|
|
1000
|
+
# Step 6: Find entrypoint if not specified
|
|
1001
|
+
if (
|
|
1002
|
+
deploy_config.spec.code.source_dir
|
|
1003
|
+
and not deploy_config.spec.code.entrypoint
|
|
1004
|
+
):
|
|
1005
|
+
entry_script = _find_entrypoint(
|
|
1006
|
+
deploy_config.spec.code.source_dir,
|
|
1007
|
+
)
|
|
1008
|
+
deploy_config.spec.code.entrypoint = entry_script
|
|
1009
|
+
|
|
1010
|
+
# Step 7: Validate configuration
|
|
1011
|
+
try:
|
|
1012
|
+
deploy_config.validate_for_deploy()
|
|
1013
|
+
except ValueError as e:
|
|
1014
|
+
echo_error(str(e))
|
|
1015
|
+
sys.exit(1)
|
|
1016
|
+
|
|
1017
|
+
# Step 8: Create deployer
|
|
1018
|
+
# Use resolved OSS work dir (spec.storage -> context.storage fallback)
|
|
1019
|
+
resolved_oss_path = deploy_config.resolve_oss_work_dir()
|
|
1020
|
+
deployer = PAIDeployManager(
|
|
1021
|
+
workspace_id=deploy_config.context.workspace_id,
|
|
1022
|
+
region_id=deploy_config.context.region,
|
|
1023
|
+
oss_path=resolved_oss_path,
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
# Validate workspace_id (may come from env var in deployer)
|
|
1027
|
+
if not deployer.workspace_id:
|
|
1028
|
+
echo_error(
|
|
1029
|
+
"PAI workspace ID is required. Set PAI_WORKSPACE_ID "
|
|
1030
|
+
"environment variable, use --workspace-id, or set "
|
|
1031
|
+
"context.workspace_id in config file.",
|
|
1032
|
+
)
|
|
1033
|
+
sys.exit(1)
|
|
1034
|
+
|
|
1035
|
+
# Step 9: Display deployment info
|
|
1036
|
+
service_name = deploy_config.spec.name
|
|
1037
|
+
resource_type = deploy_config.resolve_resource_type()
|
|
1038
|
+
|
|
1039
|
+
echo_info(f"Service Name: {service_name}")
|
|
1040
|
+
echo_info(f"Workspace ID: {deployer.workspace_id}")
|
|
1041
|
+
echo_info(f"Region: {deployer.region_id}")
|
|
1042
|
+
echo_info(f"Resource Type: {resource_type}")
|
|
1043
|
+
echo_info(f"Source: {deploy_config.spec.code.source_dir}")
|
|
1044
|
+
if deploy_config.spec.code.entrypoint:
|
|
1045
|
+
echo_info(f"Entrypoint: {deploy_config.spec.code.entrypoint}")
|
|
1046
|
+
if deployer.oss_path:
|
|
1047
|
+
echo_info(f"OSS Path: {deployer.oss_path}")
|
|
1048
|
+
if deploy_config.spec.tags:
|
|
1049
|
+
echo_info(f"Tags: {deploy_config.spec.tags}")
|
|
1050
|
+
|
|
1051
|
+
# Step 10: Deploy
|
|
1052
|
+
echo_info(f"Deploying to PAI as service '{service_name}'...")
|
|
1053
|
+
|
|
1054
|
+
deploy_kwargs = deploy_config.to_deployer_kwargs()
|
|
1055
|
+
# Add deploy_method to indicate this is a CLI deployment
|
|
1056
|
+
deploy_kwargs["deploy_method"] = "cli"
|
|
1057
|
+
result = asyncio.run(deployer.deploy(**deploy_kwargs))
|
|
1058
|
+
|
|
1059
|
+
# Step 11: Display results
|
|
1060
|
+
deploy_id = result.get("deploy_id")
|
|
1061
|
+
flow_id = result.get("flow_id")
|
|
1062
|
+
snapshot_id = result.get("snapshot_id")
|
|
1063
|
+
console_url = result.get("url")
|
|
1064
|
+
status = result.get("status")
|
|
1065
|
+
|
|
1066
|
+
echo_success("Deployment created!")
|
|
1067
|
+
echo_info(f"Deployment ID: {deploy_id}")
|
|
1068
|
+
echo_info(f"Project ID: {flow_id}")
|
|
1069
|
+
echo_info(f"Snapshot ID: {snapshot_id}")
|
|
1070
|
+
echo_info(f"Service Name: {service_name}")
|
|
1071
|
+
echo_info(f"Status: {status}")
|
|
1072
|
+
echo_info(f"Deployment Console URL: {console_url}")
|
|
1073
|
+
|
|
1074
|
+
# Step 12: Handle approval flow for auto_approve=False
|
|
1075
|
+
if not deploy_config.auto_approve:
|
|
1076
|
+
# Interactive approval flow
|
|
1077
|
+
echo_info("\n" + "=" * 60)
|
|
1078
|
+
echo_warning(
|
|
1079
|
+
"Deployment created but waiting for approval.",
|
|
1080
|
+
)
|
|
1081
|
+
echo_info(
|
|
1082
|
+
f"View deployment details at:\n {console_url}",
|
|
1083
|
+
)
|
|
1084
|
+
echo_info("=" * 60)
|
|
1085
|
+
|
|
1086
|
+
# Check if we're in an interactive terminal
|
|
1087
|
+
if sys.stdin.isatty():
|
|
1088
|
+
echo_info("\nWhat would you like to do?")
|
|
1089
|
+
echo_info(" [A]pprove - Approve and start deployment")
|
|
1090
|
+
echo_info(" [C]ancel - Cancel this deployment")
|
|
1091
|
+
echo_info(" [S]kip - Skip (approve later in console)")
|
|
1092
|
+
|
|
1093
|
+
choice = click.prompt(
|
|
1094
|
+
"\nYour choice(case insensitive)",
|
|
1095
|
+
type=click.Choice(
|
|
1096
|
+
["A", "C", "S"],
|
|
1097
|
+
case_sensitive=False,
|
|
1098
|
+
),
|
|
1099
|
+
default="S",
|
|
1100
|
+
)
|
|
1101
|
+
choice = choice.upper()
|
|
1102
|
+
|
|
1103
|
+
if choice == "A":
|
|
1104
|
+
echo_info("\nApproving deployment...")
|
|
1105
|
+
try:
|
|
1106
|
+
# Wait for deployment to reach approval stage
|
|
1107
|
+
asyncio.run(
|
|
1108
|
+
deployer.wait_for_approval_stage(deploy_id),
|
|
1109
|
+
)
|
|
1110
|
+
# Approve the deployment
|
|
1111
|
+
echo_info("Deployment approved by CLI.")
|
|
1112
|
+
asyncio.run(
|
|
1113
|
+
deployer.approve_deployment(
|
|
1114
|
+
deploy_id,
|
|
1115
|
+
wait=deploy_config.wait,
|
|
1116
|
+
timeout=deploy_config.timeout,
|
|
1117
|
+
),
|
|
1118
|
+
)
|
|
1119
|
+
echo_success("Deployment completed!")
|
|
1120
|
+
|
|
1121
|
+
# Get updated service info
|
|
1122
|
+
if deploy_config.wait:
|
|
1123
|
+
service = asyncio.run(
|
|
1124
|
+
deployer.get_service(service_name),
|
|
1125
|
+
)
|
|
1126
|
+
if service and service.internet_endpoint:
|
|
1127
|
+
echo_info(
|
|
1128
|
+
f"Service Endpoint: "
|
|
1129
|
+
f"{service.internet_endpoint}",
|
|
1130
|
+
)
|
|
1131
|
+
echo_info(
|
|
1132
|
+
f"\nDeployment is running. Use "
|
|
1133
|
+
f"'agentscope stop {deploy_id}' to stop it.",
|
|
1134
|
+
)
|
|
1135
|
+
except Exception as e:
|
|
1136
|
+
echo_error(f"Failed to approve deployment: {e}")
|
|
1137
|
+
sys.exit(1)
|
|
1138
|
+
|
|
1139
|
+
elif choice == "C":
|
|
1140
|
+
echo_info("\nCancelling deployment...")
|
|
1141
|
+
try:
|
|
1142
|
+
asyncio.run(
|
|
1143
|
+
deployer.wait_for_approval_stage(deploy_id),
|
|
1144
|
+
)
|
|
1145
|
+
asyncio.run(deployer.cancel_deployment(deploy_id))
|
|
1146
|
+
echo_warning("Deployment cancelled.")
|
|
1147
|
+
except Exception as e:
|
|
1148
|
+
echo_error(f"Failed to cancel deployment: {e}")
|
|
1149
|
+
sys.exit(1)
|
|
1150
|
+
|
|
1151
|
+
else: # choice == "S"
|
|
1152
|
+
echo_info(
|
|
1153
|
+
"\nSkipped. Please approve or cancel the deployment "
|
|
1154
|
+
"in the PAI console.",
|
|
1155
|
+
)
|
|
1156
|
+
else:
|
|
1157
|
+
# Non-interactive mode
|
|
1158
|
+
echo_warning(
|
|
1159
|
+
"\nNon-interactive mode: Please approve or cancel the "
|
|
1160
|
+
"deployment in the PAI console.",
|
|
1161
|
+
)
|
|
1162
|
+
|
|
1163
|
+
elif deploy_config.wait:
|
|
1164
|
+
echo_success("Deployment completed successfully!")
|
|
1165
|
+
echo_info(
|
|
1166
|
+
f"\nDeployment is running. Use 'agentscope stop "
|
|
1167
|
+
f"{deploy_id}' to stop it.",
|
|
1168
|
+
)
|
|
1169
|
+
|
|
1170
|
+
except Exception as e:
|
|
1171
|
+
echo_error(f"Deployment failed: {e}")
|
|
1172
|
+
import traceback
|
|
1173
|
+
|
|
1174
|
+
echo_error(traceback.format_exc())
|
|
1175
|
+
sys.exit(1)
|
|
1176
|
+
|
|
1177
|
+
|
|
704
1178
|
@deploy.command()
|
|
705
1179
|
@click.argument("source", required=True)
|
|
706
1180
|
@click.option("--name", help="Deployment name", default=None)
|
|
@@ -1070,5 +1544,366 @@ def k8s(
|
|
|
1070
1544
|
sys.exit(1)
|
|
1071
1545
|
|
|
1072
1546
|
|
|
1547
|
+
@deploy.command()
|
|
1548
|
+
@click.argument("source", required=True)
|
|
1549
|
+
@click.option("--name", help="Deployment name", default=None)
|
|
1550
|
+
@click.option(
|
|
1551
|
+
"--namespace",
|
|
1552
|
+
help="Kubernetes namespace",
|
|
1553
|
+
default="agentscope-runtime",
|
|
1554
|
+
)
|
|
1555
|
+
@click.option(
|
|
1556
|
+
"--kube-config-path",
|
|
1557
|
+
"-c",
|
|
1558
|
+
type=click.Path(exists=True),
|
|
1559
|
+
help="Path to knative service config file (.json, .yaml, or .yml)",
|
|
1560
|
+
)
|
|
1561
|
+
@click.option(
|
|
1562
|
+
"--port",
|
|
1563
|
+
help="Container port",
|
|
1564
|
+
type=int,
|
|
1565
|
+
default=8080,
|
|
1566
|
+
)
|
|
1567
|
+
@click.option(
|
|
1568
|
+
"--image-name",
|
|
1569
|
+
help="Docker image name",
|
|
1570
|
+
default="agent_app",
|
|
1571
|
+
)
|
|
1572
|
+
@click.option(
|
|
1573
|
+
"--image-tag",
|
|
1574
|
+
help="Docker image tag",
|
|
1575
|
+
default="linux-amd64",
|
|
1576
|
+
)
|
|
1577
|
+
@click.option(
|
|
1578
|
+
"--registry-url",
|
|
1579
|
+
help="Remote registry url",
|
|
1580
|
+
default="localhost",
|
|
1581
|
+
)
|
|
1582
|
+
@click.option(
|
|
1583
|
+
"--registry-namespace",
|
|
1584
|
+
help="Remote registry namespace",
|
|
1585
|
+
default="agentscope-runtime",
|
|
1586
|
+
)
|
|
1587
|
+
@click.option(
|
|
1588
|
+
"--push",
|
|
1589
|
+
is_flag=True,
|
|
1590
|
+
help="Push image to registry",
|
|
1591
|
+
)
|
|
1592
|
+
@click.option(
|
|
1593
|
+
"--entrypoint",
|
|
1594
|
+
"-e",
|
|
1595
|
+
help="Entrypoint file name for directory sources (e.g., 'app.py', "
|
|
1596
|
+
"'main.py')",
|
|
1597
|
+
default=None,
|
|
1598
|
+
)
|
|
1599
|
+
@click.option(
|
|
1600
|
+
"--env",
|
|
1601
|
+
"-E",
|
|
1602
|
+
multiple=True,
|
|
1603
|
+
help="Environment variable in KEY=VALUE format (can be repeated)",
|
|
1604
|
+
)
|
|
1605
|
+
@click.option(
|
|
1606
|
+
"--env-file",
|
|
1607
|
+
type=click.Path(exists=True),
|
|
1608
|
+
help="Path to .env file with environment variables",
|
|
1609
|
+
)
|
|
1610
|
+
@click.option(
|
|
1611
|
+
"--config",
|
|
1612
|
+
"-c",
|
|
1613
|
+
type=click.Path(exists=True),
|
|
1614
|
+
help="Path to knative service config file (.json, .yaml, or .yml)",
|
|
1615
|
+
)
|
|
1616
|
+
@click.option(
|
|
1617
|
+
"--base-image",
|
|
1618
|
+
help="Base Docker image",
|
|
1619
|
+
default="python:3.10-slim-bookworm",
|
|
1620
|
+
)
|
|
1621
|
+
@click.option(
|
|
1622
|
+
"--requirements",
|
|
1623
|
+
help="Python requirements (comma-separated or file path)",
|
|
1624
|
+
default=None,
|
|
1625
|
+
)
|
|
1626
|
+
@click.option(
|
|
1627
|
+
"--cpu-request",
|
|
1628
|
+
help="CPU resource request (e.g., '200m', '1')",
|
|
1629
|
+
default="200m",
|
|
1630
|
+
)
|
|
1631
|
+
@click.option(
|
|
1632
|
+
"--cpu-limit",
|
|
1633
|
+
help="CPU resource limit (e.g., '1000m', '2')",
|
|
1634
|
+
default="1000m",
|
|
1635
|
+
)
|
|
1636
|
+
@click.option(
|
|
1637
|
+
"--memory-request",
|
|
1638
|
+
help="Memory resource request (e.g., '512Mi', '1Gi')",
|
|
1639
|
+
default="512Mi",
|
|
1640
|
+
)
|
|
1641
|
+
@click.option(
|
|
1642
|
+
"--memory-limit",
|
|
1643
|
+
help="Memory resource limit (e.g., '2Gi', '4Gi')",
|
|
1644
|
+
default="2Gi",
|
|
1645
|
+
)
|
|
1646
|
+
@click.option(
|
|
1647
|
+
"--image-pull-policy",
|
|
1648
|
+
help="Image pull policy",
|
|
1649
|
+
type=click.Choice(["Always", "IfNotPresent", "Never"]),
|
|
1650
|
+
default="IfNotPresent",
|
|
1651
|
+
)
|
|
1652
|
+
@click.option(
|
|
1653
|
+
"--deploy-timeout",
|
|
1654
|
+
help="Deployment timeout in seconds",
|
|
1655
|
+
type=int,
|
|
1656
|
+
default=300,
|
|
1657
|
+
)
|
|
1658
|
+
@click.option(
|
|
1659
|
+
"--health-check",
|
|
1660
|
+
is_flag=True,
|
|
1661
|
+
help="Enable/disable health check",
|
|
1662
|
+
)
|
|
1663
|
+
@click.option(
|
|
1664
|
+
"--platform",
|
|
1665
|
+
help="Target platform (e.g., 'linux/amd64', 'linux/arm64')",
|
|
1666
|
+
default="linux/amd64",
|
|
1667
|
+
)
|
|
1668
|
+
@click.option(
|
|
1669
|
+
"--pypi-mirror",
|
|
1670
|
+
help="PyPI mirror URL for pip package installation (e.g., "
|
|
1671
|
+
"https://pypi.tuna.tsinghua.edu.cn/simple). If not specified, "
|
|
1672
|
+
"uses pip default.",
|
|
1673
|
+
default=None,
|
|
1674
|
+
)
|
|
1675
|
+
def knative(
|
|
1676
|
+
source: str,
|
|
1677
|
+
name: str,
|
|
1678
|
+
namespace: str,
|
|
1679
|
+
kube_config_path: str,
|
|
1680
|
+
port: int,
|
|
1681
|
+
image_name: str,
|
|
1682
|
+
image_tag: str,
|
|
1683
|
+
registry_url: str,
|
|
1684
|
+
registry_namespace: str,
|
|
1685
|
+
push: bool,
|
|
1686
|
+
entrypoint: str,
|
|
1687
|
+
env: tuple,
|
|
1688
|
+
env_file: str,
|
|
1689
|
+
config: str,
|
|
1690
|
+
base_image: str,
|
|
1691
|
+
requirements: str,
|
|
1692
|
+
cpu_request: str,
|
|
1693
|
+
cpu_limit: str,
|
|
1694
|
+
memory_request: str,
|
|
1695
|
+
memory_limit: str,
|
|
1696
|
+
image_pull_policy: str,
|
|
1697
|
+
deploy_timeout: int,
|
|
1698
|
+
health_check: bool,
|
|
1699
|
+
platform: str,
|
|
1700
|
+
pypi_mirror: str,
|
|
1701
|
+
):
|
|
1702
|
+
"""
|
|
1703
|
+
Deploy to Knative/ACK Knative.
|
|
1704
|
+
|
|
1705
|
+
SOURCE can be a Python file or project directory containing an agent.
|
|
1706
|
+
|
|
1707
|
+
This will build a Docker image and deploy it to your Knative cluster.
|
|
1708
|
+
"""
|
|
1709
|
+
if not KNATIVE_AVAILABLE:
|
|
1710
|
+
echo_error("Knative deployer is not available")
|
|
1711
|
+
echo_info("Please ensure Knative are available")
|
|
1712
|
+
sys.exit(1)
|
|
1713
|
+
|
|
1714
|
+
try:
|
|
1715
|
+
echo_info(f"Preparing deployment from {source}...")
|
|
1716
|
+
|
|
1717
|
+
# Load config file if provided
|
|
1718
|
+
config_dict = {}
|
|
1719
|
+
if config:
|
|
1720
|
+
echo_info(f"Loading configuration from {config}...")
|
|
1721
|
+
config_dict = _load_config_file(config)
|
|
1722
|
+
|
|
1723
|
+
# make sure not to push if use local registry_url
|
|
1724
|
+
if registry_url == "localhost":
|
|
1725
|
+
push = False
|
|
1726
|
+
|
|
1727
|
+
# Merge CLI parameters with config (CLI takes precedence)
|
|
1728
|
+
cli_params = {
|
|
1729
|
+
"name": name,
|
|
1730
|
+
"namespace": namespace,
|
|
1731
|
+
"port": port,
|
|
1732
|
+
"image_name": image_name,
|
|
1733
|
+
"image_tag": image_tag,
|
|
1734
|
+
"registry_url": registry_url,
|
|
1735
|
+
"registry_namespace": registry_namespace,
|
|
1736
|
+
"push_to_registry": push if push else None,
|
|
1737
|
+
"entrypoint": entrypoint,
|
|
1738
|
+
"base_image": base_image,
|
|
1739
|
+
"requirements": requirements,
|
|
1740
|
+
"image_pull_policy": image_pull_policy,
|
|
1741
|
+
"deploy_timeout": deploy_timeout,
|
|
1742
|
+
"health_check": health_check,
|
|
1743
|
+
"platform": platform,
|
|
1744
|
+
"pypi_mirror": pypi_mirror,
|
|
1745
|
+
}
|
|
1746
|
+
merged_config = _merge_config(config_dict, cli_params)
|
|
1747
|
+
|
|
1748
|
+
# Extract parameters with defaults
|
|
1749
|
+
namespace = merged_config.get("namespace", "agentscope-runtime")
|
|
1750
|
+
port = merged_config.get("port", 8080)
|
|
1751
|
+
image_name = merged_config.get("image_name", "agent_llm")
|
|
1752
|
+
image_tag = merged_config.get("image_tag", "latest")
|
|
1753
|
+
registry_url = merged_config.get("registry_url", "localhost")
|
|
1754
|
+
registry_namespace = merged_config.get(
|
|
1755
|
+
"registry_namespace",
|
|
1756
|
+
"agentscope-runtime",
|
|
1757
|
+
)
|
|
1758
|
+
push_to_registry = merged_config.get("push_to_registry", False)
|
|
1759
|
+
entrypoint = merged_config.get("entrypoint")
|
|
1760
|
+
base_image = merged_config.get("base_image")
|
|
1761
|
+
deploy_timeout = merged_config.get("deploy_timeout", 300)
|
|
1762
|
+
health_check = merged_config.get("health_check", True)
|
|
1763
|
+
platform = merged_config.get("platform")
|
|
1764
|
+
pypi_mirror = merged_config.get("pypi_mirror")
|
|
1765
|
+
|
|
1766
|
+
# Handle requirements (can be comma-separated string, list, or file
|
|
1767
|
+
# path)
|
|
1768
|
+
requirements = merged_config.get("requirements")
|
|
1769
|
+
if requirements:
|
|
1770
|
+
if isinstance(requirements, str):
|
|
1771
|
+
# Check if it's a file path
|
|
1772
|
+
if os.path.isfile(requirements):
|
|
1773
|
+
with open(requirements, "r", encoding="utf-8") as f:
|
|
1774
|
+
requirements = [
|
|
1775
|
+
line.strip()
|
|
1776
|
+
for line in f
|
|
1777
|
+
if line.strip() and not line.startswith("#")
|
|
1778
|
+
]
|
|
1779
|
+
else:
|
|
1780
|
+
# Treat as comma-separated string
|
|
1781
|
+
requirements = [r.strip() for r in requirements.split(",")]
|
|
1782
|
+
|
|
1783
|
+
# Handle extra_packages
|
|
1784
|
+
extra_packages = merged_config.get("extra_packages", [])
|
|
1785
|
+
|
|
1786
|
+
# Handle image_pull_policy
|
|
1787
|
+
image_pull_policy = merged_config.get("image_pull_policy")
|
|
1788
|
+
|
|
1789
|
+
# Build runtime_config from resource parameters
|
|
1790
|
+
runtime_config = merged_config.get("runtime_config", {})
|
|
1791
|
+
if not runtime_config.get("resources"):
|
|
1792
|
+
resources = {}
|
|
1793
|
+
if cpu_request or memory_request:
|
|
1794
|
+
resources["requests"] = {}
|
|
1795
|
+
if cpu_request:
|
|
1796
|
+
resources["requests"]["cpu"] = cpu_request
|
|
1797
|
+
if memory_request:
|
|
1798
|
+
resources["requests"]["memory"] = memory_request
|
|
1799
|
+
if cpu_limit or memory_limit:
|
|
1800
|
+
resources["limits"] = {}
|
|
1801
|
+
if cpu_limit:
|
|
1802
|
+
resources["limits"]["cpu"] = cpu_limit
|
|
1803
|
+
if memory_limit:
|
|
1804
|
+
resources["limits"]["memory"] = memory_limit
|
|
1805
|
+
if resources:
|
|
1806
|
+
runtime_config["resources"] = resources
|
|
1807
|
+
|
|
1808
|
+
if image_pull_policy and "image_pull_policy" not in runtime_config:
|
|
1809
|
+
runtime_config["image_pull_policy"] = image_pull_policy
|
|
1810
|
+
|
|
1811
|
+
# Validate source
|
|
1812
|
+
abs_source, source_type = _validate_source(source)
|
|
1813
|
+
|
|
1814
|
+
# Parse environment variables (from config, env_file, and CLI)
|
|
1815
|
+
environment = merged_config.get("environment", {}).copy()
|
|
1816
|
+
cli_env = _parse_environment(env, env_file)
|
|
1817
|
+
environment.update(cli_env) # CLI env overrides config env
|
|
1818
|
+
|
|
1819
|
+
if environment:
|
|
1820
|
+
echo_info(f"Using {len(environment)} environment variable(s)")
|
|
1821
|
+
|
|
1822
|
+
# Create deployer
|
|
1823
|
+
k8s_config = K8sConfig(
|
|
1824
|
+
k8s_namespace=namespace,
|
|
1825
|
+
kubeconfig_path=kube_config_path,
|
|
1826
|
+
)
|
|
1827
|
+
registry_config = RegistryConfig(
|
|
1828
|
+
registry_url=registry_url,
|
|
1829
|
+
namespace=registry_namespace,
|
|
1830
|
+
)
|
|
1831
|
+
deployer = KnativeDeployManager(
|
|
1832
|
+
kube_config=k8s_config,
|
|
1833
|
+
registry_config=registry_config,
|
|
1834
|
+
)
|
|
1835
|
+
|
|
1836
|
+
# Prepare entrypoint specification
|
|
1837
|
+
if source_type == "directory":
|
|
1838
|
+
# For directory: find entrypoint and create path
|
|
1839
|
+
project_dir = abs_source
|
|
1840
|
+
entry_script = _find_entrypoint(project_dir, entrypoint)
|
|
1841
|
+
entrypoint_spec = os.path.join(project_dir, entry_script)
|
|
1842
|
+
|
|
1843
|
+
echo_info(f"Using project directory: {project_dir}")
|
|
1844
|
+
echo_info(f"Entry script: {entry_script}")
|
|
1845
|
+
else:
|
|
1846
|
+
# For single file: use file path directly
|
|
1847
|
+
entrypoint_spec = abs_source
|
|
1848
|
+
|
|
1849
|
+
echo_info(f"Using file: {abs_source}")
|
|
1850
|
+
|
|
1851
|
+
# Deploy to Knative using entrypoint
|
|
1852
|
+
echo_info("Deploying to Knative...")
|
|
1853
|
+
|
|
1854
|
+
# Build deploy parameters
|
|
1855
|
+
deploy_params = {
|
|
1856
|
+
"entrypoint": entrypoint_spec,
|
|
1857
|
+
"port": port,
|
|
1858
|
+
"image_name": image_name,
|
|
1859
|
+
"image_tag": image_tag,
|
|
1860
|
+
"push_to_registry": push_to_registry,
|
|
1861
|
+
"environment": environment if environment else None,
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
# Add optional parameters if provided
|
|
1865
|
+
if base_image:
|
|
1866
|
+
deploy_params["base_image"] = base_image
|
|
1867
|
+
if requirements:
|
|
1868
|
+
deploy_params["requirements"] = requirements
|
|
1869
|
+
if extra_packages:
|
|
1870
|
+
deploy_params["extra_packages"] = extra_packages
|
|
1871
|
+
if runtime_config:
|
|
1872
|
+
deploy_params["runtime_config"] = runtime_config
|
|
1873
|
+
if deploy_timeout:
|
|
1874
|
+
deploy_params["deploy_timeout"] = deploy_timeout
|
|
1875
|
+
if health_check is not None:
|
|
1876
|
+
deploy_params["health_check"] = health_check
|
|
1877
|
+
if platform:
|
|
1878
|
+
deploy_params["platform"] = platform
|
|
1879
|
+
if pypi_mirror:
|
|
1880
|
+
deploy_params["pypi_mirror"] = pypi_mirror
|
|
1881
|
+
|
|
1882
|
+
# Add agent_source for state saving
|
|
1883
|
+
deploy_params["agent_source"] = abs_source
|
|
1884
|
+
deploy_params["labels"] = {
|
|
1885
|
+
"app": "agent-ksvc",
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
result = asyncio.run(deployer.deploy(**deploy_params))
|
|
1889
|
+
|
|
1890
|
+
deploy_id = result.get("deploy_id")
|
|
1891
|
+
url = result.get("url")
|
|
1892
|
+
resource_name = result.get("resource_name")
|
|
1893
|
+
|
|
1894
|
+
echo_success("Deployment successful!")
|
|
1895
|
+
echo_info(f"Deployment ID: {deploy_id}")
|
|
1896
|
+
echo_info(f"Resource Name: {resource_name}")
|
|
1897
|
+
echo_info(f"URL: {url}")
|
|
1898
|
+
echo_info(f"Namespace: {namespace}")
|
|
1899
|
+
|
|
1900
|
+
except Exception as e:
|
|
1901
|
+
echo_error(f"Deployment failed: {e}")
|
|
1902
|
+
import traceback
|
|
1903
|
+
|
|
1904
|
+
echo_error(traceback.format_exc())
|
|
1905
|
+
sys.exit(1)
|
|
1906
|
+
|
|
1907
|
+
|
|
1073
1908
|
if __name__ == "__main__":
|
|
1074
1909
|
deploy()
|