Skip to content

Commit

Permalink
Merge pull request #540 from fetchai/develop
Browse files Browse the repository at this point in the history
Release v0.1.15
  • Loading branch information
DavidMinarsch authored Dec 21, 2019
2 parents bf4badf + 54159b7 commit 629fdd4
Show file tree
Hide file tree
Showing 329 changed files with 11,684 additions and 6,192 deletions.
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ _Put an `x` in the boxes that apply._
- [ ] I built the documentation and updated it with the latest changes
- [ ] I've added an item in `HISTORY.rst` for this release
- [ ] I bumped the version number in the `aea/__version__.py` file.
- [ ] I bumped the version number in the `docs/version.md` file
- [ ] I bumped the version number in every Docker image of the repo and published it. Also, I built and published them with tag `latest`
(check the READMEs of [`aea-develop`](../develop-image/README.md#publish)
and [`aea-deploy`](../deploy-image/README.md#publish))
Expand Down
19 changes: 19 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,22 @@ Release History
- Adds support to run multiple connections from CLI
- Updates the docs and adds uml diagrams
- Multiple additional minor fixes and changes

0.1.15 (2019-12-19)
-------------------

- Moves non-default packages from aea to packages directory
- Supports get & set on package configs
- Changes skill configuration resource types from lists to dictionaries
- Adds additional features to decision maker
- Refactors most protocols and improves their API
- Removes multiple unintended side-effects of the CLI
- Improves dependency referencing in config files
- Adds push and publish functionality to CLI
- Introduces simple and composite behaviours and applies them in skills
- Adds URI to envelopes
- Adds guide for programmatic assembly of an AEA
- Adds guide on agent-oriented development
- Multiple minor doc updates
- Adds additional tests
- Multiple additional minor fixes and changes
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pygments = "*"
pytest-asyncio = "*"
gym = "*"
numpy = "*"
tensorflow = "*"
scikit-image = "*"
mkdocs-mermaid-plugin = {editable = true,git = "https://github.com/pugong/mkdocs-mermaid-plugin.git"}

Expand All @@ -45,6 +46,7 @@ python-dotenv = "*"
fetchai-ledger-api = "==0.8.1"
web3 = "==5.2.2"
eth-account = "==0.4.0"
fetch-p2p-api = {index = "https://test.pypi.org/simple/",version = "==0.0.1"}

[requires]
python_version = "3.7"
464 changes: 383 additions & 81 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion aea/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
__title__ = 'aea'
__description__ = 'Autonomous Economic Agent framework'
__url__ = 'https://github.com/fetchai/agents-aea.git'
__version__ = '0.1.14'
__version__ = '0.1.15'
__author__ = 'Fetch.AI Limited'
__license__ = 'Apache 2.0'
__copyright__ = '2019 Fetch.AI Limited'
26 changes: 21 additions & 5 deletions aea/aea.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"""This module contains the implementation of an Autonomous Economic Agent."""
import logging
from asyncio import AbstractEventLoop
from concurrent.futures import Executor
from typing import Optional, cast, List

from aea.agent import Agent
Expand All @@ -31,6 +32,7 @@
from aea.mail.base import Envelope
from aea.registries.base import Filter, Resources
from aea.skills.error.handlers import ErrorHandler
from aea.skills.tasks import TaskManager

logger = logging.getLogger(__name__)

Expand All @@ -46,7 +48,8 @@ def __init__(self, name: str,
loop: Optional[AbstractEventLoop] = None,
timeout: float = 0.0,
debug: bool = False,
max_reactions: int = 20) -> None:
max_reactions: int = 20,
executor: Optional[Executor] = None) -> None:
"""
Instantiate the agent.
Expand All @@ -59,12 +62,14 @@ def __init__(self, name: str,
:param timeout: the time in (fractions of) seconds to time out an agent between act and react
:param debug: if True, run the agent in debug mode.
:param max_reactions: the processing rate of messages per iteration.
:param executor: executor for asynchronous execution of tasks.
:return: None
"""
super().__init__(name=name, wallet=wallet, connections=connections, loop=loop, timeout=timeout, debug=debug)

self.max_reactions = max_reactions
self._task_manager = TaskManager(executor)
self._decision_maker = DecisionMaker(self.name,
self.max_reactions,
self.outbox,
Expand All @@ -79,7 +84,8 @@ def __init__(self, name: str,
self.decision_maker.message_in_queue,
self.decision_maker.ownership_state,
self.decision_maker.preferences,
self.decision_maker.goal_pursuit_readiness)
self.decision_maker.goal_pursuit_readiness,
self.task_manager.task_queue)
self._resources = resources
self._filter = Filter(self.resources, self.decision_maker.message_out_queue)

Expand Down Expand Up @@ -108,6 +114,11 @@ def filter(self) -> Filter:
"""Get filter."""
return self._filter

@property
def task_manager(self) -> TaskManager:
"""Get the task manager."""
return self._task_manager

def setup(self) -> None:
"""
Set up the agent.
Expand All @@ -116,6 +127,7 @@ def setup(self) -> None:
"""
self.resources.load(self.context)
self.resources.setup()
self.task_manager.start()

def act(self) -> None:
"""
Expand All @@ -124,7 +136,7 @@ def act(self) -> None:
:return: None
"""
for behaviour in self.filter.get_active_behaviours():
behaviour.act()
behaviour.act_wrapper()

def react(self) -> None:
"""
Expand Down Expand Up @@ -159,8 +171,10 @@ def _handle(self, envelope: Envelope) -> None:

try:
msg = protocol.serializer.decode(envelope.message)
except Exception:
msg.counterparty = envelope.sender
except Exception as e:
error_handler.send_decoding_error(envelope)
logger.warning("Decoding error. Exception: {}".format(str(e)))
return

if not protocol.check(msg): # pragma: no cover
Expand All @@ -174,14 +188,15 @@ def _handle(self, envelope: Envelope) -> None:
return

for handler in handlers:
handler.handle(msg, envelope.sender)
handler.handle(msg)

def update(self) -> None:
"""
Update the current state of the agent.
:return None
"""
# TODO: task should be submitted by the behaviours and handlers
for task in self.filter.get_active_tasks():
task.execute()
self.decision_maker.execute()
Expand All @@ -193,5 +208,6 @@ def teardown(self) -> None:
:return: None
"""
self.task_manager.stop()
if self._resources is not None:
self._resources.teardown()
17 changes: 12 additions & 5 deletions aea/cli/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

from aea import AEA_DIR
from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config
from aea.cli.registry.utils import fetch_package, split_public_id
from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, \
DEFAULT_PROTOCOL_CONFIG_FILE
from aea.cli.registry.utils import fetch_package, split_public_id


@click.group()
Expand All @@ -46,7 +46,7 @@ def add(ctx: Context, registry):
_try_to_load_agent_config(ctx)


def _find_connection_locally(ctx, connection_name):
def _find_connection_locally(ctx, connection_name, click_context):
# check that the provided path points to a proper connection directory -> look for connection.yaml file.
# first check in aea dir
registry_path = ctx.agent_config.registry_path
Expand All @@ -62,7 +62,8 @@ def _find_connection_locally(ctx, connection_name):
# try to load the connection configuration file
try:
connection_configuration = ctx.connection_loader.load(open(str(connection_configuration_filepath)))
logger.info("Connection '{}' supports the following protocols: {}".format(connection_name, connection_configuration.restricted_to_protocols))
if connection_configuration.restricted_to_protocols != []:
logger.info("Connection '{}' is restricted to the following protocols: {}".format(connection_name, connection_configuration.restricted_to_protocols))
except ValidationError as e:
logger.error("Connection configuration file not valid: {}".format(str(e)))
sys.exit(1)
Expand All @@ -77,6 +78,12 @@ def _find_connection_locally(ctx, connection_name):
logger.error(str(e))
sys.exit(1)

# check for protocol dependencies not yet added, and add it.
for protocol_name in connection_configuration.protocols:
if protocol_name not in ctx.agent_config.protocols:
logger.debug("Adding protocol '{}' to the agent...".format(protocol_name))
click_context.invoke(protocol, protocol_name=protocol_name)


@add.command()
@click.argument(
Expand Down Expand Up @@ -106,7 +113,7 @@ def connection(click_context, connection_name):
# fetch from Registry
fetch_package('connection', public_id=public_id, cwd=ctx.cwd)
else:
_find_connection_locally(ctx, connection_name)
_find_connection_locally(ctx, connection_name, click_context)

# make the 'connections' folder a Python package.
connections_init_module = os.path.join(ctx.cwd, "connections", "__init__.py")
Expand Down Expand Up @@ -221,7 +228,7 @@ def _find_skill_locally(ctx, skill_name, click_context):
logger.error(str(e))
sys.exit(1)

# check for not supported protocol, and add it.
# check for protocol dependencies not yet added, and add it.
for protocol_name in skill_configuration.protocols:
if protocol_name not in ctx.agent_config.protocols:
logger.debug("Adding protocol '{}' to the agent...".format(protocol_name))
Expand Down
32 changes: 20 additions & 12 deletions aea/cli/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@

from aea.cli.loggers import default_logging_config
from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, AgentConfig, SkillConfig, ConnectionConfig, ProtocolConfig, \
DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE
DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, Dependencies
from aea.configurations.loader import ConfigLoader

logger = logging.getLogger("aea")
logger = default_logging_config(logger)

DEFAULT_REGISTRY_PATH = "../packages"
DEFAULT_REGISTRY_PATH = str(Path("..", "packages"))
DEFAULT_CONNECTION = "stub"
DEFAULT_SKILL = "error"


class Context(object):
Expand Down Expand Up @@ -67,31 +69,31 @@ def set_config(self, key, value) -> None:
self.config[key] = value
logger.debug(' config[%s] = %s' % (key, value))

def get_dependencies(self) -> List[str]:
def get_dependencies(self) -> Dependencies:
"""Aggregate the dependencies from every component.
:return a list of dependency version specification. e.g. ["gym >= 1.0.0"]
"""
dependencies = [] # type: List[str]
dependencies = {} # type: Dependencies
for protocol_id in self.agent_config.protocols:
path = str(Path("protocols", protocol_id, DEFAULT_PROTOCOL_CONFIG_FILE))
protocol_config = self.protocol_loader.load(open(path))
deps = cast(List[str], protocol_config.dependencies)
dependencies.extend(deps)
deps = cast(Dependencies, protocol_config.dependencies)
dependencies.update(deps)

for connection_id in self.agent_config.connections:
path = str(Path("connections", connection_id, DEFAULT_CONNECTION_CONFIG_FILE))
connection_config = self.connection_loader.load(open(path))
deps = cast(List[str], connection_config.dependencies)
dependencies.extend(deps)
deps = cast(Dependencies, connection_config.dependencies)
dependencies.update(deps)

for skill_id in self.agent_config.skills:
path = str(Path("skills", skill_id, DEFAULT_SKILL_CONFIG_FILE))
skill_config = self.skill_loader.load(open(path))
deps = cast(List[str], skill_config.dependencies)
dependencies.extend(deps)
deps = cast(Dependencies, skill_config.dependencies)
dependencies.update(deps)

return sorted(set(dependencies))
return dependencies


pass_ctx = click.make_pass_decorator(Context)
Expand Down Expand Up @@ -146,11 +148,14 @@ def format_items(items):
for item in items:
list_str += (
'{line}\n'
'Public ID: {public_id}\n'
'Name: {name}\n'
'Description: {description}\n'
'Version: {version}\n'
'{line}\n'.format(
name=item['name'],
# TODO: switch to unsafe get public_id when every obj has it
public_id=item.get('public_id'),
description=item['description'],
version=item['version'],
line='-' * 30
Expand All @@ -164,12 +169,15 @@ def format_skills(items):
for item in items:
list_str += (
'{line}\n'
'Public ID: {public_id}\n'
'Name: {name}\n'
'Description: {description}\n'
'Protocols: {protocols}\n'
'Version: {version}\n'
'{line}\n'.format(
name=item['name'],
# TODO: switch to unsafe get public_id when every obj has it
public_id=item.get('public_id'),
description=item['description'],
version=item['version'],
protocols=''.join(
Expand Down Expand Up @@ -212,5 +220,5 @@ def arg_strip(s):

connection_names = set(arg_strip(s) for s in value.split(",") if arg_strip(s) != "")
return list(connection_names)
except Exception:
except Exception: # pragma: no cover
raise click.BadParameter(value)
Loading

0 comments on commit 629fdd4

Please sign in to comment.