Ejemplo n.º 1
0
def remove_unused_component_configurations(ctx: Context):
    """
    Remove all component configurations for items not registered and dump agent config.

    Context manager!
    Clean all configurations on enter, restore actual configurations and dump agent config.
    """
    saved_configuration = ctx.agent_config.component_configurations
    ctx.agent_config.component_configurations = {}
    try:
        yield
    finally:
        saved_configuration_by_component_prefix = {
            key.component_prefix: value
            for key, value in saved_configuration.items()
        }
        # need to reload agent configuration with the updated references
        try_to_load_agent_config(ctx)
        for component_id in ctx.agent_config.package_dependencies:
            if component_id.component_prefix in saved_configuration_by_component_prefix:
                ctx.agent_config.component_configurations[
                    component_id] = saved_configuration_by_component_prefix[
                        component_id.component_prefix]

    with open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w") as f:
        ctx.agent_loader.dump(ctx.agent_config, f)
Ejemplo n.º 2
0
def search(click_context, local):
    """Search for components in the registry.

    If called from an agent directory, it will check

    E.g.

        aea search connections
        aea search --local skills
    """
    ctx = cast(Context, click_context.obj)
    if local:
        ctx.set_config("is_local", True)
        # if we are in an agent directory, try to load the configuration file.
        # otherwise, use the default path (i.e. 'packages/' in the current directory.)
        try:
            try_to_load_agent_config(ctx, is_exit_on_except=False)
            # path = Path(DEFAULT_AEA_CONFIG_FILE)
            # fp = open(str(path), mode="r", encoding="utf-8")
            # agent_config = ctx.agent_loader.load(fp)
            registry_directory = ctx.agent_config.registry_path
        except Exception:
            registry_directory = os.path.join(ctx.cwd, DEFAULT_REGISTRY_PATH)

        ctx.set_config("registry_directory", registry_directory)
        logger.debug("Using registry {}".format(registry_directory))
Ejemplo n.º 3
0
def publish_agent(ctx: Context):
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        "connections": ctx.agent_config.connections,
        "contracts": ctx.agent_config.contracts,
        "protocols": ctx.agent_config.protocols,
        "skills": ctx.agent_config.skills,
    }

    path = "/agents/create"
    logger.debug("Publishing agent {} to Registry ...".format(name))
    resp = request_api("POST", path, data=data, is_auth=True, filepath=output_tar)
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
Ejemplo n.º 4
0
def fetch_agent_locally(
    ctx: Context,
    public_id: PublicId,
    alias: Optional[str] = None,
    target_dir: Optional[str] = None,
) -> None:
    """
    Fetch Agent from local packages.

    :param ctx: a Context object.
    :param public_id: public ID of agent to be fetched.
    :param alias: an optional alias.
    :param target_dir: the target directory to which the agent is fetched.
    :return: None
    """
    packages_path = (
        DEFAULT_REGISTRY_NAME if ctx.registry_path is None else ctx.registry_path
    )
    source_path = try_get_item_source_path(
        packages_path, public_id.author, AGENTS, public_id.name
    )
    enforce(
        ctx.config.get("is_local") is True or ctx.config.get("is_mixed") is True,
        "Please use `ctx.set_config('is_local', True)` or `ctx.set_config('is_mixed', True)` to fetch agent and all components locally.",
    )
    try_to_load_agent_config(ctx, agent_src_path=source_path)
    if not _is_version_correct(ctx, public_id):
        raise click.ClickException(
            "Wrong agent version in public ID: specified {}, found {}.".format(
                public_id.version, ctx.agent_config.version
            )
        )

    folder_name = target_dir or (public_id.name if alias is None else alias)
    target_path = os.path.join(ctx.cwd, folder_name)
    if os.path.exists(target_path):
        path = Path(target_path)
        raise click.ClickException(
            f'Item "{path.name}" already exists in target folder "{path.parent}".'
        )
    if target_dir is not None:
        os.makedirs(target_path)  # pragma: nocover

    ctx.clean_paths.append(target_path)
    copy_tree(source_path, target_path)

    ctx.cwd = target_path
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config,
            open_file(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"),
        )

    _fetch_agent_deps(ctx)
    click.echo("Agent {} successfully fetched.".format(public_id.name))
