diff --git a/README.md b/README.md index 4044f8c6..6fc10787 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,8 @@ Follow these instructions to have your local environment prepared to run the dem 1. Create a Poetry virtual environment and install the dependencies: ```bash - poetry run pip install "cython<3" - poetry run pip install wheel==0.40.0 - poetry run pip install --no-build-isolation pyyaml==5.4.1 + poetry run pip install openapi-core==0.13.2 + poetry run pip install openapi-spec-validator==0.2.8 poetry install && poetry shell ``` diff --git a/packages/packages.json b/packages/packages.json index f17ae2a0..bbb1cf07 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -2,12 +2,12 @@ "dev": { "connection/valory/websocket_client/0.1.0": "bafybeiflmystocxaqblhpzqlcop2vkhsknpzjx2jomohomaxamwskeokzm", "skill/valory/contract_subscription/0.1.0": "bafybeicyugrkx5glat4p4ezwf6i7oduh26eycfie6ftd4uxrknztzl3ik4", - "agent/valory/mech/0.1.0": "bafybeifw2qj6n7kwpjdhupjkcwdz4ydqur4j7744jb3vtevcucxcylpd2e", - "skill/valory/mech_abci/0.1.0": "bafybeihm6tdacrqw3fg4tpujrsi3p3owx4qxem3ehmzntjvxdjie4twcom", + "agent/valory/mech/0.1.0": "bafybeiamnuotz3zj7whskv6hoieswntuobr3fowkfoh52xw4vait4b5eli", + "skill/valory/mech_abci/0.1.0": "bafybeid6pm3a3yd33hpcvcj5s4rydk623b6hmukrgs4oxnabct2zylzotm", "contract/valory/agent_mech/0.1.0": "bafybeicshvlc2slopzidzblf2zhdcw2uuav3ntxcgqduxskjujvebikg5u", - "service/valory/mech/0.1.0": "bafybeigjxfgvkjotfodzell24wvcg74lm2t7rcxdhsdgty2aczhhxcpudy", + "service/valory/mech/0.1.0": "bafybeigh5gm3yc5dsi2gjxcussokytzxqbjvpabedhdshxzgwkmdhknxom", "protocol/valory/acn_data_share/0.1.0": "bafybeih5ydonnvrwvy2ygfqgfabkr47s4yw3uqxztmwyfprulwfsoe7ipq", - "skill/valory/task_submission_abci/0.1.0": "bafybeidk7pqb3hr2cokhroi4sfjbbwssidkfx5lhkjuitoeb4fswhdixra", + "skill/valory/task_submission_abci/0.1.0": "bafybeihluuiksi63kwp2kzn5hdbeek74bnhsctdwl72qv2xjmzqvf7j3va", "skill/valory/task_execution/0.1.0": "bafybeianf56ypn6pjrqvj24uhmty2b5vtsewzjcrqxnrqyjsuudhyjpiue", "contract/valory/agent_registry/0.1.0": "bafybeiargayav6yiztdnwzejoejstcx4idssch2h4f5arlgtzj3tgsgfmu", "protocol/valory/websocket_client/0.1.0": "bafybeih43mnztdv3v2hetr2k3gezg7d3yj4ur7cxdvcyaqhg65e52s5sf4", @@ -37,6 +37,7 @@ "connection/valory/p2p_libp2p_client/0.1.0": "bafybeihge56dn3xep2dzomu7rtvbgo4uc2qqh7ljl3fubqdi2lq44gs5lq", "contract/valory/gnosis_safe_proxy_factory/0.1.0": "bafybeig6evakqztiuyn67vwv63fzgqqfig4whp4qlef3w6pf7hmngrw3si", "contract/valory/gnosis_safe/0.1.0": "bafybeie7qpo4sue4i54pzsg6nx365q6d3i4sl6ygdilwldqqxwroukbkiu", - "contract/valory/multisend/0.1.0": "bafybeig5byt5urg2d2bsecufxe5ql7f4mezg3mekfleeh32nmuusx66p4y" + "contract/valory/multisend/0.1.0": "bafybeig5byt5urg2d2bsecufxe5ql7f4mezg3mekfleeh32nmuusx66p4y", + "connection/valory/http_server/0.22.0": "bafybeie6g5hxhvdijyjlz4opquapxbsh6udzdjvlqhguwd6wp5cb5a5wuy" } } \ No newline at end of file diff --git a/packages/valory/agents/mech/aea-config.yaml b/packages/valory/agents/mech/aea-config.yaml index 43fc1356..6b36635a 100644 --- a/packages/valory/agents/mech/aea-config.yaml +++ b/packages/valory/agents/mech/aea-config.yaml @@ -12,6 +12,7 @@ connections: - valory/ipfs:0.1.0:bafybeigfmqvlzbp67fttccpl4hsu3zaztbxv6vd7ikzra2hfppfkalgpji - valory/ledger:0.19.0:bafybeigdckv3e6bz6kfloz4ucqrsufft6k4jp6bwkbbcvh4fxvgbmzq3dm - valory/p2p_libp2p_client:0.1.0:bafybeihge56dn3xep2dzomu7rtvbgo4uc2qqh7ljl3fubqdi2lq44gs5lq +- valory/http_server:0.22.0:bafybeie6g5hxhvdijyjlz4opquapxbsh6udzdjvlqhguwd6wp5cb5a5wuy - valory/websocket_client:0.1.0:bafybeiflmystocxaqblhpzqlcop2vkhsknpzjx2jomohomaxamwskeokzm contracts: - valory/agent_mech:0.1.0:bafybeicshvlc2slopzidzblf2zhdcw2uuav3ntxcgqduxskjujvebikg5u @@ -36,11 +37,11 @@ skills: - valory/abstract_abci:0.1.0:bafybeieynwkrnlm6wwtufh2jsgnlprjbpmte7now5rk7fbgd5mh5yumhry - valory/abstract_round_abci:0.1.0:bafybeifcq2nwd6m5tgxooe7436bc6lwo73xcreedmhcwauzhp5jic6jeq4 - valory/contract_subscription:0.1.0:bafybeicyugrkx5glat4p4ezwf6i7oduh26eycfie6ftd4uxrknztzl3ik4 -- valory/mech_abci:0.1.0:bafybeihm6tdacrqw3fg4tpujrsi3p3owx4qxem3ehmzntjvxdjie4twcom +- valory/mech_abci:0.1.0:bafybeid6pm3a3yd33hpcvcj5s4rydk623b6hmukrgs4oxnabct2zylzotm - valory/task_execution:0.1.0:bafybeianf56ypn6pjrqvj24uhmty2b5vtsewzjcrqxnrqyjsuudhyjpiue - valory/registration_abci:0.1.0:bafybeig5fb3ibz3tr4kie53venqtajnlhvh7gwt5h45rxwzakwgs6jjsjq - valory/reset_pause_abci:0.1.0:bafybeiergfseqtmsphdimzjijxezqyyhigktvqriw2xb4dyujim6s5dr4a -- valory/task_submission_abci:0.1.0:bafybeidk7pqb3hr2cokhroi4sfjbbwssidkfx5lhkjuitoeb4fswhdixra +- valory/task_submission_abci:0.1.0:bafybeihluuiksi63kwp2kzn5hdbeek74bnhsctdwl72qv2xjmzqvf7j3va - valory/termination_abci:0.1.0:bafybeia73cl2vqj2uawt5lnoej3fzlhhum72i2p6ld4bbudd67lxb7f3cu - valory/transaction_settlement_abci:0.1.0:bafybeifqase6vqfrakahogdl4h2hpxntug5ckioicfqlw2og5tn6htru3q - valory/websocket_client:0.1.0:bafybeidwntmkk4b2ixq5454ycbkknclqx7a6vpn7aqpm2nw3duszqrxvta @@ -172,6 +173,7 @@ models: share_tm_config_on_startup: ${bool:false} multisend_address: ${str:0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761} service_registry_address: ${str:0x9338b5153AE39BB89f50468E608eD9d764B755fD} + service_endpoint_base: ${str:https://dummy_service.autonolas.tech/} init_fallback_gas: ${int:500000} manual_gas_limit: ${int:1000000} setup: @@ -209,3 +211,10 @@ config: chain_id: ${int:100} poa_chain: ${bool:false} default_gas_price_strategy: ${str:eip1559} +--- +public_id: valory/http_server:0.22.0:bafybeicblltx7ha3ulthg7bzfccuqqyjmihhrvfeztlgrlcoxhr7kf6nbq +type: connection +config: + host: ${str:0.0.0.0} + target_skill_id: valory/mech_abci:0.1.0 +is_abstract: true diff --git a/packages/valory/services/mech/service.yaml b/packages/valory/services/mech/service.yaml index 6df3c1c3..acdc97d9 100644 --- a/packages/valory/services/mech/service.yaml +++ b/packages/valory/services/mech/service.yaml @@ -7,7 +7,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeif7ia4jdlazy6745ke2k2x5yoqlwsgwr6sbztbgqtwvs3ndm2p7ba fingerprint_ignore_patterns: [] -agent: valory/mech:0.1.0:bafybeifw2qj6n7kwpjdhupjkcwdz4ydqur4j7744jb3vtevcucxcylpd2e +agent: valory/mech:0.1.0:bafybeiamnuotz3zj7whskv6hoieswntuobr3fowkfoh52xw4vait4b5eli number_of_agents: 4 deployment: agent: @@ -46,6 +46,7 @@ type: skill agent_mech_contract_addresses: ${AGENT_MECH_CONTRACT_ADDRESSES:list:["0xFf82123dFB52ab75C417195c5fDB87630145ae81","0x77af31De935740567Cf4fF1986D04B2c964A786a"]} manual_gas_limit: ${MANUAL_GAS_LIMIT:int:1000000} reset_period_count: ${RESET_PERIOD_COUNT:int:1000} + service_endpoint_base: ${SERVICE_ENDPOINT_BASE:str:https://dummy_service.autonolas.tech/} use_slashing: ${USE_SLASHING:bool:false} slash_cooldown_hours: ${SLASH_COOLDOWN_HOURS:int:3} slash_threshold_amount: ${SLASH_THRESHOLD_AMOUNT:int:10000000000000000} @@ -82,6 +83,7 @@ type: skill agent_registry_address: ${AGENT_REGISTRY_ADDRESS:str:0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA} agent_id: ${AGENT_ID:int:3} metadata_hash: ${METADATA_HASH:str:f01701220caa53607238e340da63b296acab232c18a48e954f0af6ff2b835b2d93f1962f0} + service_endpoint_base: ${SERVICE_ENDPOINT_BASE:str:https://dummy_service.autonolas.tech/} 2: models: params: @@ -107,6 +109,7 @@ type: skill slash_threshold_amount: ${SLASH_THRESHOLD_AMOUNT:int:10000000000000000} light_slash_unit_amount: ${LIGHT_SLASH_UNIT_AMOUNT:int:5000000000000000} serious_slash_unit_amount: ${SERIOUS_SLASH_UNIT_AMOUNT:int:8000000000000000} + service_endpoint_base: ${SERVICE_ENDPOINT_BASE:str:https://dummy_service.autonolas.tech/} agent_registry_address: ${AGENT_REGISTRY_ADDRESS:str:0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA} agent_id: ${AGENT_ID:int:3} metadata_hash: ${METADATA_HASH:str:f01701220caa53607238e340da63b296acab232c18a48e954f0af6ff2b835b2d93f1962f0} @@ -138,6 +141,7 @@ type: skill agent_registry_address: ${AGENT_REGISTRY_ADDRESS:str:0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA} agent_id: ${AGENT_ID:int:3} metadata_hash: ${METADATA_HASH:str:f01701220caa53607238e340da63b296acab232c18a48e954f0af6ff2b835b2d93f1962f0} + service_endpoint_base: ${SERVICE_ENDPOINT_BASE:str:https://dummy_service.autonolas.tech/} --- public_id: valory/task_execution:0.1.0 type: skill diff --git a/packages/valory/skills/mech_abci/handlers.py b/packages/valory/skills/mech_abci/handlers.py index 510e173b..256d5247 100644 --- a/packages/valory/skills/mech_abci/handlers.py +++ b/packages/valory/skills/mech_abci/handlers.py @@ -19,6 +19,19 @@ """This module contains the handlers for the skill of AutonomousFundAbciApp.""" +import json +import re +from datetime import datetime +from enum import Enum +from typing import Callable, Dict, List, Optional, Tuple, Union, cast +from urllib.parse import urlparse + +from aea.protocols.base import Message + +from packages.valory.connections.http_server.connection import ( + PUBLIC_ID as HTTP_SERVER_PUBLIC_ID, +) +from packages.valory.protocols.http.message import HttpMessage from packages.valory.skills.abstract_round_abci.handlers import ( ABCIRoundHandler as BaseABCIRoundHandler, ) @@ -40,12 +53,269 @@ from packages.valory.skills.abstract_round_abci.handlers import ( TendermintHandler as BaseTendermintHandler, ) +from packages.valory.skills.mech_abci.dialogues import HttpDialogue, HttpDialogues +from packages.valory.skills.task_submission_abci.models import ( + SharedState as BaseSharedState, +) +from packages.valory.skills.task_submission_abci.rounds import SynchronizedData ABCIRoundHandler = BaseABCIRoundHandler -HttpHandler = BaseHttpHandler SigningHandler = BaseSigningHandler LedgerApiHandler = BaseLedgerApiHandler ContractApiHandler = BaseContractApiHandler TendermintHandler = BaseTendermintHandler IpfsHandler = BaseIpfsHandler + + +class HttpCode(Enum): + """Http codes""" + + OK_CODE = 200 + NOT_FOUND_CODE = 404 + BAD_REQUEST_CODE = 400 + + +class HttpMethod(Enum): + """Http methods""" + + GET = "get" + HEAD = "head" + POST = "post" + + +class HttpHandler(BaseHttpHandler): + """This implements the HTTP handler.""" + + SUPPORTED_PROTOCOL = HttpMessage.protocol_id + + def setup(self) -> None: + """Implement the setup.""" + + # Custom hostname (set via params) + service_endpoint_base = urlparse( + self.context.params.service_endpoint_base + ).hostname + + # Propel hostname regex + propel_uri_base_hostname = ( + r"https?:\/\/[a-zA-Z0-9]{16}.agent\.propel\.(staging\.)?autonolas\.tech" + ) + + # Route regexes + hostname_regex = rf".*({service_endpoint_base}|{propel_uri_base_hostname}|localhost|127.0.0.1|0.0.0.0)(:\d+)?" + self.handler_url_regex = rf"{hostname_regex}\/.*" + health_url_regex = rf"{hostname_regex}\/healthcheck" + + # Routes + self.routes = { + (HttpMethod.POST.value,): [], + (HttpMethod.GET.value, HttpMethod.HEAD.value): [ + (health_url_regex, self._handle_get_health), + ], + } + + self.json_content_header = "Content-Type: application/json\n" + + @property + def synchronized_data(self) -> SynchronizedData: + """Return the synchronized data.""" + return SynchronizedData( + db=self.context.state.round_sequence.latest_synchronized_data.db + ) + + def _get_handler(self, url: str, method: str) -> Tuple[Optional[Callable], Dict]: + """Check if an url is meant to be handled in this handler + + We expect url to match the pattern {hostname}/.*, + where hostname is allowed to be localhost, 127.0.0.1 or the token_uri_base's hostname. + Examples: + localhost:8000/0 + 127.0.0.1:8000/100 + https://pfp.staging.autonolas.tech/45 + http://pfp.staging.autonolas.tech/120 + + :param url: the url to check + :param method: the http method + :returns: the handling method if the message is intended to be handled by this handler, None otherwise, and the regex captures + """ + # Check base url + if not re.match(self.handler_url_regex, url): + self.context.logger.info( + f"The url {url} does not match the HttpHandler's pattern" + ) + return None, {} + + # Check if there is a route for this request + for methods, routes in self.routes.items(): + if method not in methods: + continue + + for route in routes: # type: ignore + # Routes are tuples like (route_regex, handle_method) + m = re.match(route[0], url) + if m: + return route[1], m.groupdict() + + # No route found + self.context.logger.info( + f"The message [{method}] {url} is intended for the HttpHandler but did not match any valid pattern" + ) + return self._handle_bad_request, {} + + def handle(self, message: Message) -> None: + """ + Implement the reaction to an envelope. + + :param message: the message + """ + http_msg = cast(HttpMessage, message) + + # Check if this is a request sent from the http_server skill + if ( + http_msg.performative != HttpMessage.Performative.REQUEST + or message.sender != str(HTTP_SERVER_PUBLIC_ID.without_hash()) + ): + super().handle(message) + return + + # Check if this message is for this skill. If not, send to super() + handler, kwargs = self._get_handler(http_msg.url, http_msg.method) + if not handler: + super().handle(message) + return + + # Retrieve dialogues + http_dialogues = cast(HttpDialogues, self.context.http_dialogues) + http_dialogue = cast(HttpDialogue, http_dialogues.update(http_msg)) + + # Invalid message + if http_dialogue is None: + self.context.logger.info( + "Received invalid http message={}, unidentified dialogue.".format( + http_msg + ) + ) + return + + # Handle message + self.context.logger.info( + "Received http request with method={}, url={} and body={!r}".format( + http_msg.method, + http_msg.url, + http_msg.body, + ) + ) + handler(http_msg, http_dialogue, **kwargs) + + def _handle_bad_request( + self, http_msg: HttpMessage, http_dialogue: HttpDialogue + ) -> None: + """ + Handle a Http bad request. + + :param http_msg: the http message + :param http_dialogue: the http dialogue + """ + http_response = http_dialogue.reply( + performative=HttpMessage.Performative.RESPONSE, + target_message=http_msg, + version=http_msg.version, + status_code=HttpCode.BAD_REQUEST_CODE.value, + status_text="Bad request", + headers=http_msg.headers, + body=b"", + ) + + # Send response + self.context.logger.info("Responding with: {}".format(http_response)) + self.context.outbox.put_message(message=http_response) + + def _send_ok_response( + self, + http_msg: HttpMessage, + http_dialogue: HttpDialogue, + data: Union[Dict, List], + ) -> None: + """Send an OK response with the provided data""" + http_response = http_dialogue.reply( + performative=HttpMessage.Performative.RESPONSE, + target_message=http_msg, + version=http_msg.version, + status_code=HttpCode.OK_CODE.value, + status_text="Success", + headers=f"{self.json_content_header}{http_msg.headers}", + body=json.dumps(data).encode("utf-8"), + ) + + # Send response + self.context.logger.info("Responding with: {}".format(http_response)) + self.context.outbox.put_message(message=http_response) + + def _send_not_found_response( + self, http_msg: HttpMessage, http_dialogue: HttpDialogue + ) -> None: + """Send an not found response""" + http_response = http_dialogue.reply( + performative=HttpMessage.Performative.RESPONSE, + target_message=http_msg, + version=http_msg.version, + status_code=HttpCode.NOT_FOUND_CODE.value, + status_text="Not found", + headers=http_msg.headers, + body=b"", + ) + # Send response + self.context.logger.info("Responding with: {}".format(http_response)) + self.context.outbox.put_message(message=http_response) + + def _handle_get_health( + self, http_msg: HttpMessage, http_dialogue: HttpDialogue + ) -> None: + """ + Handle a Http request of verb GET. + + :param http_msg: the http message + :param http_dialogue: the http dialogue + """ + seconds_since_last_transition = None + is_tm_unhealthy = None + is_transitioning_fast = None + current_round = None + previous_rounds = None + + round_sequence = cast(BaseSharedState, self.context.state).round_sequence + + if round_sequence._last_round_transition_timestamp: + is_tm_unhealthy = cast( + BaseSharedState, self.context.state + ).round_sequence.block_stall_deadline_expired + + current_time = datetime.now().timestamp() + seconds_since_last_transition = current_time - datetime.timestamp( + round_sequence._last_round_transition_timestamp + ) + + is_transitioning_fast = ( + not is_tm_unhealthy + and seconds_since_last_transition + < 2 * self.context.params.reset_pause_duration + ) + + if round_sequence._abci_app: + current_round = round_sequence._abci_app.current_round.round_id + previous_rounds = [ + r.round_id for r in round_sequence._abci_app._previous_rounds[-10:] + ] + + data = { + "seconds_since_last_transition": seconds_since_last_transition, + "is_tm_healthy": not is_tm_unhealthy, + "period": self.synchronized_data.period_count, + "reset_pause_duration": self.context.params.reset_pause_duration, + "current_round": current_round, + "previous_rounds": previous_rounds, + "is_transitioning_fast": is_transitioning_fast, + } + + self._send_ok_response(http_msg, http_dialogue, data) diff --git a/packages/valory/skills/mech_abci/skill.yaml b/packages/valory/skills/mech_abci/skill.yaml index ef47697c..71608c8c 100644 --- a/packages/valory/skills/mech_abci/skill.yaml +++ b/packages/valory/skills/mech_abci/skill.yaml @@ -11,17 +11,19 @@ fingerprint: composition.py: bafybeihmtr4ddrs4eu5wkk4xmcfnytvw2lt4udcfo7cf6a46fhe6gjdn3q dialogues.py: bafybeifhydd6xmstbh2jx5igj33upip5a3hhlcaxttfsc77heszqmru7ri fsm_specification.yaml: bafybeiefcun637n44sw4htjg7qgvhkalfhsdlszbu3fg7vn6mu73eqbssq - handlers.py: bafybeiffuduhg433qsu6lbet5jsaub63bzv2l4x756aj2fbnu5bnfu4ble + handlers.py: bafybeibfsyvno2qgcftlftjmhj66aiurmcdqwfj2ac7jm44z7kwwk6illu models.py: bafybeic3pjxw7py6jpiaaxjtcufzcjmyldj2fdhpkik5qnj4hpruuxcu4q fingerprint_ignore_patterns: [] -connections: [] +connections: +- valory/http_server:0.22.0:bafybeie6g5hxhvdijyjlz4opquapxbsh6udzdjvlqhguwd6wp5cb5a5wuy contracts: [] -protocols: [] +protocols: +- valory/http:1.0.0:bafybeiejoqgv7finfxo3rcvvovrlj5ccrbgxodjq43uo26ylpowsa3llfe skills: - valory/abstract_round_abci:0.1.0:bafybeifcq2nwd6m5tgxooe7436bc6lwo73xcreedmhcwauzhp5jic6jeq4 - valory/registration_abci:0.1.0:bafybeig5fb3ibz3tr4kie53venqtajnlhvh7gwt5h45rxwzakwgs6jjsjq - valory/reset_pause_abci:0.1.0:bafybeiergfseqtmsphdimzjijxezqyyhigktvqriw2xb4dyujim6s5dr4a -- valory/task_submission_abci:0.1.0:bafybeidk7pqb3hr2cokhroi4sfjbbwssidkfx5lhkjuitoeb4fswhdixra +- valory/task_submission_abci:0.1.0:bafybeihluuiksi63kwp2kzn5hdbeek74bnhsctdwl72qv2xjmzqvf7j3va - valory/termination_abci:0.1.0:bafybeia73cl2vqj2uawt5lnoej3fzlhhum72i2p6ld4bbudd67lxb7f3cu - valory/transaction_settlement_abci:0.1.0:bafybeifqase6vqfrakahogdl4h2hpxntug5ckioicfqlw2og5tn6htru3q behaviours: @@ -160,6 +162,7 @@ models: slash_threshold_amount: 10000000000000000 light_slash_unit_amount: 5000000000000000 serious_slash_unit_amount: 8000000000000000 + service_endpoint_base: https://dummy_service.autonolas.tech/ class_name: Params randomness_api: args: diff --git a/packages/valory/skills/task_submission_abci/models.py b/packages/valory/skills/task_submission_abci/models.py index ae731bfd..aa79b666 100644 --- a/packages/valory/skills/task_submission_abci/models.py +++ b/packages/valory/skills/task_submission_abci/models.py @@ -54,6 +54,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize the parameters object.""" self.task_wait_timeout = self._ensure("task_wait_timeout", kwargs, float) + self.service_endpoint_base = self._ensure("service_endpoint_base", kwargs, str) self.multisend_address = kwargs.get("multisend_address", None) if self.multisend_address is None: raise ValueError("No multisend_address specified!") diff --git a/packages/valory/skills/task_submission_abci/skill.yaml b/packages/valory/skills/task_submission_abci/skill.yaml index 09188364..b8e65e40 100644 --- a/packages/valory/skills/task_submission_abci/skill.yaml +++ b/packages/valory/skills/task_submission_abci/skill.yaml @@ -12,7 +12,7 @@ fingerprint: dialogues.py: bafybeibmac3m5u5h6ucoyjr4dazay72dyga656wvjl6z6saapluvjo54ne fsm_specification.yaml: bafybeig6bhn554qyou7kef5bstnlv54zke32avyti63uu4hvsol3lzqkoi handlers.py: bafybeibe5n7my2vd2wlwo73sbma65epjqc7kxgtittewlylcmvnmoxtxzq - models.py: bafybeib6d45xymtpy7qhjzeb37imgtmibqqfpekd5uqqetottw6riddxtu + models.py: bafybeiantvyh3lznvrwiaim5h3ot4lnoi4sxvdej2rifum43c67l3nkl4i payloads.py: bafybeia2yorri2u5rwh6vukb6iwdrbn53ygsuuhthns2txptvjipyb6f4e rounds.py: bafybeicstmau4vlzpxz3kjgiwwsetwmotdk4un4iucmdddzvot5dgdkg2a tasks.py: bafybeicu5t5cvfhbndgpxbbtmp4vbmtyb6fba6vsnlewftvuderxp5lwcy @@ -142,6 +142,7 @@ models: slash_threshold_amount: 10000000000000000 light_slash_unit_amount: 5000000000000000 serious_slash_unit_amount: 8000000000000000 + service_endpoint_base: https://dummy_service.autonolas.tech/ class_name: Params requests: args: {} diff --git a/tox.ini b/tox.ini index 5c40b131..d9cb992f 100644 --- a/tox.ini +++ b/tox.ini @@ -53,6 +53,8 @@ deps = eth-utils==2.2.0 eth-abi==4.0.0 pycryptodome==3.18.0 + openapi-core==0.13.2 + openapi-spec-validator==0.2.8 anthropic==0.3.11 langchain==0.0.303 scikit-learn==1.3.1 @@ -63,6 +65,11 @@ deps = tiktoken==0.5.1 python-dateutil==2.8.2 +[extra-deps] +deps = + werkzeug +; end-extra + [testenv] basepython = python3 whitelist_externals = /bin/sh