1818# ------------------------------------------------------------------------------
1919
2020"""Implementation of the 'aea add' subcommand."""
21-
21+ from pathlib import Path
2222from typing import cast
2323
2424import click
2525
2626from aea .cli .registry .add import fetch_package
27- from aea .cli .utils .click_utils import PublicIdParameter
27+ from aea .cli .utils .click_utils import PublicIdParameter , registry_flag
2828from aea .cli .utils .config import load_item_config
2929from aea .cli .utils .context import Context
3030from aea .cli .utils .decorators import check_aea_project , clean_after , pass_ctx
4343
4444
4545@click .group ()
46- @click . option ( "--local" , is_flag = True , help = "For adding from local folder." )
46+ @registry_flag ( )
4747@click .pass_context
4848@check_aea_project
49- def add (click_context , local ):
49+ def add (click_context , local , remote ):
5050 """Add a resource to the agent."""
5151 ctx = cast (Context , click_context .obj )
52- if local :
53- ctx .set_config ("is_local " , True )
52+ ctx . set_config ( "is_local" , local and not remote )
53+ ctx .set_config ("is_mixed " , not local and not remote )
5454
5555
5656@add .command ()
@@ -95,13 +95,7 @@ def add_item(ctx: Context, item_type: str, item_public_id: PublicId) -> None:
9595 :param item_public_id: the item public id.
9696 :return: None
9797 """
98- agent_name = cast (str , ctx .agent_config .agent_name )
99-
100- click .echo (
101- "Adding {} '{}' to the agent '{}'..." .format (
102- item_type , item_public_id , agent_name
103- )
104- )
98+ click .echo (f"Adding { item_type } '{ item_public_id } '..." )
10599 if is_item_present (ctx , item_type , item_public_id ):
106100 present_item_id = get_item_id_present (ctx , item_type , item_public_id )
107101 raise click .ClickException (
@@ -112,16 +106,16 @@ def add_item(ctx: Context, item_type: str, item_public_id: PublicId) -> None:
112106
113107 dest_path = get_package_path (ctx , item_type , item_public_id )
114108 is_local = ctx .config .get ("is_local" )
109+ is_mixed = ctx .config .get ("is_mixed" )
115110
116111 ctx .clean_paths .append (dest_path )
117112
118- is_distributed = is_distributed_item (item_public_id )
119- if is_local and is_distributed : # pragma: nocover
120- source_path = find_item_in_distribution (ctx , item_type , item_public_id )
121- package_path = copy_package_directory (source_path , dest_path )
122- elif is_local and not is_distributed :
123- source_path , _ = find_item_locally (ctx , item_type , item_public_id )
124- package_path = copy_package_directory (source_path , dest_path )
113+ if is_mixed :
114+ package_path = fetch_item_mixed (ctx , item_type , item_public_id , dest_path )
115+ elif is_local :
116+ package_path = find_item_locally_or_distributed (
117+ ctx , item_type , item_public_id , dest_path
118+ )
125119 else :
126120 package_path = fetch_package (
127121 item_type , public_id = item_public_id , cwd = ctx .cwd , dest = dest_path
@@ -167,3 +161,54 @@ def _add_item_deps(ctx: Context, item_type: str, item_config) -> None:
167161 for skill_public_id in item_config .skills :
168162 if skill_public_id not in ctx .agent_config .skills :
169163 add_item (ctx , "skill" , skill_public_id )
164+
165+
166+ def find_item_locally_or_distributed (
167+ ctx : Context , item_type : str , item_public_id : PublicId , dest_path : str
168+ ) -> Path :
169+ """
170+ Unify find item locally both in case it is distributed or not.
171+
172+ :param ctx: the CLI context.
173+ :param item_type: the item type.
174+ :param item_public_id: the item public id.
175+ :param dest_path: the path to the destination.
176+ :return: the path to the found package.
177+ """
178+ is_distributed = is_distributed_item (item_public_id )
179+ if is_distributed : # pragma: nocover
180+ source_path = find_item_in_distribution (ctx , item_type , item_public_id )
181+ package_path = copy_package_directory (source_path , dest_path )
182+ else :
183+ source_path , _ = find_item_locally (ctx , item_type , item_public_id )
184+ package_path = copy_package_directory (source_path , dest_path )
185+
186+ return package_path
187+
188+
189+ def fetch_item_mixed (
190+ ctx : Context , item_type : str , item_public_id : PublicId , dest_path : str ,
191+ ) -> Path :
192+ """
193+ Find item, mixed mode.
194+
195+ That is, give priority to local registry, and fall back to remote registry
196+ in case of failure.
197+
198+ :param ctx: the CLI context.
199+ :param item_type: the item type.
200+ :param item_public_id: the item public id.
201+ :param dest_path: the path to the destination.
202+ :return: the path to the found package.
203+ """
204+ try :
205+ package_path = find_item_locally_or_distributed (
206+ ctx , item_type , item_public_id , dest_path
207+ )
208+ except click .ClickException :
209+ click .echo ("Fetch from local registry failed, trying remote registry..." )
210+ # the following might raise exception, but we don't catch it this time
211+ package_path = fetch_package (
212+ item_type , public_id = item_public_id , cwd = ctx .cwd , dest = dest_path
213+ )
214+ return package_path
0 commit comments