Ejemplo n.º 5
0
def _fetch_agent_locally(
    click_context, public_id: PublicId, alias: Optional[str] = None
) -> None:
    """
    Fetch Agent from local packages.

    :param click_context: click context object.
    :param public_id: public ID of agent to be fetched.
    :param click_context: the click context.
    :param alias: an optional alias.
    :return: None
    """
    packages_path = os.path.basename(DEFAULT_REGISTRY_PATH)
    source_path = try_get_item_source_path(
        packages_path, public_id.author, "agents", public_id.name
    )
    ctx = cast(Context, click_context.obj)
    try_to_load_agent_config(ctx, agent_src_path=source_path)
    if not _is_version_correct(ctx, public_id):
        raise click.ClickException(
            "Wrong agent version in public ID: specified {}, found {}.".format(
                public_id.version, ctx.agent_config.version
            )
        )

    folder_name = public_id.name if alias is None else alias
    target_path = os.path.join(ctx.cwd, folder_name)
    if os.path.exists(target_path):
        raise click.ClickException(
            'Item "{}" already exists in target folder.'.format(public_id.name)
        )

    ctx.clean_paths.append(target_path)
    copy_tree(source_path, target_path)

    ctx.cwd = target_path
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")
        )

    # add dependencies
    for item_type in ("skill", "connection", "contract", "protocol"):
        item_type_plural = "{}s".format(item_type)
        required_items = getattr(ctx.agent_config, item_type_plural)
        for item_id in required_items:
            try:
                _add_item(click_context, item_type, item_id)
            except click.ClickException as e:
                raise click.ClickException(
                    "Failed to add {} dependency {}: {}".format(
                        item_type, item_id, str(e)
                    )
                )
    click.echo("Agent {} successfully fetched.".format(public_id.name))
Ejemplo n.º 6
0
def fetch_agent(
    click_context, public_id: PublicId, alias: Optional[str] = None
) -> None:
    """
    Fetch Agent from Registry.

    :param ctx: Context
    :param public_id: str public ID of desirable Agent.
    :param click_context: the click context.
    :param alias: an optional alias.
    :return: None
    """
    author, name, version = public_id.author, public_id.name, public_id.version
    api_path = "/agents/{}/{}/{}".format(author, name, version)
    resp = request_api("GET", api_path)
    file_url = resp["file"]

    ctx = cast(Context, click_context.obj)
    filepath = download_file(file_url, ctx.cwd)

    folder_name = name if alias is None else alias
    aea_folder = os.path.join(ctx.cwd, folder_name)
    ctx.clean_paths.append(aea_folder)

    extract(filepath, ctx.cwd)

    if alias is not None:
        os.rename(name, alias)

    ctx.cwd = aea_folder
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")
        )

    click.echo("Fetching dependencies...")
    for item_type in ("connection", "contract", "skill", "protocol"):
        item_type_plural = item_type + "s"

        # initialize fetched agent with empty folders for custom packages
        custom_items_folder = os.path.join(ctx.cwd, item_type_plural)
        os.makedirs(custom_items_folder)

        config = getattr(ctx.agent_config, item_type_plural)
        for item_public_id in config:
            try:
                _add_item(click_context, item_type, item_public_id)
            except Exception as e:
                raise click.ClickException(
                    'Unable to fetch dependency for agent "{}", aborting. {}'.format(
                        name, e
                    )
                )
    click.echo("Dependencies successfully fetched.")
    click.echo("Agent {} successfully fetched to {}.".format(name, aea_folder))
Ejemplo n.º 7
0
def _check_aea_project(args):
    try:
        click_context = args[0]
        ctx = cast(Context, click_context.obj)
        try_to_load_agent_config(ctx)
        skip_consistency_check = ctx.config["skip_consistency_check"]
        if not skip_consistency_check:
            _validate_config_consistency(ctx)
    except Exception as e:
        raise click.ClickException(str(e))
Ejemplo n.º 8
0
def _check_aea_project(args: Tuple[Any, ...], check_aea_version: bool = True) -> None:
    try:
        click_context = args[0]
        ctx = cast(Context, click_context.obj)
        try_to_load_agent_config(ctx)
        skip_consistency_check = ctx.config["skip_consistency_check"]
        if not skip_consistency_check:
            _validate_config_consistency(ctx, check_aea_version=check_aea_version)
    except Exception as e:  # pylint: disable=broad-except
        raise click.ClickException(str(e))
