2020import subprocess
2121from typing import Final
2222from typing import Optional
23+ import warnings
2324
2425import click
2526from packaging .version import parse
2627
2728_IS_WINDOWS = os .name == 'nt'
2829_GCLOUD_CMD = 'gcloud.cmd' if _IS_WINDOWS else 'gcloud'
2930_LOCAL_STORAGE_FLAG_MIN_VERSION : Final [str ] = '1.21.0'
31+ _AGENT_ENGINE_REQUIREMENT : Final [str ] = (
32+ 'google-cloud-aiplatform[adk,agent_engines]'
33+ )
34+
35+
36+ def _ensure_agent_engine_dependency (requirements_txt_path : str ) -> None :
37+ """Ensures staged requirements include Agent Engine dependencies."""
38+ if not os .path .exists (requirements_txt_path ):
39+ raise FileNotFoundError (
40+ f'requirements.txt not found at: { requirements_txt_path } '
41+ )
42+
43+ requirements = ''
44+ with open (requirements_txt_path , 'r' , encoding = 'utf-8' ) as f :
45+ requirements = f .read ()
46+
47+ for line in requirements .splitlines ():
48+ stripped = line .strip ()
49+ if (
50+ stripped
51+ and not stripped .startswith ('#' )
52+ and stripped .startswith ('google-cloud-aiplatform' )
53+ ):
54+ return
55+
56+ with open (requirements_txt_path , 'a' , encoding = 'utf-8' ) as f :
57+ if requirements and not requirements .endswith ('\n ' ):
58+ f .write ('\n ' )
59+ f .write (_AGENT_ENGINE_REQUIREMENT + '\n ' )
60+
3061
3162_DOCKERFILE_TEMPLATE : Final [str ] = """
3263FROM python:3.11-slim
74105
75106if {is_config_agent}:
76107 from google.adk.agents import config_agent_utils
77- try:
78- # This path is for local loading.
79- root_agent = config_agent_utils.from_config("{agent_folder}/root_agent.yaml")
80- except FileNotFoundError:
81- # This path is used to support the file structure in Agent Engine.
82- root_agent = config_agent_utils.from_config("./{temp_folder}/{app_name}/root_agent.yaml")
108+ root_agent = config_agent_utils.from_config("{agent_folder}/root_agent.yaml")
83109else:
84110 from .agent import {adk_app_object}
85111
@@ -661,7 +687,7 @@ def to_agent_engine(
661687 agent_folder : str ,
662688 temp_folder : Optional [str ] = None ,
663689 adk_app : str ,
664- staging_bucket : str ,
690+ staging_bucket : Optional [ str ] = None ,
665691 trace_to_cloud : Optional [bool ] = None ,
666692 api_key : Optional [str ] = None ,
667693 adk_app_object : Optional [str ] = None ,
@@ -704,7 +730,8 @@ def to_agent_engine(
704730 files. It will be replaced with the generated files if it already exists.
705731 adk_app (str): The name of the file (without .py) containing the AdkApp
706732 instance.
707- staging_bucket (str): The GCS bucket for staging the deployment artifacts.
733+ staging_bucket (str): Deprecated. This argument is no longer required or
734+ used.
708735 trace_to_cloud (bool): Whether to enable Cloud Trace.
709736 api_key (str): Optional. The API key to use for Express Mode.
710737 If not provided, the API key from the GOOGLE_API_KEY environment variable
@@ -734,26 +761,41 @@ def to_agent_engine(
734761 app_name = os .path .basename (agent_folder )
735762 display_name = display_name or app_name
736763 parent_folder = os .path .dirname (agent_folder )
737- if parent_folder != os .getcwd ():
738- click .echo (f'Please deploy from the project dir: { parent_folder } ' )
739- return
740- tmp_app_name = app_name + '_tmp' + datetime .now ().strftime ('%Y%m%d_%H%M%S' )
741- temp_folder = temp_folder or tmp_app_name
742- agent_src_path = os .path .join (parent_folder , temp_folder )
743- click .echo (f'Staging all files in: { agent_src_path } ' )
744764 adk_app_object = adk_app_object or 'root_agent'
745765 if adk_app_object not in ['root_agent' , 'app' ]:
746766 click .echo (
747767 f'Invalid adk_app_object: { adk_app_object } . Please use "root_agent"'
748768 ' or "app".'
749769 )
750770 return
771+ if staging_bucket :
772+ warnings .warn (
773+ 'WARNING: `staging_bucket` is deprecated and will be removed in a'
774+ ' future release. Please drop it from the list of arguments.' ,
775+ DeprecationWarning ,
776+ stacklevel = 2 ,
777+ )
778+
779+ original_cwd = os .getcwd ()
780+ did_change_cwd = False
781+ if parent_folder != original_cwd :
782+ click .echo (
783+ 'Agent Engine deployment uses relative paths; temporarily switching '
784+ f'working directory to: { parent_folder } '
785+ )
786+ os .chdir (parent_folder )
787+ did_change_cwd = True
788+ tmp_app_name = app_name + '_tmp' + datetime .now ().strftime ('%Y%m%d_%H%M%S' )
789+ temp_folder = temp_folder or tmp_app_name
790+ agent_src_path = os .path .join (parent_folder , temp_folder )
791+ click .echo (f'Staging all files in: { agent_src_path } ' )
751792 # remove agent_src_path if it exists
752793 if os .path .exists (agent_src_path ):
753794 click .echo ('Removing existing files' )
754795 shutil .rmtree (agent_src_path )
755796
756797 try :
798+ click .echo (f'Staging all files in: { agent_src_path } ' )
757799 ignore_patterns = None
758800 ae_ignore_path = os .path .join (agent_folder , '.ae_ignore' )
759801 if os .path .exists (ae_ignore_path ):
@@ -762,15 +804,18 @@ def to_agent_engine(
762804 patterns = [pattern .strip () for pattern in f .readlines ()]
763805 ignore_patterns = shutil .ignore_patterns (* patterns )
764806 click .echo ('Copying agent source code...' )
765- shutil .copytree (agent_folder , agent_src_path , ignore = ignore_patterns )
807+ shutil .copytree (
808+ agent_folder ,
809+ agent_src_path ,
810+ ignore = ignore_patterns ,
811+ dirs_exist_ok = True ,
812+ )
766813 click .echo ('Copying agent source code complete.' )
767814
768815 project = _resolve_project (project )
769816
770817 click .echo ('Resolving files and dependencies...' )
771818 agent_config = {}
772- if staging_bucket :
773- agent_config ['staging_bucket' ] = staging_bucket
774819 if not agent_engine_config_file :
775820 # Attempt to read the agent engine config from .agent_engine_config.json in the dir (if any).
776821 agent_engine_config_file = os .path .join (
@@ -813,8 +858,9 @@ def to_agent_engine(
813858 if not os .path .exists (requirements_txt_path ):
814859 click .echo (f'Creating { requirements_txt_path } ...' )
815860 with open (requirements_txt_path , 'w' , encoding = 'utf-8' ) as f :
816- f .write ('google-cloud-aiplatform[adk,agent_engines] ' )
861+ f .write (_AGENT_ENGINE_REQUIREMENT + ' \n ' )
817862 click .echo (f'Created { requirements_txt_path } ' )
863+ _ensure_agent_engine_dependency (requirements_txt_path )
818864 agent_config ['requirements_file' ] = f'{ temp_folder } /requirements.txt'
819865
820866 env_vars = {}
@@ -912,8 +958,7 @@ def to_agent_engine(
912958 app_name = app_name ,
913959 trace_to_cloud_option = trace_to_cloud ,
914960 is_config_agent = is_config_agent ,
915- temp_folder = temp_folder ,
916- agent_folder = agent_folder ,
961+ agent_folder = f'./{ temp_folder } ' ,
917962 adk_app_object = adk_app_object ,
918963 adk_app_type = adk_app_type ,
919964 express_mode = api_key is not None ,
@@ -946,7 +991,9 @@ def to_agent_engine(
946991 click .secho (f'✅ Updated agent engine: { agent_engine_id } ' , fg = 'green' )
947992 finally :
948993 click .echo (f'Cleaning up the temp folder: { temp_folder } ' )
949- shutil .rmtree (temp_folder )
994+ shutil .rmtree (agent_src_path )
995+ if did_change_cwd :
996+ os .chdir (original_cwd )
950997
951998
952999def to_gke (
0 commit comments