Ejemplo n.º 9
0
def fetch_agent_locally(
    ctx: Context,
    public_id: PublicId,
    alias: Optional[str] = None,
    target_dir: Optional[str] = None,
    is_mixed: bool = True,
) -> None:
    """
    Fetch Agent from local packages.

    :param ctx: a Context object.
    :param public_id: public ID of agent to be fetched.
    :param alias: an optional alias.
    :param target_dir: the target directory to which the agent is fetched.
    :param is_mixed: flag to enable mixed mode (try first local, then remote).
    :return: None
    """
    packages_path = (DEFAULT_REGISTRY_PATH
                     if ctx.registry_path is None else ctx.registry_path)
    source_path = try_get_item_source_path(packages_path, public_id.author,
                                           "agents", public_id.name)

    try_to_load_agent_config(ctx, agent_src_path=source_path)
    if not _is_version_correct(ctx, public_id):
        raise click.ClickException(
            "Wrong agent version in public ID: specified {}, found {}.".format(
                public_id.version, ctx.agent_config.version))

    folder_name = target_dir or (public_id.name if alias is None else alias)
    target_path = os.path.join(ctx.cwd, folder_name)
    if os.path.exists(target_path):
        raise click.ClickException(
            'Item "{}" already exists in target folder.'.format(
                public_id.name))
    if target_dir is not None:
        os.makedirs(target_path)  # pragma: nocover

    ctx.clean_paths.append(target_path)
    copy_tree(source_path, target_path)

    ctx.cwd = target_path
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config,
            open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"))

    # add dependencies
    _fetch_agent_deps(ctx, is_mixed)
    click.echo("Agent {} successfully fetched.".format(public_id.name))
Ejemplo n.º 10
0
def _eject_item(ctx: Context, item_type: str, public_id: PublicId):
    """
    Eject item from installed (vendor) to custom folder.

    :param ctx: context object.
    :param item_type: item type.
    :param public_id: item public ID.

    :return: None
    :raises: ClickException if item is absent at source path or present at destenation path.
    """
    item_type_plural = item_type + "s"
    if not is_item_present(ctx, item_type, public_id):  # pragma: no cover
        raise click.ClickException(
            "{} {} not found in agent's vendor items.".format(
                item_type.title(), public_id))
    src = get_package_path(ctx, item_type, public_id)
    dst = get_package_path(ctx, item_type, public_id, is_vendor=False)
    if is_item_present(ctx, item_type, public_id,
                       is_vendor=False):  # pragma: no cover
        raise click.ClickException(
            "{} {} is already in a non-vendor item.".format(
                item_type.title(), public_id))

    ctx.clean_paths.append(dst)
    copy_package_directory(Path(src), dst)

    try_to_load_agent_config(ctx)
    new_public_id = PublicId(author=ctx.agent_config.author,
                             name=public_id.name,
                             version=DEFAULT_VERSION)
    update_item_config(item_type,
                       Path(dst),
                       author=new_public_id.author,
                       version=new_public_id.version)
    update_item_public_id_in_init(item_type, Path(dst), new_public_id)
    supported_items = getattr(ctx.agent_config, item_type_plural)
    for p_id in supported_items:
        if p_id.author == public_id.author and p_id.name == public_id.name:
            present_public_id = p_id
            break
    supported_items.add(new_public_id)
    supported_items.remove(present_public_id)
    update_item_config("agent", Path(ctx.cwd),
                       **{item_type_plural: supported_items})

    shutil.rmtree(src)
    fingerprint_item(ctx, item_type, new_public_id)
    click.echo("Successfully ejected {} {} to {} as {}.".format(
        item_type, public_id, dst, new_public_id))
Ejemplo n.º 11
0
def publish_agent(ctx: Context) -> None:
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    readme_source_path = os.path.join(ctx.cwd, DEFAULT_README_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)
        if is_readme_present(readme_source_path):
            readme_file_target_path = os.path.join(package_dir, DEFAULT_README_FILE)
            shutil.copy(readme_source_path, readme_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        CONNECTIONS: ctx.agent_config.connections,
        CONTRACTS: ctx.agent_config.contracts,
        PROTOCOLS: ctx.agent_config.protocols,
        SKILLS: ctx.agent_config.skills,
    }

    files = {}
    try:
        files["file"] = open(output_tar, "rb")
        if is_readme_present(readme_source_path):
            files["readme"] = open(readme_source_path, "rb")
        path = "/agents/create"
        logger.debug("Publishing agent {} to Registry ...".format(name))
        resp = cast(
            JSONLike, request_api("POST", path, data=data, is_auth=True, files=files)
        )
    finally:
        for fd in files.values():
            fd.close()
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
Ejemplo n.º 12
0
def get_local_items(agent_id: str, item_type: str):
    """Return a list of protocols, skills or connections supported by a local agent."""
    if agent_id == "NONE":
        return [], 200  # 200 (Success)

    # need to place ourselves one directory down so the searcher can find the packages
    ctx = Context(cwd=os.path.join(app_context.agents_dir, agent_id))
    try:
        try_to_load_agent_config(ctx)
        result = cli_list_agent_items(ctx, item_type)
    except ClickException:
        return {
            "detail": "Failed to list agent items."
        }, 400  # 400 Bad request
    else:
        sorted_items = sort_items(result)
        return sorted_items, 200  # 200 (Success)
Ejemplo n.º 13
0
 def convert(self, value, param, ctx):
     """Convert the value. This is not invoked for values that are `None` (the missing value)."""
     cwd = os.getcwd()
     path = Path(value)
     try:
         # check that the target folder is an AEA project.
         os.chdir(path)
         fp = open(DEFAULT_AEA_CONFIG_FILE, mode="r", encoding="utf-8")
         ctx.obj.agent_config = ctx.obj.agent_loader.load(fp)
         try_to_load_agent_config(ctx.obj)
         # everything ok - return the parameter to the command
         return value
     except Exception:
         raise click.ClickException(
             "The name provided is not a path to an AEA project.")
     finally:
         os.chdir(cwd)
Ejemplo n.º 14
0
def scaffold_item(agent_id: str, item_type: str, item_id: str):
    """Scaffold a moslty empty item on an agent (either protocol, skill or connection)."""
    agent_dir = os.path.join(app_context.agents_dir, agent_id)
    ctx = Context(cwd=agent_dir)
    try:
        try_to_load_agent_config(ctx)
        cli_scaffold_item(ctx, item_type, item_id)
    except ClickException:
        return (
            {
                "detail": "Failed to scaffold a new {} in to agent {}".format(
                    item_type, agent_id
                )
            },
            400,
        )  # 400 Bad request
    else:
        return agent_id, 201  # 200 (OK)
Ejemplo n.º 15
0
def remove_local_item(agent_id: str, item_type: str, item_id: str):
    """Remove a protocol, skill or connection from a local agent."""
    agent_dir = os.path.join(app_context.agents_dir, agent_id)
    ctx = Context(cwd=agent_dir)
    try:
        try_to_load_agent_config(ctx)
        cli_remove_item(ctx, item_type, PublicId.from_str(item_id))
    except ClickException:
        return (
            {
                "detail": "Failed to remove {} {} from agent {}".format(
                    item_type, item_id, agent_id
                )
            },
            400,
        )  # 400 Bad request
    else:
        return agent_id, 201  # 200 (OK)
Ejemplo n.º 16
0
def add_item(agent_id: str, item_type: str, item_id: str):
    """Add a protocol, skill or connection to the register to a local agent."""
    ctx = Context(cwd=os.path.join(app_context.agents_dir, agent_id))
    ctx.set_config("is_local", app_context.local)
    try:
        try_to_load_agent_config(ctx)
        cli_add_item(ctx, item_type, PublicId.from_str(item_id))
    except ClickException as e:
        return (
            {
                "detail": "Failed to add {} {} to agent {}. {}".format(
                    item_type, item_id, agent_id, str(e)
                )
            },
            400,
        )  # 400 Bad request
    else:
        return agent_id, 201  # 200 (OK)
Ejemplo n.º 17
0
def fetch_agent_locally(ctx: Context,
                        public_id: PublicId,
                        alias: Optional[str] = None) -> None:
    """
    Fetch Agent from local packages.

    :param ctx: a Context object.
    :param public_id: public ID of agent to be fetched.
    :param alias: an optional alias.
    :return: None
    """
    packages_path = os.path.basename(DEFAULT_REGISTRY_PATH)
    source_path = try_get_item_source_path(packages_path, public_id.author,
                                           "agents", public_id.name)

    try_to_load_agent_config(ctx, agent_src_path=source_path)
    if not _is_version_correct(ctx, public_id):
        raise click.ClickException(
            "Wrong agent version in public ID: specified {}, found {}.".format(
                public_id.version, ctx.agent_config.version))

    folder_name = public_id.name if alias is None else alias
    target_path = os.path.join(ctx.cwd, folder_name)
    if os.path.exists(target_path):
        raise click.ClickException(
            'Item "{}" already exists in target folder.'.format(
                public_id.name))

    ctx.clean_paths.append(target_path)
    copy_tree(source_path, target_path)

    ctx.cwd = target_path
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config,
            open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"))

    # add dependencies
    _fetch_agent_deps(ctx)
    click.echo("Agent {} successfully fetched.".format(public_id.name))
Ejemplo n.º 18
0
def setup_search_ctx(ctx: Context, local: bool) -> None:
    """
    Set up search command.

    :param click_context: click context object.
    :param local: bool flag for local search.

    :return: None.
    """
    if local:
        ctx.set_config("is_local", True)
        # if we are in an agent directory, try to load the configuration file.
        # otherwise, use the default path (i.e. 'packages/' in the current directory.)
        try:
            try_to_load_agent_config(ctx, is_exit_on_except=False)
            registry_directory = ctx.agent_config.registry_path
        except Exception:  # pylint: disable=broad-except
            registry_directory = os.path.join(ctx.cwd, DEFAULT_REGISTRY_PATH)

        ctx.set_config("registry_directory", registry_directory)
        logger.debug("Using registry {}".format(registry_directory))
Ejemplo n.º 19
0
def _eject_item(
    ctx: Context,
    item_type: str,
    public_id: PublicId,
    quiet: bool = True,
    with_symlinks: bool = False,
) -> None:
    """
    Eject item from installed (vendor) to custom folder.

    :param ctx: context object.
    :param item_type: item type.
    :param public_id: item public ID.
    :param quiet: if false, the function will ask the user in case of recursive eject.

    :return: None
    :raises: ClickException if item is absent at source path or present at destenation path.
    """
    # we know cli_author is set because of the above checks.
    cli_author: str = cast(str, ctx.config.get("cli_author"))
    item_type_plural = item_type + "s"
    if not is_item_present(
            ctx.cwd,
            ctx.agent_config,
            item_type,
            public_id,
            is_vendor=True,
            with_version=True,
    ):  # pragma: no cover
        raise click.ClickException(
            f"{item_type.title()} {public_id} not found in agent's vendor items."
        )
    src = get_package_path(ctx.cwd, item_type, public_id)
    dst = get_package_path(ctx.cwd, item_type, public_id, is_vendor=False)
    if is_item_present(ctx.cwd,
                       ctx.agent_config,
                       item_type,
                       public_id,
                       is_vendor=False):  # pragma: no cover
        raise click.ClickException(
            f"{item_type.title()} {public_id} is already a non-vendor package."
        )
    configuration = load_item_config(item_type, Path(src))

    if public_id.package_version.is_latest:
        # get 'concrete' public id, in case it is 'latest'
        component_prefix = ComponentType(
            item_type), public_id.author, public_id.name
        component_id = get_latest_component_id_from_prefix(
            ctx.agent_config, component_prefix)
        # component id is necessarily found, due to the checks above.
        public_id = cast(ComponentId, component_id).public_id

    package_id = PackageId(PackageType(item_type), public_id)

    click.echo(
        f"Ejecting item {package_id.package_type.value} {str(package_id.public_id)}"
    )

    # first, eject all the vendor packages that depend on this
    item_remover = ItemRemoveHelper(ctx, ignore_non_vendor=True)
    reverse_dependencies = (
        item_remover.get_agent_dependencies_with_reverse_dependencies())
    reverse_reachable_dependencies = reachable_nodes(reverse_dependencies,
                                                     {package_id})
    # the reversed topological order of a graph
    # is the topological order of the reverse graph.
    eject_order = list(
        reversed(find_topological_order(reverse_reachable_dependencies)))
    eject_order.remove(package_id)
    if len(eject_order) > 0 and not quiet:
        click.echo(
            f"The following vendor packages will be ejected: {eject_order}")
        answer = click.confirm("Do you want to proceed?")
        if not answer:
            click.echo("Aborted.")
            return

    for dependency_package_id in eject_order:
        # 'dependency_package_id' depends on 'package_id',
        # so we need to eject it first
        _eject_item(
            ctx,
            dependency_package_id.package_type.value,
            dependency_package_id.public_id,
            quiet=True,
        )

    # copy the vendor package into the non-vendor packages
    ctx.clean_paths.append(dst)
    copy_package_directory(Path(src), dst)

    new_public_id = PublicId(cli_author, public_id.name, DEFAULT_VERSION)
    current_version = Version(aea.__version__)
    new_aea_range = (
        configuration.aea_version
        if configuration.aea_version_specifiers.contains(current_version) else
        compute_specifier_from_version(current_version))
    update_item_config(
        item_type,
        Path(dst),
        author=new_public_id.author,
        version=new_public_id.version,
        aea_version=new_aea_range,
    )
    update_item_public_id_in_init(item_type, Path(dst), new_public_id)
    shutil.rmtree(src)

    # update references in all the other packages
    component_type = ComponentType(item_type_plural[:-1])
    old_component_id = ComponentId(component_type, public_id)
    new_component_id = ComponentId(component_type, new_public_id)
    update_references(ctx, {old_component_id: new_component_id})

    # need to reload agent configuration with the updated references
    try_to_load_agent_config(ctx)

    # replace import statements in all the non-vendor packages
    replace_all_import_statements(Path(ctx.cwd), ComponentType(item_type),
                                  public_id, new_public_id)

    # fingerprint all (non-vendor) packages
    fingerprint_all(ctx)

    if with_symlinks:
        click.echo(
            "Adding symlinks from vendor to non-vendor and packages to vendor folders."
        )
        create_symlink_vendor_to_local(ctx, item_type, new_public_id)
        create_symlink_packages_to_vendor(ctx)

    click.echo(
        f"Successfully ejected {item_type} {public_id} to {dst} as {new_public_id}."
    )
Ejemplo n.º 20
0
def fetch_agent(
    ctx: Context,
    public_id: PublicId,
    alias: Optional[str] = None,
    target_dir: Optional[str] = None,
) -> None:
    """
    Fetch Agent from Registry.

    :param ctx: Context
    :param public_id: str public ID of desirable agent.
    :param alias: an optional alias.
    :param target_dir: the target directory to which the agent is fetched.
    :return: None
    """
    author, name, version = public_id.author, public_id.name, public_id.version

    folder_name = target_dir or (name if alias is None else alias)
    aea_folder = os.path.join(ctx.cwd, folder_name)
    if os.path.exists(aea_folder):
        raise ClickException(
            f'Item "{folder_name}" already exists in target folder.')

    ctx.clean_paths.append(aea_folder)

    api_path = f"/agents/{author}/{name}/{version}"
    resp = request_api("GET", api_path)
    file_url = resp["file"]
    filepath = download_file(file_url, ctx.cwd)

    extract(filepath, ctx.cwd)

    if alias or target_dir:
        shutil.move(
            os.path.join(ctx.cwd, name),
            aea_folder,
        )

    ctx.cwd = aea_folder
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        with open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w") as fp:
            ctx.agent_loader.dump(ctx.agent_config, fp)

    click.echo("Fetching dependencies...")
    for item_type in (CONNECTION, CONTRACT, SKILL, PROTOCOL):
        item_type_plural = item_type + "s"

        # initialize fetched agent with empty folders for custom packages
        custom_items_folder = os.path.join(ctx.cwd, item_type_plural)
        os.makedirs(custom_items_folder)

        config = getattr(ctx.agent_config, item_type_plural)
        for item_public_id in config:
            try:
                add_item(ctx, item_type, item_public_id)
            except Exception as e:
                raise click.ClickException(
                    f'Unable to fetch dependency for agent "{name}", aborting. {e}'
                )
    click.echo("Dependencies successfully fetched.")
    click.echo(f"Agent {name} successfully fetched to {aea_folder}.")