From 845f06567b4c67ac60cfa37c8888a56c0d905b7c Mon Sep 17 00:00:00 2001 From: David Vilela Date: Thu, 31 Aug 2023 09:57:31 +0200 Subject: [PATCH 01/14] fix: separate latest_tweet_id --- docs/index.md | 2 +- packages/packages.json | 8 ++-- .../agents/impact_evaluator/aea-config.yaml | 4 +- .../services/impact_evaluator/service.yaml | 30 ++++++------- .../skills/impact_evaluator_abci/skill.yaml | 2 +- .../skills/twitter_scoring_abci/behaviours.py | 38 ++++++++--------- .../skills/twitter_scoring_abci/rounds.py | 42 ++++++++++++------- .../skills/twitter_scoring_abci/skill.yaml | 2 +- 8 files changed, 68 insertions(+), 60 deletions(-) diff --git a/docs/index.md b/docs/index.md index e81e76b9..e944b59e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeibxdpqanic5yizhhu6v5bbapghyktschuouywiedgq5u2l5dyj634 --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeigsgnh5bmcjjrblii6xvqtua3gbjrtgipuqxjtuthjdnw2b2smcba --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index f97c8699..e20365e5 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeianmf6g3sq3bqdmlmyjzfad6xoo6fotmhgyribrej632ye3ybpuhq", + "agent/valory/impact_evaluator/0.1.0": "bafybeiesdk2lqm2ehztq54zpj4pqmpy54tuqsndl4fl3yxyrdxhgj6mrxu", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeibxdpqanic5yizhhu6v5bbapghyktschuouywiedgq5u2l5dyj634", + "service/valory/impact_evaluator/0.1.0": "bafybeigsgnh5bmcjjrblii6xvqtua3gbjrtgipuqxjtuthjdnw2b2smcba", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeidtp3l5jzfqr5fjvwpyzk4tn7lb3m66rjomyqktfvxbwmd66bzthu", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeide5kpu6iwmwstszvzanvtgwwjw2soqhac62ynblsa4e3teweosgm", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 60bac34e..5e51599d 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeidtp3l5jzfqr5fjvwpyzk4tn7lb3m66rjomyqktfvxbwmd66bzthu +- valory/impact_evaluator_abci:0.1.0:bafybeide5kpu6iwmwstszvzanvtgwwjw2soqhac62ynblsa4e3teweosgm - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q +- valory/twitter_scoring_abci:0.1.0:bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 42d925a1..61467a24 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeianmf6g3sq3bqdmlmyjzfad6xoo6fotmhgyribrej632ye3ybpuhq +agent: valory/impact_evaluator:0.1.0:bafybeiesdk2lqm2ehztq54zpj4pqmpy54tuqsndl4fl3yxyrdxhgj6mrxu number_of_agents: 4 deployment: agent: @@ -103,11 +103,10 @@ extra: twitter_api_base: ${TWITTER_API_BASE:str:https://api.twitter.com/} twitter_api_bearer_token: ${TWITTER_API_BEARER_TOKEN:str:null} twitter_mentions_endpoint: ${TWITTER_MENTIONS_ENDPOINT:str:2/users/1450081635559428107/mentions?} - twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} - twitter_max_pages: ${TWITTER_MAX_PAGES:int:1} - max_tweet_pulls_allowed: ${MAX_TWEET_PULLS_ALLOWED:int:80} + twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} + twitter_max_pages: 10 twitter_search_endpoint: ${TWITTER_SEARCH_ENDPOINT:str:2/tweets/search/recent?} - twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} + twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} tx_timeout: 10.0 use_termination: ${USE_TERMINATION:bool:false} validate_timeout: 1205 @@ -170,11 +169,10 @@ extra: twitter_api_base: ${TWITTER_API_BASE:str:https://api.twitter.com/} twitter_api_bearer_token: ${TWITTER_API_BEARER_TOKEN:str:null} twitter_mentions_endpoint: ${TWITTER_MENTIONS_ENDPOINT:str:2/users/1450081635559428107/mentions?} - twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} - twitter_max_pages: ${TWITTER_MAX_PAGES:int:1} - max_tweet_pulls_allowed: ${MAX_TWEET_PULLS_ALLOWED:int:80} + twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} + twitter_max_pages: 10 twitter_search_endpoint: ${TWITTER_SEARCH_ENDPOINT:str:2/tweets/search/recent?} - twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} + twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} tx_timeout: 10.0 use_termination: ${USE_TERMINATION:bool:false} validate_timeout: 1205 @@ -237,11 +235,10 @@ extra: twitter_api_base: ${TWITTER_API_BASE:str:https://api.twitter.com/} twitter_api_bearer_token: ${TWITTER_API_BEARER_TOKEN:str:null} twitter_mentions_endpoint: ${TWITTER_MENTIONS_ENDPOINT:str:2/users/1450081635559428107/mentions?} - twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} - twitter_max_pages: ${TWITTER_MAX_PAGES:int:1} - max_tweet_pulls_allowed: ${MAX_TWEET_PULLS_ALLOWED:int:80} + twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} + twitter_max_pages: 10 twitter_search_endpoint: ${TWITTER_SEARCH_ENDPOINT:str:2/tweets/search/recent?} - twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} + twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} tx_timeout: 10.0 use_termination: ${USE_TERMINATION:bool:false} validate_timeout: 1205 @@ -306,11 +303,10 @@ extra: twitter_api_base: ${TWITTER_API_BASE:str:https://api.twitter.com/} twitter_api_bearer_token: ${TWITTER_API_BEARER_TOKEN:str:null} twitter_mentions_endpoint: ${TWITTER_MENTIONS_ENDPOINT:str:2/users/1450081635559428107/mentions?} - twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} - twitter_max_pages: ${TWITTER_MAX_PAGES:int:1} - max_tweet_pulls_allowed: ${MAX_TWEET_PULLS_ALLOWED:int:80} + twitter_mentions_args: ${TWITTER_MENTIONS_ARGS:str:tweet.fields=author_id&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} + twitter_max_pages: 10 twitter_search_endpoint: ${TWITTER_SEARCH_ENDPOINT:str:2/tweets/search/recent?} - twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results={max_results}&since_id={since_id}} + twitter_search_args: ${TWITTER_SEARCH_ARGS:str:query=%23olas&tweet.fields=author_id,created_at&user.fields=name&expansions=author_id&max_results=10&since_id={since_id}} tx_timeout: 10.0 use_termination: ${USE_TERMINATION:bool:false} validate_timeout: 1205 diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index a4feb313..13ab80f9 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q +- valory/twitter_scoring_abci:0.1.0:bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index cd77f589..e4be3897 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -168,6 +168,10 @@ def async_act(self) -> Generator: number_of_tweets_pulled_today, last_tweet_pull_window_reset, ) = self._check_daily_limit() + + latest_mention_tweet_id = None + latest_hashtag_tweet_id = None + if has_limit_reached: self.context.logger.info( "Cannot retrieve tweets, max number of tweets reached for today" @@ -176,43 +180,35 @@ def async_act(self) -> Generator: else: # Get mentions from Twitter ( - tweets_0, + tweets_mentions, latest_mention_tweet_id, number_of_tweets_pulled_today, ) = yield from self._get_twitter_mentions( number_of_tweets_pulled_today=number_of_tweets_pulled_today ) - tweets_1 = {} + # Get hashtags from Twitter - if tweets_0 != TwitterCollectionRound.ERROR_PAYLOAD: + tweets_hashtags = TwitterCollectionRound.ERROR_PAYLOAD # initialize + if tweets_mentions != TwitterCollectionRound.ERROR_PAYLOAD: ( - tweets_1, + tweets_hashtags, latest_hashtag_tweet_id, number_of_tweets_pulled_today, ) = yield from self._get_twitter_hashtag_search( number_of_tweets_pulled_today=number_of_tweets_pulled_today, ) - # Keep the max latest_tweet_id - valid_latest_ids = [ - i - for i in (latest_mention_tweet_id, latest_hashtag_tweet_id) - if i - ] - if valid_latest_ids: - latest_mention_tweet_id = max(valid_latest_ids) - if tweets_1 == TwitterCollectionRound.ERROR_PAYLOAD: - tweets_1 = {} - - if tweets_0 == TwitterCollectionRound.ERROR_PAYLOAD: + + if tweets_mentions == TwitterCollectionRound.ERROR_PAYLOAD or tweets_hashtags == TwitterCollectionRound.ERROR_PAYLOAD: payload_data = TwitterCollectionRound.ERROR_PAYLOAD else: - tweets = {**tweets_0, **tweets_1} + tweets = {**tweets_mentions, **tweets_hashtags} self.context.logger.info( f"Retrieved new tweets [until_id={latest_mention_tweet_id}]: {list(tweets.keys())}" ) payload_data = { "tweets": tweets, "latest_mention_tweet_id": latest_mention_tweet_id, + "latest_hashtag_tweet_id": latest_hashtag_tweet_id, "number_of_tweets_pulled_today": number_of_tweets_pulled_today, "last_tweet_pull_window_reset": last_tweet_pull_window_reset, } @@ -270,7 +266,9 @@ def _get_twitter_mentions( api_url = api_base + api_endpoint + api_args headers = dict(Authorization=f"Bearer {self.params.twitter_api_bearer_token}") - self.context.logger.info(f"Retrieving mentions from Twitter API [{api_url}]") + self.context.logger.info( + f"Retrieving mentions from Twitter API [{api_url}]\nBearer token {self.params.twitter_api_bearer_token[:5]}*******{self.params.twitter_api_bearer_token[-5:]}" + ) tweets = {} next_token = None @@ -292,7 +290,7 @@ def _get_twitter_mentions( # Check response status if response.status_code != 200: self.context.logger.error( - f"Error retrieving mentions from Twitter [{response.status_code}]" + f"Error retrieving mentions from Twitter [{response.status_code}]: {response.body}" ) return ( TwitterCollectionRound.ERROR_PAYLOAD, @@ -376,7 +374,7 @@ def _get_twitter_hashtag_search( try: latest_hashtag_tweet_id = int( self.synchronized_data.ceramic_db["module_data"]["twitter"][ - "latest_mention_tweet_id" + "latest_hashtag_tweet_id" ] ) except KeyError: diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index 5ec9de4a..c56129db 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -89,14 +89,19 @@ def latest_mention_tweet_id(self) -> dict: """Get the latest_mention_tweet_id.""" return cast(dict, self.db.get_strict("latest_mention_tweet_id")) + @property + def latest_hashtag_tweet_id(self) -> dict: + """Get the latest_hashtag_tweet_id.""" + return cast(dict, self.db.get_strict("latest_hashtag_tweet_id")) + @property def number_of_tweets_pulled_today(self) -> dict: - """Get the latest_mention_tweet_id.""" + """Get the number_of_tweets_pulled_today.""" return cast(dict, self.db.get_strict("number_of_tweets_pulled_today")) @property def last_tweet_pull_window_reset(self) -> dict: - """Get the latest_mention_tweet_id.""" + """Get the last_tweet_pull_window_reset.""" return cast(dict, self.db.get_strict("last_tweet_pull_window_reset")) @@ -157,20 +162,29 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: if not tweets: return self.synchronized_data, Event.SKIP + updates = { + get_name(SynchronizedData.tweets): tweets, + get_name(SynchronizedData.number_of_tweets_pulled_today): payload[ + "number_of_tweets_pulled_today" + ], + get_name(SynchronizedData.last_tweet_pull_window_reset): payload[ + "last_tweet_pull_window_reset" + ], + } + + if payload["latest_mention_tweet_id"]: + updates[get_name(SynchronizedData.latest_mention_tweet_id)] = payload[ + "latest_mention_tweet_id" + ] + + if payload["latest_hashtag_tweet_id"]: + updates[get_name(SynchronizedData.latest_hashtag_tweet_id)] = payload[ + "latest_hashtag_tweet_id" + ] + synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, - **{ - get_name(SynchronizedData.tweets): tweets, - get_name(SynchronizedData.latest_mention_tweet_id): payload[ - "latest_mention_tweet_id" - ], - get_name(SynchronizedData.number_of_tweets_pulled_today): payload[ - "number_of_tweets_pulled_today" - ], - get_name(SynchronizedData.last_tweet_pull_window_reset): payload[ - "last_tweet_pull_window_reset" - ], - }, + **updates, ) return synchronized_data, Event.DONE if not self.is_majority_possible( diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index c1bc6eea..2662c856 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeicucnx5gq2xrmprtjohx7murrd3gsr6hncvhaled7brc7jirvuipu + behaviours.py: bafybeidpmat2k7gdq6jtivw4dwqshoa35gb4hpmm26gdnvroqcqa2mc3ia ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si fsm_specification.yaml: bafybeietfinv3lvmyon3bk5f4gu2qf4hjlrqogfiombqnncyme5qrpbffa From 1e2af042c222e113bb8ee407b1f693a64065e0aa Mon Sep 17 00:00:00 2001 From: David Vilela Date: Thu, 31 Aug 2023 17:23:15 +0200 Subject: [PATCH 02/14] fix: split FSM --- .../tests/test_impact_evaluator.py | 6 +- .../fsm_specification.yaml | 14 +- .../skills/twitter_scoring_abci/behaviours.py | 243 +++++++++++----- .../fsm_specification.yaml | 14 +- .../skills/twitter_scoring_abci/payloads.py | 20 +- .../skills/twitter_scoring_abci/rounds.py | 267 +++++++++++++++--- .../tests/test_behaviours.py | 8 +- .../tests/test_payloads.py | 4 +- .../twitter_scoring_abci/tests/test_rounds.py | 14 +- 9 files changed, 450 insertions(+), 140 deletions(-) diff --git a/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py b/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py index 10a85626..fcbc31b4 100644 --- a/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py +++ b/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py @@ -65,14 +65,16 @@ from packages.valory.skills.generic_scoring_abci.rounds import GenericScoringRound from packages.valory.skills.registration_abci.rounds import RegistrationStartupRound from packages.valory.skills.reset_pause_abci.rounds import ResetAndPauseRound -from packages.valory.skills.twitter_scoring_abci.rounds import TwitterCollectionRound +from packages.valory.skills.twitter_scoring_abci.rounds import ( + TwitterMentionsCollectionRound, +) HAPPY_PATH: Tuple[RoundChecks, ...] = ( RoundChecks(RegistrationStartupRound.auto_round_id(), n_periods=1), RoundChecks(StreamReadRound.auto_round_id(), n_periods=3), RoundChecks(GenericScoringRound.auto_round_id(), n_periods=2), - RoundChecks(TwitterCollectionRound.auto_round_id(), n_periods=2), + RoundChecks(TwitterMentionsCollectionRound.auto_round_id(), n_periods=2), RoundChecks(TokenTrackRound.auto_round_id(), success_event="WRITE", n_periods=2), RoundChecks(RandomnessRound.auto_round_id(), n_periods=2), RoundChecks(SelectKeeperRound.auto_round_id(), n_periods=2), diff --git a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml index ce3840e0..6d8f1e9e 100644 --- a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml +++ b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml @@ -49,7 +49,7 @@ states: - StreamWriteRound - TokenTrackRound - TweetEvaluationRound -- TwitterCollectionRound +- TwitterMentionsCollectionRound - TwitterWriteRound - VerificationRound transition_func: @@ -84,7 +84,7 @@ transition_func: (LLMSelectKeeperRound, NO_MAJORITY): LLMRandomnessRound (LLMSelectKeeperRound, ROUND_TIMEOUT): LLMRandomnessRound (OpenAICallCheckRound, API_ERROR): TokenTrackRound - (OpenAICallCheckRound, DONE): TwitterCollectionRound + (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound (RandomnessRound, DONE): SelectKeeperRound (RandomnessRound, NO_MAJORITY): RandomnessRound @@ -119,11 +119,11 @@ transition_func: (TokenTrackRound, ROUND_TIMEOUT): TokenTrackRound (TweetEvaluationRound, DONE): DBUpdateRound (TweetEvaluationRound, TWEET_EVALUATION_ROUND_TIMEOUT): TweetEvaluationRound - (TwitterCollectionRound, API_ERROR): TwitterCollectionRound - (TwitterCollectionRound, DONE): TweetEvaluationRound - (TwitterCollectionRound, NO_MAJORITY): TwitterCollectionRound - (TwitterCollectionRound, ROUND_TIMEOUT): TwitterCollectionRound - (TwitterCollectionRound, SKIP): TokenTrackRound + (TwitterMentionsCollectionRound, API_ERROR): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, DONE): TweetEvaluationRound + (TwitterMentionsCollectionRound, NO_MAJORITY): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, ROUND_TIMEOUT): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, SKIP): TokenTrackRound (TwitterWriteRound, API_ERROR): RandomnessTwitterRound (TwitterWriteRound, CONTINUE): TwitterWriteRound (TwitterWriteRound, DONE): DecisionMakingRound diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index e4be3897..3a9acf83 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -51,15 +51,20 @@ DBUpdatePayload, OpenAICallCheckPayload, TweetEvaluationPayload, - TwitterCollectionPayload, + TwitterDecisionMakingPayload, + TwitterHashtagsCollectionPayload, + TwitterMentionsCollectionPayload, ) from packages.valory.skills.twitter_scoring_abci.prompts import tweet_evaluation_prompt from packages.valory.skills.twitter_scoring_abci.rounds import ( DBUpdateRound, + Event, OpenAICallCheckRound, SynchronizedData, TweetEvaluationRound, - TwitterCollectionRound, + TwitterDecisionMakingRound, + TwitterHashtagsCollectionRound, + TwitterMentionsCollectionRound, TwitterScoringAbciApp, ) @@ -90,40 +95,6 @@ def openai_calls(self) -> OpenAICalls: """Return the params.""" return self.params.openai_calls - -class OpenAICallCheckBehaviour(TwitterScoringBaseBehaviour): - """TwitterCollectionBehaviour""" - - matching_round: Type[AbstractRound] = OpenAICallCheckRound - - def async_act(self) -> Generator: - """Do the act, supporting asynchronous execution.""" - with self.context.benchmark_tool.measure(self.behaviour_id).local(): - current_time = cast( - SharedState, self.context.state - ).round_sequence.last_round_transition_timestamp.timestamp() - # Reset the window if the window expired before checking - self.openai_calls.reset(current_time=current_time) - if self.openai_calls.max_calls_reached(): - content = None - else: - content = OpenAICallCheckRound.CALLS_REMAINING - with self.context.benchmark_tool.measure(self.behaviour_id).consensus(): - yield from self.send_a2a_transaction( - payload=OpenAICallCheckPayload( - sender=self.context.agent_address, - content=content, - ) - ) - yield from self.wait_until_round_end() - self.set_done() - - -class TwitterCollectionBehaviour(TwitterScoringBaseBehaviour): - """TwitterCollectionBehaviour""" - - matching_round: Type[AbstractRound] = TwitterCollectionRound - def _check_daily_limit(self) -> Tuple: """Check if the daily limit has exceeded or not""" try: @@ -158,6 +129,89 @@ def _check_daily_limit(self) -> Tuple: # Window has not expired and we have not reached the max number of tweets return False, number_of_tweets_pulled_today, last_tweet_pull_window_reset + +class TwitterDecisionMakingBehaviour(TwitterScoringBaseBehaviour): + """TwitterDecisionMakingBehaviour""" + + matching_round: Type[AbstractRound] = TwitterDecisionMakingRound + + def async_act(self) -> Generator: + """Do the act, supporting asynchronous execution.""" + with self.context.benchmark_tool.measure(self.behaviour_id).local(): + event = self.get_next_event() + self.context.logger.info(f"Next event: {event}") + + with self.context.benchmark_tool.measure(self.behaviour_id).consensus(): + yield from self.send_a2a_transaction( + payload=TwitterDecisionMakingPayload( + sender=self.context.agent_address, + event=event, + ) + ) + yield from self.wait_until_round_end() + self.set_done() + + def get_next_event(self) -> str: + """Decide what is the next round""" + + performed_tasks = self.synchronized_data.performed_twitter_tasks + + self.context.logger.info(f"Permormed tasks: {performed_tasks}") + + if Event.OPENAI_CALL_CHECK.value not in performed_tasks: + return Event.OPENAI_CALL_CHECK.value + + if performed_tasks[Event.OPENAI_CALL_CHECK.value] == Event.NO_ALLOWANCE.value: + return Event.DONE_SKIP.value + + if Event.RETRIEVE_HASHTAGS.value not in performed_tasks: + return Event.RETRIEVE_HASHTAGS.value + + if Event.RETRIEVE_MENTIONS.value not in performed_tasks: + return Event.RETRIEVE_MENTIONS.value + + if Event.EVALUATE.value not in performed_tasks: + return Event.EVALUATE.value + + if Event.DB_UPDATE.value not in performed_tasks: + return Event.DB_UPDATE.value + + return Event.DONE.value + + +class OpenAICallCheckBehaviour(TwitterScoringBaseBehaviour): + """TwitterMentionsCollectionBehaviour""" + + matching_round: Type[AbstractRound] = OpenAICallCheckRound + + def async_act(self) -> Generator: + """Do the act, supporting asynchronous execution.""" + with self.context.benchmark_tool.measure(self.behaviour_id).local(): + current_time = cast( + SharedState, self.context.state + ).round_sequence.last_round_transition_timestamp.timestamp() + # Reset the window if the window expired before checking + self.openai_calls.reset(current_time=current_time) + if self.openai_calls.max_calls_reached(): + content = None + else: + content = OpenAICallCheckRound.CALLS_REMAINING + with self.context.benchmark_tool.measure(self.behaviour_id).consensus(): + yield from self.send_a2a_transaction( + payload=OpenAICallCheckPayload( + sender=self.context.agent_address, + content=content, + ) + ) + yield from self.wait_until_round_end() + self.set_done() + + +class TwitterMentionsCollectionBehaviour(TwitterScoringBaseBehaviour): + """TwitterMentionsCollectionBehaviour""" + + matching_round: Type[AbstractRound] = TwitterMentionsCollectionRound + def async_act(self) -> Generator: """Do the act, supporting asynchronous execution.""" @@ -169,52 +223,36 @@ def async_act(self) -> Generator: last_tweet_pull_window_reset, ) = self._check_daily_limit() - latest_mention_tweet_id = None - latest_hashtag_tweet_id = None - if has_limit_reached: self.context.logger.info( "Cannot retrieve tweets, max number of tweets reached for today" ) - payload_data = TwitterCollectionRound.ERROR_PAYLOAD + payload_data = TwitterMentionsCollectionRound.ERROR_PAYLOAD else: # Get mentions from Twitter ( - tweets_mentions, + tweets, latest_mention_tweet_id, number_of_tweets_pulled_today, ) = yield from self._get_twitter_mentions( number_of_tweets_pulled_today=number_of_tweets_pulled_today ) - # Get hashtags from Twitter - tweets_hashtags = TwitterCollectionRound.ERROR_PAYLOAD # initialize - if tweets_mentions != TwitterCollectionRound.ERROR_PAYLOAD: - ( - tweets_hashtags, - latest_hashtag_tweet_id, - number_of_tweets_pulled_today, - ) = yield from self._get_twitter_hashtag_search( - number_of_tweets_pulled_today=number_of_tweets_pulled_today, - ) - - if tweets_mentions == TwitterCollectionRound.ERROR_PAYLOAD or tweets_hashtags == TwitterCollectionRound.ERROR_PAYLOAD: - payload_data = TwitterCollectionRound.ERROR_PAYLOAD + if tweets == TwitterMentionsCollectionRound.ERROR_PAYLOAD: + payload_data = TwitterMentionsCollectionRound.ERROR_PAYLOAD else: - tweets = {**tweets_mentions, **tweets_hashtags} self.context.logger.info( - f"Retrieved new tweets [until_id={latest_mention_tweet_id}]: {list(tweets.keys())}" + f"Retrieved new mentions [until_id={latest_mention_tweet_id}]: {list(tweets.keys())}" ) payload_data = { "tweets": tweets, "latest_mention_tweet_id": latest_mention_tweet_id, - "latest_hashtag_tweet_id": latest_hashtag_tweet_id, "number_of_tweets_pulled_today": number_of_tweets_pulled_today, "last_tweet_pull_window_reset": last_tweet_pull_window_reset, } sender = self.context.agent_address - payload = TwitterCollectionPayload( + payload = TwitterMentionsCollectionPayload( sender=sender, content=json.dumps(payload_data, sort_keys=True) ) @@ -249,7 +287,7 @@ def _get_twitter_mentions( "Cannot retrieve twitter mentions, max number of tweets reached for today" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -293,7 +331,7 @@ def _get_twitter_mentions( f"Error retrieving mentions from Twitter [{response.status_code}]: {response.body}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -306,7 +344,7 @@ def _get_twitter_mentions( f"Twitter API response does not contain the required 'meta' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -324,7 +362,7 @@ def _get_twitter_mentions( f"Twitter API response does not contain the required 'meta' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -334,7 +372,7 @@ def _get_twitter_mentions( f"Twitter API response does not contain the required 'includes/users' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -363,6 +401,62 @@ def _get_twitter_mentions( return tweets, latest_tweet_id, number_of_tweets_pulled_today + +class TwitterHashtagsCollectionBehaviour(TwitterScoringBaseBehaviour): + """TwitterHashtagsCollectionBehaviour""" + + matching_round: Type[AbstractRound] = TwitterHashtagsCollectionRound + + def async_act(self) -> Generator: + """Do the act, supporting asynchronous execution.""" + + with self.context.benchmark_tool.measure(self.behaviour_id).local(): + + ( + has_limit_reached, + number_of_tweets_pulled_today, + last_tweet_pull_window_reset, + ) = self._check_daily_limit() + + if has_limit_reached: + self.context.logger.info( + "Cannot retrieve tweets, max number of tweets reached for today" + ) + payload_data = TwitterMentionsCollectionRound.ERROR_PAYLOAD + else: + # Get hashtags from Twitter + ( + tweets, + latest_hashtag_tweet_id, + number_of_tweets_pulled_today, + ) = yield from self._get_twitter_hashtag_search( + number_of_tweets_pulled_today=number_of_tweets_pulled_today + ) + + if tweets == TwitterMentionsCollectionRound.ERROR_PAYLOAD: + payload_data = TwitterMentionsCollectionRound.ERROR_PAYLOAD + else: + self.context.logger.info( + f"Retrieved new hashtags [until_id={latest_hashtag_tweet_id}]: {list(tweets.keys())}" + ) + payload_data = { + "tweets": tweets, + "latest_hashtag_tweet_id": latest_hashtag_tweet_id, + "number_of_tweets_pulled_today": number_of_tweets_pulled_today, + "last_tweet_pull_window_reset": last_tweet_pull_window_reset, + } + + sender = self.context.agent_address + payload = TwitterMentionsCollectionPayload( + sender=sender, content=json.dumps(payload_data, sort_keys=True) + ) + + with self.context.benchmark_tool.measure(self.behaviour_id).consensus(): + yield from self.send_a2a_transaction(payload) + yield from self.wait_until_round_end() + + self.set_done() + def _get_twitter_hashtag_search( self, number_of_tweets_pulled_today: int, @@ -388,7 +482,7 @@ def _get_twitter_hashtag_search( "Cannot retrieve hashtag mentions, max number of tweets reached for today" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -432,7 +526,7 @@ def _get_twitter_hashtag_search( f"Error retrieving mentions from Twitter [{response.status_code}]" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -445,7 +539,7 @@ def _get_twitter_hashtag_search( f"Twitter API response does not contain the required 'meta' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -463,7 +557,7 @@ def _get_twitter_hashtag_search( f"Twitter API response does not contain the required 'meta' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -473,7 +567,7 @@ def _get_twitter_hashtag_search( f"Twitter API response does not contain the required 'includes/users' field: {api_data!r}" ) return ( - TwitterCollectionRound.ERROR_PAYLOAD, + TwitterMentionsCollectionRound.ERROR_PAYLOAD, None, number_of_tweets_pulled_today, ) @@ -516,6 +610,9 @@ def async_act(self) -> Generator: with self.context.benchmark_tool.measure(self.behaviour_id).local(): tweet_id_to_points = {} for tweet_id, tweet in self.synchronized_data.tweets.items(): + if "points" in tweet: + # Already scored previously + continue tweet_id_to_points[tweet_id] = yield from self.evaluate_tweet( tweet["text"] ) @@ -636,6 +733,7 @@ def update_ceramic_db(self) -> Dict: tweets = self.synchronized_data.tweets latest_mention_tweet_id = self.synchronized_data.latest_mention_tweet_id + latest_hashtag_tweet_id = self.synchronized_data.latest_hashtag_tweet_id number_of_tweets_pulled_today = ( self.synchronized_data.number_of_tweets_pulled_today ) @@ -715,10 +813,15 @@ def update_ceramic_db(self) -> Dict: # entries on the database ceramic_db.merge_by_wallet() + # Update the latest_hashtag_tweet_id + ceramic_db.data["module_data"]["twitter"]["latest_hashtag_tweet_id"] = str( + latest_hashtag_tweet_id + ) # Update the latest_mention_tweet_id ceramic_db.data["module_data"]["twitter"]["latest_mention_tweet_id"] = str( latest_mention_tweet_id ) + # Update the number of tweets made today ceramic_db.data["module_data"]["twitter"][ "number_of_tweets_pulled_today" @@ -754,11 +857,11 @@ def get_registration(text: str) -> Optional[str]: class TwitterScoringRoundBehaviour(AbstractRoundBehaviour): """TwitterScoringRoundBehaviour""" - initial_behaviour_cls = TwitterCollectionBehaviour + initial_behaviour_cls = TwitterMentionsCollectionBehaviour abci_app_cls = TwitterScoringAbciApp # type: ignore behaviours: Set[Type[BaseBehaviour]] = [ OpenAICallCheckBehaviour, - TwitterCollectionBehaviour, + TwitterMentionsCollectionBehaviour, TweetEvaluationBehaviour, DBUpdateBehaviour, ] diff --git a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml index d154468a..61dd05a3 100644 --- a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml +++ b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml @@ -18,18 +18,18 @@ states: - FinishedTwitterScoringWithAPIErrorRound - OpenAICallCheckRound - TweetEvaluationRound -- TwitterCollectionRound +- TwitterMentionsCollectionRound transition_func: (DBUpdateRound, DONE): FinishedTwitterScoringRound (DBUpdateRound, NO_MAJORITY): DBUpdateRound (DBUpdateRound, ROUND_TIMEOUT): DBUpdateRound (OpenAICallCheckRound, API_ERROR): FinishedTwitterScoringWithAPIErrorRound - (OpenAICallCheckRound, DONE): TwitterCollectionRound + (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound (TweetEvaluationRound, DONE): DBUpdateRound (TweetEvaluationRound, TWEET_EVALUATION_ROUND_TIMEOUT): TweetEvaluationRound - (TwitterCollectionRound, API_ERROR): TwitterCollectionRound - (TwitterCollectionRound, DONE): TweetEvaluationRound - (TwitterCollectionRound, NO_MAJORITY): TwitterCollectionRound - (TwitterCollectionRound, ROUND_TIMEOUT): TwitterCollectionRound - (TwitterCollectionRound, SKIP): FinishedTwitterScoringRound + (TwitterMentionsCollectionRound, API_ERROR): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, DONE): TweetEvaluationRound + (TwitterMentionsCollectionRound, NO_MAJORITY): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, ROUND_TIMEOUT): TwitterMentionsCollectionRound + (TwitterMentionsCollectionRound, SKIP): FinishedTwitterScoringRound diff --git a/packages/valory/skills/twitter_scoring_abci/payloads.py b/packages/valory/skills/twitter_scoring_abci/payloads.py index 4eead7b1..7674f246 100644 --- a/packages/valory/skills/twitter_scoring_abci/payloads.py +++ b/packages/valory/skills/twitter_scoring_abci/payloads.py @@ -26,8 +26,15 @@ @dataclass(frozen=True) -class TwitterCollectionPayload(BaseTxPayload): - """Represent a transaction payload for the TwitterCollectionRound.""" +class TwitterMentionsCollectionPayload(BaseTxPayload): + """Represent a transaction payload for the TwitterMentionsCollectionRound.""" + + content: str + + +@dataclass(frozen=True) +class TwitterHashtagsCollectionPayload(BaseTxPayload): + """Represent a transaction payload for the TwitterHashtagsCollectionRound.""" content: str @@ -48,6 +55,13 @@ class DBUpdatePayload(BaseTxPayload): @dataclass(frozen=True) class OpenAICallCheckPayload(BaseTxPayload): - """Represent a transaction payload for the DBUpdateRound.""" + """Represent a transaction payload for the OpenAICallCheckRound.""" content: Optional[str] + + +@dataclass(frozen=True) +class TwitterDecisionMakingPayload(BaseTxPayload): + """Represent a transaction payload for the TwitterDecisionMakingRound.""" + + event: Optional[str] diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index c56129db..fb94021f 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -39,7 +39,9 @@ DBUpdatePayload, OpenAICallCheckPayload, TweetEvaluationPayload, - TwitterCollectionPayload, + TwitterDecisionMakingPayload, + TwitterHashtagsCollectionPayload, + TwitterMentionsCollectionPayload, ) @@ -50,11 +52,18 @@ class Event(Enum): """TwitterScoringAbciApp Events""" DONE = "done" + DONE_SKIP = "done_skip" + DONE_MAX_RETRIES = "done_max_retries" NO_MAJORITY = "no_majority" ROUND_TIMEOUT = "round_timeout" TWEET_EVALUATION_ROUND_TIMEOUT = "tweet_evaluation_round_timeout" API_ERROR = "api_error" - SKIP = "skip" + OPENAI_CALL_CHECK = "openai_call_check" + NO_ALLOWANCE = "no_allowance" + RETRIEVE_HASHTAGS = "retrieve_hashtags" + RETRIEVE_MENTIONS = "retrieve_mentions" + EVALUATE = "evaluate" + DB_UPDATE = "db_update" class SynchronizedData(BaseSynchronizedData): @@ -104,6 +113,29 @@ def last_tweet_pull_window_reset(self) -> dict: """Get the last_tweet_pull_window_reset.""" return cast(dict, self.db.get_strict("last_tweet_pull_window_reset")) + @property + def performed_twitter_tasks(self) -> dict: + """Get the twitter_tasks.""" + return cast(dict, self.db.get("performed_twitter_tasks", {})) + + +class TwitterDecisionMakingRound(CollectSameUntilThresholdRound): + """TwitterDecisionMakingRound""" + + payload_class = TwitterDecisionMakingPayload + synchronized_data_class = SynchronizedData + + def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: + """Process the end of the block.""" + if self.threshold_reached: + event = Event(self.most_voted_payload.content) + return self.synchronized_data, event + if not self.is_majority_possible( + self.collection, self.synchronized_data.nb_participants + ): + return self.synchronized_data, Event.NO_MAJORITY + return None + class OpenAICallCheckRound(CollectSameUntilThresholdRound): """OpenAICallCheckRound""" @@ -116,9 +148,38 @@ class OpenAICallCheckRound(CollectSameUntilThresholdRound): def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: """Process the end of the block.""" if self.threshold_reached: + performed_twitter_tasks = cast( + SynchronizedData, self.synchronized_data + ).performed_twitter_tasks + + # Happy path if self.most_voted_payload == self.CALLS_REMAINING: - return self.synchronized_data, Event.DONE - return self.synchronized_data, Event.API_ERROR + performed_twitter_tasks[ + Event.OPENAI_CALL_CHECK.value + ] = Event.DONE.value + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **{ + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks + }, + ) + return synchronized_data, Event.DONE + + # No allowance + performed_twitter_tasks[ + Event.OPENAI_CALL_CHECK.value + ] = Event.NO_ALLOWANCE.value + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **{ + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks + }, + ) + return synchronized_data, Event.NO_ALLOWANCE if not self.is_majority_possible( self.collection, self.synchronized_data.nb_participants ): @@ -126,10 +187,10 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: return None -class TwitterCollectionRound(CollectSameUntilThresholdRound): - """TwitterCollectionRound""" +class TwitterMentionsCollectionRound(CollectSameUntilThresholdRound): + """TwitterMentionsCollectionRound""" - payload_class = TwitterCollectionPayload + payload_class = TwitterMentionsCollectionPayload synchronized_data_class = SynchronizedData ERROR_PAYLOAD = {"error": "true"} @@ -137,6 +198,11 @@ class TwitterCollectionRound(CollectSameUntilThresholdRound): def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: """Process the end of the block.""" if self.threshold_reached: + performed_twitter_tasks = cast( + SynchronizedData, self.synchronized_data + ).performed_twitter_tasks + + # Api error if self.most_voted_payload == json.dumps( self.ERROR_PAYLOAD, sort_keys=True ): @@ -144,8 +210,21 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: cast(SynchronizedData, self.synchronized_data).api_retries + 1 ) + # Max retries if api_retries >= MAX_API_RETRIES: - return self.synchronized_data, Event.SKIP + performed_twitter_tasks[ + Event.RETRIEVE_MENTIONS.value + ] = Event.DONE_MAX_RETRIES.value + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **{ + get_name(SynchronizedData.api_retries): 0, # reset retries + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, + }, + ) + return self.synchronized_data, Event.DONE_MAX_RETRIES synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, @@ -155,21 +234,26 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: ) return synchronized_data, Event.API_ERROR + # Happy path payload = json.loads(self.most_voted_payload) - - tweets = payload["tweets"] - - if not tweets: - return self.synchronized_data, Event.SKIP + previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets + performed_twitter_tasks[Event.RETRIEVE_MENTIONS.value] = Event.DONE.value + new_tweets = payload["tweets"] updates = { - get_name(SynchronizedData.tweets): tweets, + get_name(SynchronizedData.tweets): { + **new_tweets, + **previous_tweets, + }, # order matters here: if there is duplication, keep old tweets get_name(SynchronizedData.number_of_tweets_pulled_today): payload[ "number_of_tweets_pulled_today" ], get_name(SynchronizedData.last_tweet_pull_window_reset): payload[ "last_tweet_pull_window_reset" ], + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, } if payload["latest_mention_tweet_id"]: @@ -177,6 +261,87 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: "latest_mention_tweet_id" ] + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **updates, + ) + return synchronized_data, Event.DONE + if not self.is_majority_possible( + self.collection, self.synchronized_data.nb_participants + ): + return self.synchronized_data, Event.NO_MAJORITY + return None + + +class TwitterHashtagsCollectionRound(CollectSameUntilThresholdRound): + """TwitterHashtagsCollectionRound""" + + payload_class = TwitterHashtagsCollectionPayload + synchronized_data_class = SynchronizedData + + ERROR_PAYLOAD = {"error": "true"} + + def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: + """Process the end of the block.""" + if self.threshold_reached: + performed_twitter_tasks = cast( + SynchronizedData, self.synchronized_data + ).performed_twitter_tasks + + # Api error + if self.most_voted_payload == json.dumps( + self.ERROR_PAYLOAD, sort_keys=True + ): + api_retries = ( + cast(SynchronizedData, self.synchronized_data).api_retries + 1 + ) + + # Max retries + if api_retries >= MAX_API_RETRIES: + performed_twitter_tasks[ + Event.RETRIEVE_HASHTAGS.value + ] = Event.DONE_MAX_RETRIES.value + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **{ + get_name(SynchronizedData.api_retries): 0, # reset retries + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, + }, + ) + return self.synchronized_data, Event.DONE_MAX_RETRIES + + synchronized_data = self.synchronized_data.update( + synchronized_data_class=SynchronizedData, + **{ + get_name(SynchronizedData.api_retries): api_retries, + }, + ) + return synchronized_data, Event.API_ERROR + + # Happy path + payload = json.loads(self.most_voted_payload) + previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets + performed_twitter_tasks[Event.RETRIEVE_HASHTAGS.value] = Event.DONE.value + new_tweets = payload["tweets"] + + updates = { + get_name(SynchronizedData.tweets): { + **new_tweets, + **previous_tweets, + }, # order matters here: if there is duplication, keep old tweets + get_name(SynchronizedData.number_of_tweets_pulled_today): payload[ + "number_of_tweets_pulled_today" + ], + get_name(SynchronizedData.last_tweet_pull_window_reset): payload[ + "last_tweet_pull_window_reset" + ], + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, + } + if payload["latest_hashtag_tweet_id"]: updates[get_name(SynchronizedData.latest_hashtag_tweet_id)] = payload[ "latest_hashtag_tweet_id" @@ -208,11 +373,17 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]: self.collection_threshold_reached and self.block_confirmations > self.required_block_confirmations ): + performed_twitter_tasks = cast( + SynchronizedData, self.synchronized_data + ).performed_twitter_tasks non_empty_values = self._get_non_empty_values() tweets = cast(SynchronizedData, self.synchronized_data).tweets # Calculate points average for tweet_id in tweets.keys(): + if "points" in tweets[tweet_id]: + # Already scored previously + continue tweet_points = [ json.loads(value[0])[tweet_id] for value in non_empty_values.values() @@ -221,10 +392,14 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]: tweets[tweet_id]["points"] = median print(f"Tweet {tweet_id} has been awarded {median} points") + performed_twitter_tasks[Event.EVALUATE.value] = Event.DONE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, **{ get_name(SynchronizedData.tweets): tweets, + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, }, ) @@ -245,12 +420,20 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: if self.threshold_reached: payload = json.loads(self.most_voted_payload) + performed_twitter_tasks = cast( + SynchronizedData, self.synchronized_data + ).performed_twitter_tasks + performed_twitter_tasks[Event.DB_UPDATE.value] = Event.DONE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, **{ get_name(SynchronizedData.ceramic_db): payload, get_name(SynchronizedData.pending_write): True, + get_name( + SynchronizedData.performed_twitter_tasks + ): performed_twitter_tasks, + get_name(SynchronizedData.tweets): {}, # clear tweet pool }, ) return synchronized_data, Event.DONE @@ -265,57 +448,66 @@ class FinishedTwitterScoringRound(DegenerateRound): """FinishedTwitterScoringRound""" -class FinishedTwitterScoringWithAPIErrorRound(DegenerateRound): - """FinishedTwitterScoringRound""" - - class TwitterScoringAbciApp(AbciApp[Event]): """TwitterScoringAbciApp""" - initial_round_cls: AppState = OpenAICallCheckRound - initial_states: Set[AppState] = {OpenAICallCheckRound} + initial_round_cls: AppState = TwitterDecisionMakingRound + initial_states: Set[AppState] = {TwitterDecisionMakingRound} transition_function: AbciAppTransitionFunction = { + TwitterDecisionMakingRound: { + Event.OPENAI_CALL_CHECK: OpenAICallCheckRound, + Event.DONE_SKIP: FinishedTwitterScoringRound, + Event.RETRIEVE_HASHTAGS: TwitterHashtagsCollectionRound, + Event.RETRIEVE_MENTIONS: TwitterMentionsCollectionRound, + Event.EVALUATE: TweetEvaluationRound, + Event.DB_UPDATE: DBUpdateRound, + Event.DONE: FinishedTwitterScoringRound, + Event.ROUND_TIMEOUT: TwitterDecisionMakingRound, + }, OpenAICallCheckRound: { - Event.DONE: TwitterCollectionRound, + Event.DONE: TwitterMentionsCollectionRound, + Event.NO_ALLOWANCE: TwitterMentionsCollectionRound, Event.NO_MAJORITY: OpenAICallCheckRound, - Event.API_ERROR: FinishedTwitterScoringWithAPIErrorRound, + Event.ROUND_TIMEOUT: OpenAICallCheckRound, }, - TwitterCollectionRound: { - Event.DONE: TweetEvaluationRound, - Event.API_ERROR: TwitterCollectionRound, - Event.SKIP: FinishedTwitterScoringRound, - Event.NO_MAJORITY: TwitterCollectionRound, - Event.ROUND_TIMEOUT: TwitterCollectionRound, + TwitterMentionsCollectionRound: { + Event.DONE: TwitterDecisionMakingRound, + Event.DONE_MAX_RETRIES: TwitterDecisionMakingRound, + Event.API_ERROR: TwitterMentionsCollectionRound, + Event.NO_MAJORITY: TwitterMentionsCollectionRound, + Event.ROUND_TIMEOUT: TwitterMentionsCollectionRound, + }, + TwitterHashtagsCollectionRound: { + Event.DONE: TwitterDecisionMakingRound, + Event.DONE_MAX_RETRIES: TwitterDecisionMakingRound, + Event.API_ERROR: TwitterMentionsCollectionRound, + Event.NO_MAJORITY: TwitterMentionsCollectionRound, + Event.ROUND_TIMEOUT: TwitterMentionsCollectionRound, }, TweetEvaluationRound: { - Event.DONE: DBUpdateRound, + Event.DONE: TwitterDecisionMakingRound, Event.TWEET_EVALUATION_ROUND_TIMEOUT: TweetEvaluationRound, }, DBUpdateRound: { - Event.DONE: FinishedTwitterScoringRound, + Event.DONE: TwitterDecisionMakingRound, Event.NO_MAJORITY: DBUpdateRound, Event.ROUND_TIMEOUT: DBUpdateRound, }, FinishedTwitterScoringRound: {}, - FinishedTwitterScoringWithAPIErrorRound: {}, } final_states: Set[AppState] = { FinishedTwitterScoringRound, - FinishedTwitterScoringWithAPIErrorRound, } event_to_timeout: EventToTimeout = { Event.ROUND_TIMEOUT: 30.0, Event.TWEET_EVALUATION_ROUND_TIMEOUT: 600.0, } cross_period_persisted_keys: FrozenSet[str] = frozenset( - [ - "ceramic_db", - "pending_write", - ] + ["ceramic_db", "pending_write", "tweets"] ) db_pre_conditions: Dict[AppState, Set[str]] = { OpenAICallCheckRound: set(), - TwitterCollectionRound: set(), + TwitterMentionsCollectionRound: set(), TweetEvaluationRound: set(), DBUpdateRound: set(), } @@ -323,5 +515,4 @@ class TwitterScoringAbciApp(AbciApp[Event]): FinishedTwitterScoringRound: { get_name(SynchronizedData.ceramic_db), }, - FinishedTwitterScoringWithAPIErrorRound: set(), } diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py index 74b2dd1b..2e0a93a9 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py @@ -34,7 +34,7 @@ from packages.valory.skills.twitter_scoring_abci.behaviours import ( TAGLINE, TweetEvaluationBehaviour, - TwitterCollectionBehaviour, + TwitterMentionsCollectionBehaviour, TwitterScoringBaseBehaviour, TwitterScoringRoundBehaviour, ) @@ -295,7 +295,7 @@ def complete(self, event: Event) -> None: class TestTwitterCollectionBehaviour(BaseBehaviourTest): """Tests BinanceObservationBehaviour""" - behaviour_class = TwitterCollectionBehaviour + behaviour_class = TwitterMentionsCollectionBehaviour next_behaviour_class = TweetEvaluationBehaviour @pytest.mark.parametrize( @@ -431,8 +431,8 @@ def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: class TestTwitterCollectionBehaviourAPIError(BaseBehaviourTest): """Tests BinanceObservationBehaviour""" - behaviour_class = TwitterCollectionBehaviour - next_behaviour_class = TwitterCollectionBehaviour + behaviour_class = TwitterMentionsCollectionBehaviour + next_behaviour_class = TwitterMentionsCollectionBehaviour @pytest.mark.parametrize( "test_case, kwargs", diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py index 837fb11a..a7866d08 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py @@ -28,7 +28,7 @@ from packages.valory.skills.twitter_scoring_abci.payloads import ( DBUpdatePayload, TweetEvaluationPayload, - TwitterCollectionPayload, + TwitterMentionsCollectionPayload, ) @@ -44,7 +44,7 @@ class PayloadTestCase: "test_case", [ PayloadTestCase( - payload_cls=TwitterCollectionPayload, + payload_cls=TwitterMentionsCollectionPayload, content="payload_test_content", ), PayloadTestCase( diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py index 0b566c72..52aa1c63 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py @@ -41,12 +41,12 @@ CollectSameUntilThresholdRound, ) from packages.valory.skills.twitter_scoring_abci.payloads import ( - TwitterCollectionPayload, + TwitterMentionsCollectionPayload, ) from packages.valory.skills.twitter_scoring_abci.rounds import ( Event, SynchronizedData, - TwitterCollectionRound, + TwitterMentionsCollectionRound, ) @@ -129,9 +129,9 @@ def run_test(self, test_case: RoundTestCase) -> None: class TestTwitterCollectionRound(BaseScoreReadRoundTest): - """Tests for TwitterCollectionRound.""" + """Tests for TwitterMentionsCollectionRound.""" - round_class = TwitterCollectionRound + round_class = TwitterMentionsCollectionRound @pytest.mark.parametrize( "test_case", @@ -140,7 +140,7 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): name="Happy path", initial_data={"ceramic_db": {}}, payloads=get_payloads( - payload_cls=TwitterCollectionPayload, + payload_cls=TwitterMentionsCollectionPayload, data=get_dummy_twitter_collection_payload_serialized(), ), final_data={ @@ -158,7 +158,7 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): name="API error", initial_data={}, payloads=get_payloads( - payload_cls=TwitterCollectionPayload, + payload_cls=TwitterMentionsCollectionPayload, data=get_dummy_twitter_collection_payload_serialized( api_error=True ), @@ -176,7 +176,7 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): "api_retries": 2, }, payloads=get_payloads( - payload_cls=TwitterCollectionPayload, + payload_cls=TwitterMentionsCollectionPayload, data=get_dummy_twitter_collection_payload_serialized( api_error=True ), From d6cfae6c92810c8165269dd1a9ff580fca305815 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Thu, 31 Aug 2023 18:26:41 +0200 Subject: [PATCH 03/14] fix: tests --- .../impact_evaluator_abci/composition.py | 3 +- .../skills/twitter_scoring_abci/behaviours.py | 2 + .../skills/twitter_scoring_abci/payloads.py | 2 +- .../skills/twitter_scoring_abci/rounds.py | 13 +- .../tests/test_behaviours.py | 238 +++++++++++++----- .../tests/test_payloads.py | 11 + .../twitter_scoring_abci/tests/test_rounds.py | 2 +- 7 files changed, 194 insertions(+), 77 deletions(-) diff --git a/packages/valory/skills/impact_evaluator_abci/composition.py b/packages/valory/skills/impact_evaluator_abci/composition.py index 508cd3b3..817125d7 100644 --- a/packages/valory/skills/impact_evaluator_abci/composition.py +++ b/packages/valory/skills/impact_evaluator_abci/composition.py @@ -51,9 +51,8 @@ DecisionMakingAbci.FinishedDecisionMakingReadManualPointsRound: CeramicReadAbci.StreamReadRound, DecisionMakingAbci.FinishedDecisionMakingScoreRound: GenericScoringAbci.GenericScoringRound, DecisionMakingAbci.FinishedDecisionMakingDoneRound: ResetAndPauseAbci.ResetAndPauseRound, - GenericScoringAbci.FinishedGenericScoringRound: TwitterScoringAbci.OpenAICallCheckRound, + GenericScoringAbci.FinishedGenericScoringRound: TwitterScoringAbci.TwitterDecisionMakingRound, TwitterScoringAbci.FinishedTwitterScoringRound: DynamicNFTAbci.TokenTrackRound, - TwitterScoringAbci.FinishedTwitterScoringWithAPIErrorRound: DynamicNFTAbci.TokenTrackRound, DynamicNFTAbci.FinishedTokenTrackRound: DecisionMakingAbci.DecisionMakingRound, LLMAbciApp.FinishedLLMRound: DecisionMakingAbci.DecisionMakingRound, TwitterWriteAbciApp.FinishedTwitterWriteRound: DecisionMakingAbci.DecisionMakingRound, diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index 3a9acf83..3bf654b0 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -860,8 +860,10 @@ class TwitterScoringRoundBehaviour(AbstractRoundBehaviour): initial_behaviour_cls = TwitterMentionsCollectionBehaviour abci_app_cls = TwitterScoringAbciApp # type: ignore behaviours: Set[Type[BaseBehaviour]] = [ + TwitterDecisionMakingBehaviour, OpenAICallCheckBehaviour, TwitterMentionsCollectionBehaviour, + TwitterHashtagsCollectionBehaviour, TweetEvaluationBehaviour, DBUpdateBehaviour, ] diff --git a/packages/valory/skills/twitter_scoring_abci/payloads.py b/packages/valory/skills/twitter_scoring_abci/payloads.py index 7674f246..3b70298f 100644 --- a/packages/valory/skills/twitter_scoring_abci/payloads.py +++ b/packages/valory/skills/twitter_scoring_abci/payloads.py @@ -64,4 +64,4 @@ class OpenAICallCheckPayload(BaseTxPayload): class TwitterDecisionMakingPayload(BaseTxPayload): """Represent a transaction payload for the TwitterDecisionMakingRound.""" - event: Optional[str] + event: str diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index fb94021f..8214c7ab 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -91,7 +91,7 @@ def api_retries(self) -> int: @property def tweets(self) -> dict: """Get the tweets.""" - return cast(dict, self.db.get_strict("tweets")) + return cast(dict, self.db.get("tweets", {})) @property def latest_mention_tweet_id(self) -> dict: @@ -480,9 +480,9 @@ class TwitterScoringAbciApp(AbciApp[Event]): TwitterHashtagsCollectionRound: { Event.DONE: TwitterDecisionMakingRound, Event.DONE_MAX_RETRIES: TwitterDecisionMakingRound, - Event.API_ERROR: TwitterMentionsCollectionRound, - Event.NO_MAJORITY: TwitterMentionsCollectionRound, - Event.ROUND_TIMEOUT: TwitterMentionsCollectionRound, + Event.API_ERROR: TwitterHashtagsCollectionRound, + Event.NO_MAJORITY: TwitterHashtagsCollectionRound, + Event.ROUND_TIMEOUT: TwitterHashtagsCollectionRound, }, TweetEvaluationRound: { Event.DONE: TwitterDecisionMakingRound, @@ -506,10 +506,7 @@ class TwitterScoringAbciApp(AbciApp[Event]): ["ceramic_db", "pending_write", "tweets"] ) db_pre_conditions: Dict[AppState, Set[str]] = { - OpenAICallCheckRound: set(), - TwitterMentionsCollectionRound: set(), - TweetEvaluationRound: set(), - DBUpdateRound: set(), + TwitterDecisionMakingRound: set(), } db_post_conditions: Dict[AppState, Set[str]] = { FinishedTwitterScoringRound: { diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py index 2e0a93a9..499d69fb 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py @@ -34,6 +34,8 @@ from packages.valory.skills.twitter_scoring_abci.behaviours import ( TAGLINE, TweetEvaluationBehaviour, + TwitterDecisionMakingBehaviour, + TwitterHashtagsCollectionBehaviour, TwitterMentionsCollectionBehaviour, TwitterScoringBaseBehaviour, TwitterScoringRoundBehaviour, @@ -262,6 +264,10 @@ class BaseBehaviourTest(FSMBehaviourBaseCase): synchronized_data: SynchronizedData done_event = Event.DONE + @classmethod + def setup_class(cls, **kwargs: Any) -> None: + super().setup_class(param_overrides={"twitter_max_pages": 10}) + def fast_forward(self, data: Optional[Dict[str, Any]] = None) -> None: """Fast-forward on initialization""" @@ -292,11 +298,11 @@ def complete(self, event: Event) -> None: ) -class TestTwitterCollectionBehaviour(BaseBehaviourTest): +class TestMentionsCollectionBehaviour(BaseBehaviourTest): """Tests BinanceObservationBehaviour""" behaviour_class = TwitterMentionsCollectionBehaviour - next_behaviour_class = TweetEvaluationBehaviour + next_behaviour_class = TwitterDecisionMakingBehaviour @pytest.mark.parametrize( "test_case, kwargs", @@ -310,28 +316,17 @@ class TestTwitterCollectionBehaviour(BaseBehaviourTest): { "request_urls": [ TWITTER_MENTIONS_URL.format(max_results=80), - TWITTER_REGISTRATIONS_URL.format(max_results=76), ], "request_headers": [ "Authorization: Bearer \r\n", - "Authorization: Bearer \r\n", - "", ], "response_urls": [ "", - "", - "https://www.autonolas.network/whitepaper", ], "response_bodies": [ json.dumps( DUMMY_MENTIONS_RESPONSE, ), - json.dumps( - DUMMY_REGISTRATIONS_RESPONSE, - ), - json.dumps( - {}, - ), ], "status_code": 200, }, @@ -345,20 +340,14 @@ class TestTwitterCollectionBehaviour(BaseBehaviourTest): { "request_urls": [ TWITTER_MENTIONS_URL.format(max_results=80), - # skipped temporarily since we're not fetching more then one page atm - # TWITTER_MENTIONS_URL.format(max_results=80) # noqa: E800 - # + "&pagination_token=dummy_next_token", # noqa: E800 - TWITTER_REGISTRATIONS_URL.format(max_results=76), - # TWITTER_REGISTRATIONS_URL.format(max_results=72) # noqa: E800 - # + "&pagination_token=dummy_next_token", # noqa: E800 + TWITTER_MENTIONS_URL.format(max_results=80) + + "&pagination_token=dummy_next_token", ], "request_headers": [ "Authorization: Bearer \r\n", "Authorization: Bearer \r\n", - "Authorization: Bearer \r\n", - "Authorization: Bearer \r\n", ], - "response_urls": ["", "", "", ""], + "response_urls": ["", ""], "response_bodies": [ json.dumps( DUMMY_MENTIONS_RESPONSE_MULTIPAGE, @@ -366,11 +355,86 @@ class TestTwitterCollectionBehaviour(BaseBehaviourTest): json.dumps( DUMMY_MENTIONS_RESPONSE, ), + ], + "status_code": 200, + }, + ), + ( + BehaviourTestCase( + "Happy path, result_count=0", + initial_data=dict(ceramic_db={}), + event=Event.DONE, + ), + { + "request_urls": [ + TWITTER_MENTIONS_URL.format(max_results=80), + ], + "request_headers": [ + "Authorization: Bearer \r\n", + ], + "response_urls": [""], + "response_bodies": [ json.dumps( - DUMMY_REGISTRATIONS_RESPONSE_MULTIPAGE, + DUMMY_MENTIONS_RESPONSE_COUNT_ZERO, ), + ], + "status_code": 200, + }, + ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: + """Run tests.""" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + for i in range(len(kwargs.get("request_urls"))): + self.mock_http_request( + request_kwargs=dict( + method="GET", + headers=kwargs.get("request_headers")[i], + version="", + url=kwargs.get("request_urls")[i], + ), + response_kwargs=dict( + version="", + status_code=kwargs.get("status_code"), + status_text="", + body=kwargs.get("response_bodies")[i].encode(), + url=kwargs.get("response_urls")[i], + ), + ) + self.complete(test_case.event) + + +class TestHashtagsCollectionBehaviour(BaseBehaviourTest): + """Tests BinanceObservationBehaviour""" + + behaviour_class = TwitterHashtagsCollectionBehaviour + next_behaviour_class = TwitterDecisionMakingBehaviour + + @pytest.mark.parametrize( + "test_case, kwargs", + [ + ( + BehaviourTestCase( + "Happy path", + initial_data=dict(ceramic_db={}), + event=Event.DONE, + ), + { + "request_urls": [ + TWITTER_REGISTRATIONS_URL.format(max_results=80), + ], + "request_headers": [ + "Authorization: Bearer \r\n", + "", + ], + "response_urls": [ + "", + ], + "response_bodies": [ json.dumps( - DUMMY_REGISTRATIONS_RESPONSE_MULTIPAGE_2, + DUMMY_REGISTRATIONS_RESPONSE, ), ], "status_code": 200, @@ -378,14 +442,15 @@ class TestTwitterCollectionBehaviour(BaseBehaviourTest): ), ( BehaviourTestCase( - "Happy path, result_count=0", + "Happy path, multi-page", initial_data=dict(ceramic_db={}), event=Event.DONE, ), { "request_urls": [ - TWITTER_MENTIONS_URL.format(max_results=80), TWITTER_REGISTRATIONS_URL.format(max_results=80), + TWITTER_REGISTRATIONS_URL.format(max_results=80) + + "&pagination_token=dummy_next_token", ], "request_headers": [ "Authorization: Bearer \r\n", @@ -394,8 +459,30 @@ class TestTwitterCollectionBehaviour(BaseBehaviourTest): "response_urls": ["", ""], "response_bodies": [ json.dumps( - DUMMY_MENTIONS_RESPONSE_COUNT_ZERO, + DUMMY_REGISTRATIONS_RESPONSE_MULTIPAGE, + ), + json.dumps( + DUMMY_REGISTRATIONS_RESPONSE_MULTIPAGE_2, ), + ], + "status_code": 200, + }, + ), + ( + BehaviourTestCase( + "Happy path, result_count=0", + initial_data=dict(ceramic_db={}), + event=Event.DONE, + ), + { + "request_urls": [ + TWITTER_REGISTRATIONS_URL.format(max_results=80), + ], + "request_headers": [ + "Authorization: Bearer \r\n", + ], + "response_urls": ["", ""], + "response_bodies": [ json.dumps( DUMMY_REGISTRATIONS_RESPONSE_COUNT_ZERO, ), @@ -428,7 +515,7 @@ def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: self.complete(test_case.event) -class TestTwitterCollectionBehaviourAPIError(BaseBehaviourTest): +class TestMentionsCollectionBehaviourAPIError(BaseBehaviourTest): """Tests BinanceObservationBehaviour""" behaviour_class = TwitterMentionsCollectionBehaviour @@ -456,27 +543,24 @@ class TestTwitterCollectionBehaviourAPIError(BaseBehaviourTest): ), ( BehaviourTestCase( - "API error registrations: 404", + "API error mentions: missing data", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), { - "urls": [ - TWITTER_MENTIONS_URL.format(max_results=80), - TWITTER_REGISTRATIONS_URL.format(max_results=76), - ], + "urls": [TWITTER_MENTIONS_URL.format(max_results=80)], "bodies": [ json.dumps( - DUMMY_MENTIONS_RESPONSE, + DUMMY_MENTIONS_RESPONSE_MISSING_DATA, ), json.dumps(DUMMY_HASHTAGS_RESPONSE), ], - "status_codes": [200, 404], + "status_codes": [200], }, ), ( BehaviourTestCase( - "API error mentions: missing data", + "API error mentions: missing meta", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), @@ -484,7 +568,7 @@ class TestTwitterCollectionBehaviourAPIError(BaseBehaviourTest): "urls": [TWITTER_MENTIONS_URL.format(max_results=80)], "bodies": [ json.dumps( - DUMMY_MENTIONS_RESPONSE_MISSING_DATA, + DUMMY_MENTIONS_RESPONSE_MISSING_META, ), json.dumps(DUMMY_HASHTAGS_RESPONSE), ], @@ -493,76 +577,100 @@ class TestTwitterCollectionBehaviourAPIError(BaseBehaviourTest): ), ( BehaviourTestCase( - "API error registrations: missing data", + "API error mentions: missing includes", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), { - "urls": [ - TWITTER_MENTIONS_URL.format(max_results=80), - TWITTER_REGISTRATIONS_URL.format(max_results=76), - ], + "urls": [TWITTER_MENTIONS_URL.format(max_results=80)], "bodies": [ json.dumps( - DUMMY_MENTIONS_RESPONSE, - ), - json.dumps( - DUMMY_REGISTRATIONS_RESPONSE_MISSING_DATA, + DUMMY_MENTIONS_RESPONSE_MISSING_INCLUDES, ), + json.dumps({}), ], - "status_codes": [200, 200], + "status_codes": [200], }, ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: + """Run tests.""" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + for i in range(len(kwargs.get("urls"))): + self.mock_http_request( + request_kwargs=dict( + method="GET", + headers="Authorization: Bearer \r\n", + version="", + url=kwargs.get("urls")[i], + ), + response_kwargs=dict( + version="", + status_code=kwargs.get("status_codes")[i], + status_text="", + body=kwargs.get("bodies")[i].encode(), + ), + ) + self.complete(test_case.event) + + +class TestHashtagsCollectionBehaviourAPIError(BaseBehaviourTest): + """Tests BinanceObservationBehaviour""" + + behaviour_class = TwitterHashtagsCollectionBehaviour + next_behaviour_class = TwitterHashtagsCollectionBehaviour + + @pytest.mark.parametrize( + "test_case, kwargs", + [ ( BehaviourTestCase( - "API error mentions: missing meta", + "API error registrations: 404", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), { - "urls": [TWITTER_MENTIONS_URL.format(max_results=80)], + "urls": [ + TWITTER_REGISTRATIONS_URL.format(max_results=80), + ], "bodies": [ - json.dumps( - DUMMY_MENTIONS_RESPONSE_MISSING_META, - ), json.dumps(DUMMY_HASHTAGS_RESPONSE), ], - "status_codes": [200], + "status_codes": [404], }, ), ( BehaviourTestCase( - "API error registrations: missing meta", + "API error registrations: missing data", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), { "urls": [ - TWITTER_MENTIONS_URL.format(max_results=80), - TWITTER_REGISTRATIONS_URL.format(max_results=76), + TWITTER_REGISTRATIONS_URL.format(max_results=80), ], "bodies": [ json.dumps( - DUMMY_MENTIONS_RESPONSE, + DUMMY_REGISTRATIONS_RESPONSE_MISSING_DATA, ), - json.dumps(DUMMY_REGISTRATIONS_RESPONSE_MISSING_META), ], - "status_codes": [200, 200], + "status_codes": [200], }, ), ( BehaviourTestCase( - "API error mentions: missing includes", + "API error registrations: missing meta", initial_data=dict(ceramic_db={}), event=Event.API_ERROR, ), { - "urls": [TWITTER_MENTIONS_URL.format(max_results=80)], + "urls": [ + TWITTER_REGISTRATIONS_URL.format(max_results=80), + ], "bodies": [ - json.dumps( - DUMMY_MENTIONS_RESPONSE_MISSING_INCLUDES, - ), - json.dumps({}), + json.dumps(DUMMY_REGISTRATIONS_RESPONSE_MISSING_META), ], "status_codes": [200], }, diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py index a7866d08..d2c2c76b 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py @@ -27,7 +27,10 @@ from packages.valory.skills.abstract_round_abci.base import BaseTxPayload from packages.valory.skills.twitter_scoring_abci.payloads import ( DBUpdatePayload, + OpenAICallCheckPayload, TweetEvaluationPayload, + TwitterDecisionMakingPayload, + TwitterHashtagsCollectionPayload, TwitterMentionsCollectionPayload, ) @@ -47,6 +50,10 @@ class PayloadTestCase: payload_cls=TwitterMentionsCollectionPayload, content="payload_test_content", ), + PayloadTestCase( + payload_cls=TwitterHashtagsCollectionPayload, + content="payload_test_content", + ), PayloadTestCase( payload_cls=TweetEvaluationPayload, content="payload_test_content", @@ -55,6 +62,10 @@ class PayloadTestCase: payload_cls=DBUpdatePayload, content="payload_test_content", ), + PayloadTestCase( + payload_cls=OpenAICallCheckPayload, + content="payload_test_content", + ), ], ) def test_payloads(test_case: PayloadTestCase) -> None: diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py index 52aa1c63..0982c231 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py @@ -182,7 +182,7 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): ), ), final_data={}, - event=Event.SKIP, + event=Event.DONE_MAX_RETRIES, most_voted_payload=get_dummy_twitter_collection_payload_serialized( api_error=True ), From a7d533c350ea5ece03132dac880fbd48e2ffa607 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Fri, 1 Sep 2023 13:54:24 +0200 Subject: [PATCH 04/14] test: coverage --- docs/index.md | 2 +- packages/packages.json | 8 +- .../agents/impact_evaluator/aea-config.yaml | 6 +- .../services/impact_evaluator/service.yaml | 2 +- .../skills/impact_evaluator_abci/skill.yaml | 6 +- .../skills/twitter_scoring_abci/rounds.py | 2 +- .../skills/twitter_scoring_abci/skill.yaml | 14 +- .../twitter_scoring_abci/tests/test_rounds.py | 266 +++++++++++++++++- 8 files changed, 277 insertions(+), 29 deletions(-) diff --git a/docs/index.md b/docs/index.md index e944b59e..ade52a44 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeigsgnh5bmcjjrblii6xvqtua3gbjrtgipuqxjtuthjdnw2b2smcba --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeidqybwdwxzlilnwautwvphmh33ieqmfa5vf3glg42dwfaivhd2owu --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index e20365e5..034b1d39 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeiesdk2lqm2ehztq54zpj4pqmpy54tuqsndl4fl3yxyrdxhgj6mrxu", + "agent/valory/impact_evaluator/0.1.0": "bafybeidvlhkzx6fk6c655rlk4uy46kcb6jqwllbp4rkzyeqnlq7bbnp6iu", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeigsgnh5bmcjjrblii6xvqtua3gbjrtgipuqxjtuthjdnw2b2smcba", + "service/valory/impact_evaluator/0.1.0": "bafybeidqybwdwxzlilnwautwvphmh33ieqmfa5vf3glg42dwfaivhd2owu", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeide5kpu6iwmwstszvzanvtgwwjw2soqhac62ynblsa4e3teweosgm", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeic6w4gw2wghfs73hmeahhjd5jtaam7y4lpuosz3l43fygkykw4vay", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 5e51599d..f96f9677 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -12,7 +12,7 @@ fingerprint: tests/helpers/data/json_server/data.json: bafybeif5wzdnb4qdo4mjxcn6f7m57n7p4jmr5lmfxlthrvewyi6mfczonq tests/helpers/docker.py: bafybeihlg5thdrcaiuzyte5s7x25mikqfyxdjwuqvhmeddluyjdkzhuhqi tests/helpers/fixtures.py: bafybeidfsamzdrqqkdra4ektollyfkhiyb2iqymy6djavgewon2cb23vwu - tests/test_impact_evaluator.py: bafybeicbhyvk4lbsckrywfhmd5lpqx76kbg4kszqpcsbd55n7letxolbae + tests/test_impact_evaluator.py: bafybeifxqu7dim3homzpzsglicv26tkevbjhcmdmlmv7dxws6uuiwpz54u fingerprint_ignore_patterns: [] connections: - fetchai/http_server:0.22.0:bafybeihp5umafxzx45aad5pj7s3343se2wjkgnbirt4pybrape22swm6de @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeide5kpu6iwmwstszvzanvtgwwjw2soqhac62ynblsa4e3teweosgm +- valory/impact_evaluator_abci:0.1.0:bafybeic6w4gw2wghfs73hmeahhjd5jtaam7y4lpuosz3l43fygkykw4vay - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi +- valory/twitter_scoring_abci:0.1.0:bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 61467a24..791b1000 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeiesdk2lqm2ehztq54zpj4pqmpy54tuqsndl4fl3yxyrdxhgj6mrxu +agent: valory/impact_evaluator:0.1.0:bafybeidvlhkzx6fk6c655rlk4uy46kcb6jqwllbp4rkzyeqnlq7bbnp6iu number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index 13ab80f9..fa7c83e9 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -8,9 +8,9 @@ aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeigmhxenrqb2ysjhcm2au2lang4abyny6irkzqqg4dtclz6net6zpy behaviours.py: bafybeifhoufesr4r4re65mxjadqasjymvz6tkc25xn5yyn473yunhjiufe - composition.py: bafybeicjgndv2v43wclaoldmhpgugajsutqjfbhwbw67cmrli7z3eqpxne + composition.py: bafybeifmf52jhbiyyqyxzd67gxrydedm44ouzib3jh56kzoe5xohjrhm34 dialogues.py: bafybeigjknz4qqynbsltjje46gidg4rftsqw6ybjwegz24wetmycutpzh4 - fsm_specification.yaml: bafybeibqudgc2r4n4maicfi3mchfqaznw6evy4iyg7keuezkub7dl6zlvq + fsm_specification.yaml: bafybeifn6z5zeowyd4seaqgywseeqwpdj332rj2dg4bwpmd7dtzedsvtdy handlers.py: bafybeidkli6fphcmdgwsys4lkyf3fx6fbawet4nt2pnixfypzijhg6b3ze models.py: bafybeifhcshu4iwqvc2fz3auu5ngfykkhvqnroeug52ilrwwc4kowkeg5a tests/__init__.py: bafybeievwzwojvq4aofk5kjpf4jzygfes7ew6s6svc6b6frktjnt3sicce @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiafl5igfirbenlu6kcobjn4c3dcvc5eq6dgzihmhtgk6obp75i6pi +- valory/twitter_scoring_abci:0.1.0:bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index 8214c7ab..0a40bbd3 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -128,7 +128,7 @@ class TwitterDecisionMakingRound(CollectSameUntilThresholdRound): def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: """Process the end of the block.""" if self.threshold_reached: - event = Event(self.most_voted_payload.content) + event = Event(self.most_voted_payload) return self.synchronized_data, event if not self.is_majority_possible( self.collection, self.synchronized_data.nb_participants diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 2662c856..635b9796 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,23 +8,23 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeidpmat2k7gdq6jtivw4dwqshoa35gb4hpmm26gdnvroqcqa2mc3ia + behaviours.py: bafybeihcbk3lgo5bj6efudg5kmrmbqrqbe5vldob6kikov67oozcutcxeu ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si - fsm_specification.yaml: bafybeietfinv3lvmyon3bk5f4gu2qf4hjlrqogfiombqnncyme5qrpbffa + fsm_specification.yaml: bafybeiegd4eodewbip6l7mcw44kxgzvuwg4jljacokb3eayud7dxcygjqe handlers.py: bafybeid3nqvcyotqj5g5hlgrz57nf7vpjysmgvsxe3p7644f4z5dcwqn6u models.py: bafybeihqlxg6tbkpkjr5kfdcxwopykvoimczfn22q3owlzgw2elsg76cf4 - payloads.py: bafybeic2fwq4n37ciytg7smpns35kww4tvg7kpcy3tmzkrtegjdpqb63iq + payloads.py: bafybeihzjioqknhekm7fzlhl52iklkwzuuht6w2qqk5ptutv5s2wqtoedy prompts.py: bafybeieiuqn427bgwfnzynxf3vtqfpvmqqscs5tyw4oibfofwropifotke - rounds.py: bafybeid3fqad3e6vlo5whytjckocpcm5qn2ro2iahbxvwaohfx5imshqly + rounds.py: bafybeifjf4doesl3ntu32fm7qycm4nwttsobryzimjk5fvlnnmxjb67mzu tests/__init__.py: bafybeidwzzd4ejsyf3aryd5kmrvd63h7ajgqyrxphmfaacvpjnneacejay - tests/test_behaviours.py: bafybeihrqdjgsu7kwz4hlbtyx3yspo4n7nvifzfcgwb7d4k6p4qkboaz4i + tests/test_behaviours.py: bafybeidfcoz3sbgr2hcgjtettjfmqqsh5pt32tyn4necjp4npgjjskdzcu tests/test_ceramic_db.py: bafybeif2v7btjphbqabq6qdmfeyweg765seon74acg5vrrvznivzg2prey tests/test_dialogues.py: bafybeiheyq7klonzb7rnjub2i22h7bmsnoimn2pq4j7ofikt3yovstvgt4 tests/test_handlers.py: bafybeigevirvi3saepukke2zmp334btgsdxhj55o2vawj3hqam63miirg4 tests/test_models.py: bafybeihaiirqmcsshghztl5lvqjzem6y6rdeefhtiycrhh45v7cuwnmdz4 - tests/test_payloads.py: bafybeigw2hvezl72maasvxkctqhm4sywzoytwksmijrhxaits45dxot3ia - tests/test_rounds.py: bafybeidylkvo4ltqkhxkdexpglbypgysq5ehmcryoclm25i3wstkaguz7e + tests/test_payloads.py: bafybeie3herufgeyupdxwi6bhcs3gbqwhsypn4ujaqnhe3myj6ezckdu4q + tests/test_rounds.py: bafybeibdrk4okn3fqatl56udkjdlanpleqajylhp2sysw64ji472uxjczy fingerprint_ignore_patterns: [] connections: - valory/openai:0.1.0:bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py index 0982c231..37e07c70 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py @@ -37,15 +37,27 @@ from packages.valory.skills.abstract_round_abci.base import BaseTxPayload from packages.valory.skills.abstract_round_abci.test_tools.rounds import ( + BaseCollectNonEmptyUntilThresholdRound, BaseCollectSameUntilThresholdRoundTest, + CollectDifferentUntilThresholdRound, CollectSameUntilThresholdRound, ) from packages.valory.skills.twitter_scoring_abci.payloads import ( + DBUpdatePayload, + OpenAICallCheckPayload, + TweetEvaluationPayload, + TwitterDecisionMakingPayload, + TwitterHashtagsCollectionPayload, TwitterMentionsCollectionPayload, ) from packages.valory.skills.twitter_scoring_abci.rounds import ( + DBUpdateRound, Event, + OpenAICallCheckRound, SynchronizedData, + TweetEvaluationRound, + TwitterDecisionMakingRound, + TwitterHashtagsCollectionRound, TwitterMentionsCollectionRound, ) @@ -83,7 +95,7 @@ def get_payloads( } -def get_dummy_twitter_collection_payload_serialized(api_error: bool = False) -> str: +def get_dummy_mentions_collection_payload_serialized(api_error: bool = False) -> str: """Dummy twitter observation payload""" if api_error: return json.dumps({"error": "true"}) @@ -98,6 +110,21 @@ def get_dummy_twitter_collection_payload_serialized(api_error: bool = False) -> ) +def get_dummy_hashtags_collection_payload_serialized(api_error: bool = False) -> str: + """Dummy twitter observation payload""" + if api_error: + return json.dumps({"error": "true"}) + return json.dumps( + { + "tweets": {"my_tweet": {}}, + "latest_hashtag_tweet_id": False, + "number_of_tweets_pulled_today": 0, + "last_tweet_pull_window_reset": 0, + }, + sort_keys=True, + ) + + class BaseScoreReadRoundTest(BaseCollectSameUntilThresholdRoundTest): """Base test class for ScoreRead rounds.""" @@ -128,7 +155,7 @@ def run_test(self, test_case: RoundTestCase) -> None: ) -class TestTwitterCollectionRound(BaseScoreReadRoundTest): +class TestMentionsCollectionRound(BaseScoreReadRoundTest): """Tests for TwitterMentionsCollectionRound.""" round_class = TwitterMentionsCollectionRound @@ -141,15 +168,15 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): initial_data={"ceramic_db": {}}, payloads=get_payloads( payload_cls=TwitterMentionsCollectionPayload, - data=get_dummy_twitter_collection_payload_serialized(), + data=get_dummy_mentions_collection_payload_serialized(), ), final_data={ "tweets": json.loads( - get_dummy_twitter_collection_payload_serialized() + get_dummy_mentions_collection_payload_serialized() )["tweets"], }, event=Event.DONE, - most_voted_payload=get_dummy_twitter_collection_payload_serialized(), + most_voted_payload=get_dummy_mentions_collection_payload_serialized(), synchronized_data_attr_checks=[ lambda _synchronized_data: _synchronized_data.ceramic_db, ], @@ -159,13 +186,13 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): initial_data={}, payloads=get_payloads( payload_cls=TwitterMentionsCollectionPayload, - data=get_dummy_twitter_collection_payload_serialized( + data=get_dummy_mentions_collection_payload_serialized( api_error=True ), ), final_data={}, event=Event.API_ERROR, - most_voted_payload=get_dummy_twitter_collection_payload_serialized( + most_voted_payload=get_dummy_mentions_collection_payload_serialized( api_error=True ), synchronized_data_attr_checks=[], @@ -177,13 +204,80 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): }, payloads=get_payloads( payload_cls=TwitterMentionsCollectionPayload, - data=get_dummy_twitter_collection_payload_serialized( + data=get_dummy_mentions_collection_payload_serialized( + api_error=True + ), + ), + final_data={}, + event=Event.DONE_MAX_RETRIES, + most_voted_payload=get_dummy_mentions_collection_payload_serialized( + api_error=True + ), + synchronized_data_attr_checks=[], + ), + ), + ) + def test_run(self, test_case: RoundTestCase) -> None: + """Run tests.""" + self.run_test(test_case) + + +class TestHashtagsCollectionRound(BaseScoreReadRoundTest): + """Tests for TwitterMentionsCollectionRound.""" + + round_class = TwitterHashtagsCollectionRound + + @pytest.mark.parametrize( + "test_case", + ( + RoundTestCase( + name="Happy path", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=TwitterHashtagsCollectionPayload, + data=get_dummy_hashtags_collection_payload_serialized(), + ), + final_data={ + "tweets": json.loads( + get_dummy_hashtags_collection_payload_serialized() + )["tweets"], + }, + event=Event.DONE, + most_voted_payload=get_dummy_hashtags_collection_payload_serialized(), + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + RoundTestCase( + name="API error", + initial_data={}, + payloads=get_payloads( + payload_cls=TwitterHashtagsCollectionPayload, + data=get_dummy_hashtags_collection_payload_serialized( + api_error=True + ), + ), + final_data={}, + event=Event.API_ERROR, + most_voted_payload=get_dummy_hashtags_collection_payload_serialized( + api_error=True + ), + synchronized_data_attr_checks=[], + ), + RoundTestCase( + name="API error: max retries", + initial_data={ + "api_retries": 2, + }, + payloads=get_payloads( + payload_cls=TwitterHashtagsCollectionPayload, + data=get_dummy_hashtags_collection_payload_serialized( api_error=True ), ), final_data={}, event=Event.DONE_MAX_RETRIES, - most_voted_payload=get_dummy_twitter_collection_payload_serialized( + most_voted_payload=get_dummy_hashtags_collection_payload_serialized( api_error=True ), synchronized_data_attr_checks=[], @@ -193,3 +287,157 @@ class TestTwitterCollectionRound(BaseScoreReadRoundTest): def test_run(self, test_case: RoundTestCase) -> None: """Run tests.""" self.run_test(test_case) + + +class TestDecisionMakingRound(BaseScoreReadRoundTest): + """Tests for TwitterDecisionMakingRound.""" + + round_class = TwitterDecisionMakingRound + + @pytest.mark.parametrize( + "test_case", + ( + RoundTestCase( + name="Happy path", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=TwitterDecisionMakingPayload, + data=Event.OPENAI_CALL_CHECK.value, + ), + final_data={}, + event=Event.OPENAI_CALL_CHECK, + most_voted_payload=Event.OPENAI_CALL_CHECK.value, + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + ), + ) + def test_run(self, test_case: RoundTestCase) -> None: + """Run tests.""" + self.run_test(test_case) + + +class TestOpenAICallCheckRound(BaseScoreReadRoundTest): + """Tests for OpenAICallCheckRound.""" + + round_class = OpenAICallCheckRound + + @pytest.mark.parametrize( + "test_case", + ( + RoundTestCase( + name="Happy path", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=OpenAICallCheckPayload, + data=OpenAICallCheckRound.CALLS_REMAINING, + ), + final_data={}, + event=Event.DONE, + most_voted_payload=OpenAICallCheckRound.CALLS_REMAINING, + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + RoundTestCase( + name="No allowance", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=OpenAICallCheckPayload, + data="", + ), + final_data={}, + event=Event.NO_ALLOWANCE, + most_voted_payload="", + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + ), + ) + def test_run(self, test_case: RoundTestCase) -> None: + """Run tests.""" + self.run_test(test_case) + + +class TestDBUpdateRound(BaseScoreReadRoundTest): + """Tests for DBUpdateRound.""" + + round_class = DBUpdateRound + + @pytest.mark.parametrize( + "test_case", + ( + RoundTestCase( + name="Happy path", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=DBUpdatePayload, + data="{}", + ), + final_data={}, + event=Event.DONE, + most_voted_payload="{}", + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + ), + ) + def test_run(self, test_case: RoundTestCase) -> None: + """Run tests.""" + self.run_test(test_case) + + +class TestTweetEvaluationRound(BaseCollectNonEmptyUntilThresholdRound): + """TweetEvaluationRound""" + + synchronized_data: SynchronizedData + _synchronized_data_class = SynchronizedData + _event_class = Event + round_class = TweetEvaluationRound + + def run_test(self, test_case: RoundTestCase) -> None: + """Run the test""" + + self.synchronized_data.update(**test_case.initial_data) + + test_round = self.round_class( + synchronized_data=self.synchronized_data, + ) + + self._complete_run( + self._test_round( + test_round=cast(CollectDifferentUntilThresholdRound, test_round), + round_payloads=test_case.payloads, + synchronized_data_update_fn=lambda sync_data, _: sync_data.update( + **test_case.final_data + ), + synchronized_data_attr_checks=test_case.synchronized_data_attr_checks, + exit_event=test_case.event, + ) + ) + + @pytest.mark.parametrize( + "test_case", + ( + RoundTestCase( + name="Happy path", + initial_data={"ceramic_db": {}}, + payloads=get_payloads( + payload_cls=TweetEvaluationPayload, + data="{}", + ), + final_data={}, + event=Event.DONE, + most_voted_payload="{}", + synchronized_data_attr_checks=[ + lambda _synchronized_data: _synchronized_data.ceramic_db, + ], + ), + ), + ) + def test_run(self, test_case: RoundTestCase) -> None: + """Run tests.""" + self.run_test(test_case) From 364ad53ebaf7f92b46ee4624f73d2d3ef0b26faa Mon Sep 17 00:00:00 2001 From: David Vilela Date: Fri, 1 Sep 2023 15:51:46 +0200 Subject: [PATCH 05/14] fix: linters --- docs/index.md | 2 +- packages/packages.json | 8 ++-- .../agents/impact_evaluator/aea-config.yaml | 4 +- .../services/impact_evaluator/service.yaml | 2 +- .../fsm_specification.yaml | 38 +++++++++++++---- .../skills/impact_evaluator_abci/skill.yaml | 4 +- .../skills/twitter_scoring_abci/behaviours.py | 2 +- .../fsm_specification.yaml | 42 ++++++++++++++----- .../skills/twitter_scoring_abci/rounds.py | 23 +++++----- .../skills/twitter_scoring_abci/skill.yaml | 12 +++--- .../tests/test_behaviours.py | 2 +- .../tests/test_payloads.py | 12 ++++++ 12 files changed, 104 insertions(+), 47 deletions(-) diff --git a/docs/index.md b/docs/index.md index ade52a44..d9daecd9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeidqybwdwxzlilnwautwvphmh33ieqmfa5vf3glg42dwfaivhd2owu --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeidypputzep42nnyb27x3nuche4sldqvpxiiipnsk5luihbhfcntla --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 034b1d39..9be37321 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeidvlhkzx6fk6c655rlk4uy46kcb6jqwllbp4rkzyeqnlq7bbnp6iu", + "agent/valory/impact_evaluator/0.1.0": "bafybeigploctarzijb7rz4lbyjrs2ted3bgujawqdc3tynsfgpoebwaflq", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeidqybwdwxzlilnwautwvphmh33ieqmfa5vf3glg42dwfaivhd2owu", + "service/valory/impact_evaluator/0.1.0": "bafybeidypputzep42nnyb27x3nuche4sldqvpxiiipnsk5luihbhfcntla", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeic6w4gw2wghfs73hmeahhjd5jtaam7y4lpuosz3l43fygkykw4vay", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeibxkrbxs5vf52vyw2ucedeiio2zrclhjn4fquyenktlg5yqao35ma", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index f96f9677..b8efa12a 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeic6w4gw2wghfs73hmeahhjd5jtaam7y4lpuosz3l43fygkykw4vay +- valory/impact_evaluator_abci:0.1.0:bafybeibxkrbxs5vf52vyw2ucedeiio2zrclhjn4fquyenktlg5yqao35ma - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq +- valory/twitter_scoring_abci:0.1.0:bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 791b1000..05448cab 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeidvlhkzx6fk6c655rlk4uy46kcb6jqwllbp4rkzyeqnlq7bbnp6iu +agent: valory/impact_evaluator:0.1.0:bafybeigploctarzijb7rz4lbyjrs2ted3bgujawqdc3tynsfgpoebwaflq number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml index 6d8f1e9e..6099f7d4 100644 --- a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml +++ b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml @@ -4,22 +4,29 @@ alphabet_in: - CONTRACT_ERROR - DAILY_ORBIS - DAILY_TWEET +- DB_UPDATE - DID_NOT_SEND - DONE - DONE_CONTINUE - DONE_FINISHED +- DONE_MAX_RETRIES +- DONE_SKIP +- EVALUATE - LLM - MAX_RETRIES_ERROR - NEXT_CENTAUR +- NO_ALLOWANCE - NO_MAJORITY +- OPENAI_CALL_CHECK - READ_CENTAURS - READ_CONTRIBUTE_DB - READ_MANUAL_POINTS - RESET_AND_PAUSE_TIMEOUT +- RETRIEVE_HASHTAGS +- RETRIEVE_MENTIONS - ROUND_TIMEOUT - SCHEDULED_TWEET - SCORE -- SKIP - TWEET_EVALUATION_ROUND_TIMEOUT - UPDATE_CENTAURS - VERIFICATION_ERROR @@ -49,11 +56,13 @@ states: - StreamWriteRound - TokenTrackRound - TweetEvaluationRound +- TwitterDecisionMakingRound +- TwitterHashtagsCollectionRound - TwitterMentionsCollectionRound - TwitterWriteRound - VerificationRound transition_func: - (DBUpdateRound, DONE): TokenTrackRound + (DBUpdateRound, DONE): TwitterDecisionMakingRound (DBUpdateRound, NO_MAJORITY): DBUpdateRound (DBUpdateRound, ROUND_TIMEOUT): DBUpdateRound (DecisionMakingRound, DAILY_ORBIS): RandomnessRound @@ -70,7 +79,7 @@ transition_func: (DecisionMakingRound, SCORE): GenericScoringRound (DecisionMakingRound, UPDATE_CENTAURS): RandomnessRound (DecisionMakingRound, WRITE_CONTRIBUTE_DB): RandomnessRound - (GenericScoringRound, DONE): OpenAICallCheckRound + (GenericScoringRound, DONE): TwitterDecisionMakingRound (GenericScoringRound, NO_MAJORITY): GenericScoringRound (GenericScoringRound, ROUND_TIMEOUT): GenericScoringRound (LLMRandomnessRound, DONE): LLMSelectKeeperRound @@ -83,9 +92,10 @@ transition_func: (LLMSelectKeeperRound, DONE): LLMRound (LLMSelectKeeperRound, NO_MAJORITY): LLMRandomnessRound (LLMSelectKeeperRound, ROUND_TIMEOUT): LLMRandomnessRound - (OpenAICallCheckRound, API_ERROR): TokenTrackRound (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound + (OpenAICallCheckRound, NO_ALLOWANCE): TwitterMentionsCollectionRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound + (OpenAICallCheckRound, ROUND_TIMEOUT): OpenAICallCheckRound (RandomnessRound, DONE): SelectKeeperRound (RandomnessRound, NO_MAJORITY): RandomnessRound (RandomnessRound, ROUND_TIMEOUT): RandomnessRound @@ -117,13 +127,27 @@ transition_func: (TokenTrackRound, DONE): DecisionMakingRound (TokenTrackRound, NO_MAJORITY): TokenTrackRound (TokenTrackRound, ROUND_TIMEOUT): TokenTrackRound - (TweetEvaluationRound, DONE): DBUpdateRound + (TweetEvaluationRound, DONE): TwitterDecisionMakingRound (TweetEvaluationRound, TWEET_EVALUATION_ROUND_TIMEOUT): TweetEvaluationRound + (TwitterDecisionMakingRound, DB_UPDATE): DBUpdateRound + (TwitterDecisionMakingRound, DONE): TokenTrackRound + (TwitterDecisionMakingRound, DONE_SKIP): TokenTrackRound + (TwitterDecisionMakingRound, EVALUATE): TweetEvaluationRound + (TwitterDecisionMakingRound, NO_MAJORITY): TwitterDecisionMakingRound + (TwitterDecisionMakingRound, OPENAI_CALL_CHECK): OpenAICallCheckRound + (TwitterDecisionMakingRound, RETRIEVE_HASHTAGS): TwitterHashtagsCollectionRound + (TwitterDecisionMakingRound, RETRIEVE_MENTIONS): TwitterMentionsCollectionRound + (TwitterDecisionMakingRound, ROUND_TIMEOUT): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, API_ERROR): TwitterHashtagsCollectionRound + (TwitterHashtagsCollectionRound, DONE): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, DONE_MAX_RETRIES): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, NO_MAJORITY): TwitterHashtagsCollectionRound + (TwitterHashtagsCollectionRound, ROUND_TIMEOUT): TwitterHashtagsCollectionRound (TwitterMentionsCollectionRound, API_ERROR): TwitterMentionsCollectionRound - (TwitterMentionsCollectionRound, DONE): TweetEvaluationRound + (TwitterMentionsCollectionRound, DONE): TwitterDecisionMakingRound + (TwitterMentionsCollectionRound, DONE_MAX_RETRIES): TwitterDecisionMakingRound (TwitterMentionsCollectionRound, NO_MAJORITY): TwitterMentionsCollectionRound (TwitterMentionsCollectionRound, ROUND_TIMEOUT): TwitterMentionsCollectionRound - (TwitterMentionsCollectionRound, SKIP): TokenTrackRound (TwitterWriteRound, API_ERROR): RandomnessTwitterRound (TwitterWriteRound, CONTINUE): TwitterWriteRound (TwitterWriteRound, DONE): DecisionMakingRound diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index fa7c83e9..87b20826 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -10,7 +10,7 @@ fingerprint: behaviours.py: bafybeifhoufesr4r4re65mxjadqasjymvz6tkc25xn5yyn473yunhjiufe composition.py: bafybeifmf52jhbiyyqyxzd67gxrydedm44ouzib3jh56kzoe5xohjrhm34 dialogues.py: bafybeigjknz4qqynbsltjje46gidg4rftsqw6ybjwegz24wetmycutpzh4 - fsm_specification.yaml: bafybeifn6z5zeowyd4seaqgywseeqwpdj332rj2dg4bwpmd7dtzedsvtdy + fsm_specification.yaml: bafybeicbmtw5gpevf5kdenu3aukxqsurov3rv5iyeygyykoecdnduiu5wq handlers.py: bafybeidkli6fphcmdgwsys4lkyf3fx6fbawet4nt2pnixfypzijhg6b3ze models.py: bafybeifhcshu4iwqvc2fz3auu5ngfykkhvqnroeug52ilrwwc4kowkeg5a tests/__init__.py: bafybeievwzwojvq4aofk5kjpf4jzygfes7ew6s6svc6b6frktjnt3sicce @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeicdj5hkpwfakes5larjzvrsqpr72ebolfegirvxp2ogrrtwqvj4rq +- valory/twitter_scoring_abci:0.1.0:bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index 3bf654b0..7187190f 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -447,7 +447,7 @@ def async_act(self) -> Generator: } sender = self.context.agent_address - payload = TwitterMentionsCollectionPayload( + payload = TwitterHashtagsCollectionPayload( sender=sender, content=json.dumps(payload_data, sort_keys=True) ) diff --git a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml index 61dd05a3..3d5046f2 100644 --- a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml +++ b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml @@ -1,35 +1,57 @@ alphabet_in: - API_ERROR +- DB_UPDATE - DONE +- DONE_MAX_RETRIES +- DONE_SKIP +- EVALUATE +- NO_ALLOWANCE - NO_MAJORITY +- OPENAI_CALL_CHECK +- RETRIEVE_HASHTAGS +- RETRIEVE_MENTIONS - ROUND_TIMEOUT -- SKIP - TWEET_EVALUATION_ROUND_TIMEOUT -default_start_state: OpenAICallCheckRound +default_start_state: TwitterDecisionMakingRound final_states: - FinishedTwitterScoringRound -- FinishedTwitterScoringWithAPIErrorRound label: TwitterScoringAbciApp start_states: -- OpenAICallCheckRound +- TwitterDecisionMakingRound states: - DBUpdateRound - FinishedTwitterScoringRound -- FinishedTwitterScoringWithAPIErrorRound - OpenAICallCheckRound - TweetEvaluationRound +- TwitterDecisionMakingRound +- TwitterHashtagsCollectionRound - TwitterMentionsCollectionRound transition_func: - (DBUpdateRound, DONE): FinishedTwitterScoringRound + (DBUpdateRound, DONE): TwitterDecisionMakingRound (DBUpdateRound, NO_MAJORITY): DBUpdateRound (DBUpdateRound, ROUND_TIMEOUT): DBUpdateRound - (OpenAICallCheckRound, API_ERROR): FinishedTwitterScoringWithAPIErrorRound (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound + (OpenAICallCheckRound, NO_ALLOWANCE): TwitterMentionsCollectionRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound - (TweetEvaluationRound, DONE): DBUpdateRound + (OpenAICallCheckRound, ROUND_TIMEOUT): OpenAICallCheckRound + (TweetEvaluationRound, DONE): TwitterDecisionMakingRound (TweetEvaluationRound, TWEET_EVALUATION_ROUND_TIMEOUT): TweetEvaluationRound + (TwitterDecisionMakingRound, DB_UPDATE): DBUpdateRound + (TwitterDecisionMakingRound, DONE): FinishedTwitterScoringRound + (TwitterDecisionMakingRound, DONE_SKIP): FinishedTwitterScoringRound + (TwitterDecisionMakingRound, EVALUATE): TweetEvaluationRound + (TwitterDecisionMakingRound, NO_MAJORITY): TwitterDecisionMakingRound + (TwitterDecisionMakingRound, OPENAI_CALL_CHECK): OpenAICallCheckRound + (TwitterDecisionMakingRound, RETRIEVE_HASHTAGS): TwitterHashtagsCollectionRound + (TwitterDecisionMakingRound, RETRIEVE_MENTIONS): TwitterMentionsCollectionRound + (TwitterDecisionMakingRound, ROUND_TIMEOUT): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, API_ERROR): TwitterHashtagsCollectionRound + (TwitterHashtagsCollectionRound, DONE): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, DONE_MAX_RETRIES): TwitterDecisionMakingRound + (TwitterHashtagsCollectionRound, NO_MAJORITY): TwitterHashtagsCollectionRound + (TwitterHashtagsCollectionRound, ROUND_TIMEOUT): TwitterHashtagsCollectionRound (TwitterMentionsCollectionRound, API_ERROR): TwitterMentionsCollectionRound - (TwitterMentionsCollectionRound, DONE): TweetEvaluationRound + (TwitterMentionsCollectionRound, DONE): TwitterDecisionMakingRound + (TwitterMentionsCollectionRound, DONE_MAX_RETRIES): TwitterDecisionMakingRound (TwitterMentionsCollectionRound, NO_MAJORITY): TwitterMentionsCollectionRound (TwitterMentionsCollectionRound, ROUND_TIMEOUT): TwitterMentionsCollectionRound - (TwitterMentionsCollectionRound, SKIP): FinishedTwitterScoringRound diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index 0a40bbd3..fa180bbf 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -129,6 +129,8 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: """Process the end of the block.""" if self.threshold_reached: event = Event(self.most_voted_payload) + # Reference events to avoid tox -e check-abciapp-specs failures + # Event.DONE, Event.DB_UPDATE, Event.RETRIEVE_MENTIONS, Event.RETRIEVE_HASHTAGS, Event.OPENAI_CALL_CHECK, Event.EVALUATE, Event.DONE_SKIP return self.synchronized_data, event if not self.is_majority_possible( self.collection, self.synchronized_data.nb_participants @@ -154,9 +156,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Happy path if self.most_voted_payload == self.CALLS_REMAINING: - performed_twitter_tasks[ - Event.OPENAI_CALL_CHECK.value - ] = Event.DONE.value + performed_twitter_tasks["openai_call_check"] = Event.DONE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, **{ @@ -168,9 +168,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: return synchronized_data, Event.DONE # No allowance - performed_twitter_tasks[ - Event.OPENAI_CALL_CHECK.value - ] = Event.NO_ALLOWANCE.value + performed_twitter_tasks["openai_call_check"] = Event.NO_ALLOWANCE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, **{ @@ -213,7 +211,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Max retries if api_retries >= MAX_API_RETRIES: performed_twitter_tasks[ - Event.RETRIEVE_MENTIONS.value + "retrieve_mentions" ] = Event.DONE_MAX_RETRIES.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, @@ -237,7 +235,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Happy path payload = json.loads(self.most_voted_payload) previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets - performed_twitter_tasks[Event.RETRIEVE_MENTIONS.value] = Event.DONE.value + performed_twitter_tasks["retrieve_mentions"] = Event.DONE.value new_tweets = payload["tweets"] updates = { @@ -299,7 +297,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Max retries if api_retries >= MAX_API_RETRIES: performed_twitter_tasks[ - Event.RETRIEVE_HASHTAGS.value + "retrieve_hashtags" ] = Event.DONE_MAX_RETRIES.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, @@ -323,7 +321,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Happy path payload = json.loads(self.most_voted_payload) previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets - performed_twitter_tasks[Event.RETRIEVE_HASHTAGS.value] = Event.DONE.value + performed_twitter_tasks["retrieve_hashtags"] = Event.DONE.value new_tweets = payload["tweets"] updates = { @@ -392,7 +390,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]: tweets[tweet_id]["points"] = median print(f"Tweet {tweet_id} has been awarded {median} points") - performed_twitter_tasks[Event.EVALUATE.value] = Event.DONE.value + performed_twitter_tasks["evaluate"] = Event.DONE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, **{ @@ -423,7 +421,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: performed_twitter_tasks = cast( SynchronizedData, self.synchronized_data ).performed_twitter_tasks - performed_twitter_tasks[Event.DB_UPDATE.value] = Event.DONE.value + performed_twitter_tasks["db_update"] = Event.DONE.value synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, @@ -463,6 +461,7 @@ class TwitterScoringAbciApp(AbciApp[Event]): Event.DB_UPDATE: DBUpdateRound, Event.DONE: FinishedTwitterScoringRound, Event.ROUND_TIMEOUT: TwitterDecisionMakingRound, + Event.NO_MAJORITY: TwitterDecisionMakingRound, }, OpenAICallCheckRound: { Event.DONE: TwitterMentionsCollectionRound, diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 635b9796..82ebf0b4 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,23 +8,23 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeihcbk3lgo5bj6efudg5kmrmbqrqbe5vldob6kikov67oozcutcxeu + behaviours.py: bafybeifiaawiifjkum2fxpusym4pvrxr7imr6uqrlb4o5sdhnf5mlyjrse ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si - fsm_specification.yaml: bafybeiegd4eodewbip6l7mcw44kxgzvuwg4jljacokb3eayud7dxcygjqe + fsm_specification.yaml: bafybeieyvejtg6s3tdbrpnnaf56t62y4btmoom7fgdzbq5uzpc7mpc6ewq handlers.py: bafybeid3nqvcyotqj5g5hlgrz57nf7vpjysmgvsxe3p7644f4z5dcwqn6u models.py: bafybeihqlxg6tbkpkjr5kfdcxwopykvoimczfn22q3owlzgw2elsg76cf4 payloads.py: bafybeihzjioqknhekm7fzlhl52iklkwzuuht6w2qqk5ptutv5s2wqtoedy prompts.py: bafybeieiuqn427bgwfnzynxf3vtqfpvmqqscs5tyw4oibfofwropifotke - rounds.py: bafybeifjf4doesl3ntu32fm7qycm4nwttsobryzimjk5fvlnnmxjb67mzu + rounds.py: bafybeihsqkae4ykxzfwgvgsqzvmlhhufxdmrkaw6b5cdggwd5vdiot4pfq tests/__init__.py: bafybeidwzzd4ejsyf3aryd5kmrvd63h7ajgqyrxphmfaacvpjnneacejay - tests/test_behaviours.py: bafybeidfcoz3sbgr2hcgjtettjfmqqsh5pt32tyn4necjp4npgjjskdzcu + tests/test_behaviours.py: bafybeiguh5cbo4m4l4r7nufhki4rasvv4qv6shezynzqiipjduxp5w2nby tests/test_ceramic_db.py: bafybeif2v7btjphbqabq6qdmfeyweg765seon74acg5vrrvznivzg2prey tests/test_dialogues.py: bafybeiheyq7klonzb7rnjub2i22h7bmsnoimn2pq4j7ofikt3yovstvgt4 tests/test_handlers.py: bafybeigevirvi3saepukke2zmp334btgsdxhj55o2vawj3hqam63miirg4 tests/test_models.py: bafybeihaiirqmcsshghztl5lvqjzem6y6rdeefhtiycrhh45v7cuwnmdz4 - tests/test_payloads.py: bafybeie3herufgeyupdxwi6bhcs3gbqwhsypn4ujaqnhe3myj6ezckdu4q - tests/test_rounds.py: bafybeibdrk4okn3fqatl56udkjdlanpleqajylhp2sysw64ji472uxjczy + tests/test_payloads.py: bafybeihzltj7fvfl6n3cylfg6jqaqpiwchfimwys4732hurvkjnwmewksy + tests/test_rounds.py: bafybeihnsc45rjukbrwtqkshkqdckjrkfcu4u3otxqhukw3duwmat6rdne fingerprint_ignore_patterns: [] connections: - valory/openai:0.1.0:bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py index 499d69fb..b5b816ef 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py @@ -33,7 +33,6 @@ ) from packages.valory.skills.twitter_scoring_abci.behaviours import ( TAGLINE, - TweetEvaluationBehaviour, TwitterDecisionMakingBehaviour, TwitterHashtagsCollectionBehaviour, TwitterMentionsCollectionBehaviour, @@ -266,6 +265,7 @@ class BaseBehaviourTest(FSMBehaviourBaseCase): @classmethod def setup_class(cls, **kwargs: Any) -> None: + """Setup class""" super().setup_class(param_overrides={"twitter_max_pages": 10}) def fast_forward(self, data: Optional[Dict[str, Any]] = None) -> None: diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py index d2c2c76b..5918768e 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_payloads.py @@ -78,3 +78,15 @@ def test_payloads(test_case: PayloadTestCase) -> None: assert payload.sender == "sender" assert payload.content == test_case.content assert payload.from_json(payload.json) == payload + + +def test_decision_making_payload() -> None: + """Tests for TwitterScoringAbciApp payloads""" + + payload = TwitterDecisionMakingPayload( + sender="sender", + event="event", + ) + assert payload.sender == "sender" + assert payload.event == "event" + assert payload.from_json(payload.json) == payload From 5b3c1ca2e155d341f8006312b09fe2191c022705 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Fri, 1 Sep 2023 19:04:14 +0200 Subject: [PATCH 06/14] test: coverage --- .../skills/twitter_scoring_abci/behaviours.py | 2 +- .../tests/test_behaviours.py | 116 +++++++++++++++++- 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index 7187190f..f3ed06fb 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -156,7 +156,7 @@ def get_next_event(self) -> str: performed_tasks = self.synchronized_data.performed_twitter_tasks - self.context.logger.info(f"Permormed tasks: {performed_tasks}") + self.context.logger.info(f"Performed tasks: {performed_tasks}") if Event.OPENAI_CALL_CHECK.value not in performed_tasks: return Event.OPENAI_CALL_CHECK.value diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py index b5b816ef..8dab78e4 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py @@ -28,18 +28,28 @@ import pytest from packages.valory.skills.abstract_round_abci.base import AbciAppDB +from packages.valory.skills.abstract_round_abci.behaviour_utils import ( + make_degenerate_behaviour, +) from packages.valory.skills.abstract_round_abci.test_tools.base import ( FSMBehaviourBaseCase, ) from packages.valory.skills.twitter_scoring_abci.behaviours import ( + DBUpdateBehaviour, + OpenAICallCheckBehaviour, TAGLINE, + TweetEvaluationBehaviour, TwitterDecisionMakingBehaviour, TwitterHashtagsCollectionBehaviour, TwitterMentionsCollectionBehaviour, TwitterScoringBaseBehaviour, TwitterScoringRoundBehaviour, ) -from packages.valory.skills.twitter_scoring_abci.rounds import Event, SynchronizedData +from packages.valory.skills.twitter_scoring_abci.rounds import ( + Event, + FinishedTwitterScoringRound, + SynchronizedData, +) ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -697,3 +707,107 @@ def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: ), ) self.complete(test_case.event) + + +class TestTwitterDecisionMakingBehaviour(BaseBehaviourTest): + """Tests BinanceObservationBehaviour""" + + behaviour_class = TwitterDecisionMakingBehaviour + + @pytest.mark.parametrize( + "test_case, next_behaviour", + [ + ( + BehaviourTestCase( + "Happy path", + initial_data=dict(performed_twitter_tasks={}), + event=Event.OPENAI_CALL_CHECK, + ), + OpenAICallCheckBehaviour, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={"openai_call_check": "done"} + ), + event=Event.RETRIEVE_MENTIONS, + ), + TwitterMentionsCollectionBehaviour, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={"openai_call_check": "no_allowance"} + ), + event=Event.DONE_SKIP, + ), + make_degenerate_behaviour(FinishedTwitterScoringRound), + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={ + "openai_call_check": "done", + "retrieve_hashtags": None, + } + ), + event=Event.RETRIEVE_HASHTAGS, + ), + TwitterHashtagsCollectionBehaviour, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={ + "openai_call_check": "done", + "retrieve_hashtags": None, + "retrieve_mentions": None, + } + ), + event=Event.EVALUATE, + ), + TweetEvaluationBehaviour, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={ + "openai_call_check": "done", + "retrieve_hashtags": None, + "retrieve_mentions": None, + "evaluate": None, + } + ), + event=Event.DB_UPDATE, + ), + DBUpdateBehaviour, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + performed_twitter_tasks={ + "openai_call_check": "done", + "retrieve_hashtags": None, + "retrieve_mentions": None, + "evaluate": None, + "db_update": None, + } + ), + event=Event.DB_UPDATE, + ), + DBUpdateBehaviour, + ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, next_behaviour) -> None: + """Run tests.""" + self.next_behaviour_class = next_behaviour + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + self.complete(test_case.event) From 415a0acff141661de92828497a8fe1fdea5b0040 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Mon, 4 Sep 2023 10:19:39 +0200 Subject: [PATCH 07/14] fix: wallet duplication --- .../skills/twitter_scoring_abci/behaviours.py | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index cd77f589..5fe7e71d 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -668,7 +668,7 @@ def update_ceramic_db(self) -> Dict: author_id = tweet["author_id"] twitter_name = tweet["username"] new_points = tweet["points"] - wallet_address = get_registration(tweet["text"]) + wallet_address = self.get_registration(tweet["text"]) # Check this user's point limit per period user, _ = ceramic_db.get_user_by_field("twitter_id", tweet["author_id"]) @@ -738,19 +738,26 @@ def update_ceramic_db(self) -> Dict: return ceramic_db.data + def get_registration(self, text: str) -> Optional[str]: + """Check if the tweet is a registration and return the wallet address""" -def get_registration(text: str) -> Optional[str]: - """Check if the tweet is a registration and return the wallet address""" + wallet_address = None - wallet_address = None + registered_addresses = [ + user["wallet_address"] + for user in self.synchronized_data.ceramic_db["users"] + if user["wallet_address"] + ] - address_match = re.search(ADDRESS_REGEX, text) - tagline_match = re.search(TAGLINE, text, re.IGNORECASE) + address_match = re.search(ADDRESS_REGEX, text) + tagline_match = re.search(TAGLINE, text, re.IGNORECASE) - if address_match and tagline_match: - wallet_address = Web3.to_checksum_address(address_match.group()) + if address_match and tagline_match: + wallet_address = Web3.to_checksum_address(address_match.group()) + if wallet_address in registered_addresses: + return None - return wallet_address + return wallet_address class TwitterScoringRoundBehaviour(AbstractRoundBehaviour): From 46a100d1043b646977c94219356be115cca5ebef Mon Sep 17 00:00:00 2001 From: David Vilela Date: Mon, 4 Sep 2023 10:21:50 +0200 Subject: [PATCH 08/14] fix: generators --- docs/index.md | 2 +- packages/packages.json | 8 ++++---- packages/valory/agents/impact_evaluator/aea-config.yaml | 4 ++-- packages/valory/services/impact_evaluator/service.yaml | 2 +- packages/valory/skills/impact_evaluator_abci/skill.yaml | 2 +- packages/valory/skills/twitter_scoring_abci/skill.yaml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/index.md b/docs/index.md index e81e76b9..78a5442e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeibxdpqanic5yizhhu6v5bbapghyktschuouywiedgq5u2l5dyj634 --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeidasru64g2t3xkskacqh52fyspmzeq4drpzmrx33wvoczv5rjsxhu --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index f97c8699..800d6fcb 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeianmf6g3sq3bqdmlmyjzfad6xoo6fotmhgyribrej632ye3ybpuhq", + "agent/valory/impact_evaluator/0.1.0": "bafybeigmv2eajssol2zl5pplol6byjfwsngdzzzoxbat6kou5h4q3gisyi", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeibxdpqanic5yizhhu6v5bbapghyktschuouywiedgq5u2l5dyj634", + "service/valory/impact_evaluator/0.1.0": "bafybeidasru64g2t3xkskacqh52fyspmzeq4drpzmrx33wvoczv5rjsxhu", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeidtp3l5jzfqr5fjvwpyzk4tn7lb3m66rjomyqktfvxbwmd66bzthu", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeicrweqh6n62vn5houbkjf275a5lniuadrjd3kkaptdcqcukyisrcq", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 60bac34e..84e75b5d 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeidtp3l5jzfqr5fjvwpyzk4tn7lb3m66rjomyqktfvxbwmd66bzthu +- valory/impact_evaluator_abci:0.1.0:bafybeicrweqh6n62vn5houbkjf275a5lniuadrjd3kkaptdcqcukyisrcq - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q +- valory/twitter_scoring_abci:0.1.0:bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 42d925a1..787bde88 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeianmf6g3sq3bqdmlmyjzfad6xoo6fotmhgyribrej632ye3ybpuhq +agent: valory/impact_evaluator:0.1.0:bafybeigmv2eajssol2zl5pplol6byjfwsngdzzzoxbat6kou5h4q3gisyi number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index a4feb313..9a93b368 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigsegi7iyftnwyte36z2wgf444z2yqifpxzrxkysmt6spc5qsmd7q +- valory/twitter_scoring_abci:0.1.0:bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index c1bc6eea..f1293ee8 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeicucnx5gq2xrmprtjohx7murrd3gsr6hncvhaled7brc7jirvuipu + behaviours.py: bafybeidv4khcl4rzqjiev2qga5o6pqpgugauyjw25pbdgoyxgadrsjfid4 ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si fsm_specification.yaml: bafybeietfinv3lvmyon3bk5f4gu2qf4hjlrqogfiombqnncyme5qrpbffa From 11b63d92e3e6f32a0185fce8afc55eb714b47fa6 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Mon, 4 Sep 2023 14:11:50 +0200 Subject: [PATCH 09/14] test: improve e2e --- docs/index.md | 2 +- packages/packages.json | 12 +-- .../agents/impact_evaluator/aea-config.yaml | 12 +-- .../tests/helpers/data/json_server/data.json | 96 +++++++++---------- .../tests/test_impact_evaluator.py | 34 ++++++- .../valory/connections/openai/connection.py | 25 +++-- .../valory/connections/openai/connection.yaml | 2 +- .../services/impact_evaluator/service.yaml | 2 +- .../skills/impact_evaluator_abci/skill.yaml | 4 +- packages/valory/skills/llm_abci/skill.yaml | 2 +- .../skills/twitter_scoring_abci/behaviours.py | 2 + .../skills/twitter_scoring_abci/rounds.py | 10 ++ .../skills/twitter_scoring_abci/skill.yaml | 8 +- 13 files changed, 121 insertions(+), 90 deletions(-) diff --git a/docs/index.md b/docs/index.md index d9daecd9..ac0f748d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeidypputzep42nnyb27x3nuche4sldqvpxiiipnsk5luihbhfcntla --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeiggrs7vvlqs5z7jrszgasj4xm4fvbzidnzcrsakn7pxzueyu4ojly --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 9be37321..176278c0 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,20 +1,20 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeigploctarzijb7rz4lbyjrs2ted3bgujawqdc3tynsfgpoebwaflq", + "agent/valory/impact_evaluator/0.1.0": "bafybeieomrbn6vpujq4oq3hdcrxxcnb54u67zjmeqaou7l7lhaxqgpu5oq", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeidypputzep42nnyb27x3nuche4sldqvpxiiipnsk5luihbhfcntla", + "service/valory/impact_evaluator/0.1.0": "bafybeiggrs7vvlqs5z7jrszgasj4xm4fvbzidnzcrsakn7pxzueyu4ojly", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeibxkrbxs5vf52vyw2ucedeiio2zrclhjn4fquyenktlg5yqao35ma", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeihnzr74nji3oulzasf44rbrdgc5whsov3aabbmvxm623htv5a5jjm", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", "connection/valory/twitter/0.1.0": "bafybeibndxp3l35osve5pj255waemunlzaacwtasyazjmcmrx7qo5wcrni", - "connection/valory/openai/0.1.0": "bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq", + "connection/valory/openai/0.1.0": "bafybeih7w2xmaecgznuhxpnbxcxjhfla6wlmx3umytindfgk6ibbwqq2lu", "skill/valory/twitter_write_abci/0.1.0": "bafybeih662zzwew4egsm2m6mis5yjwfehhx2lciio5ngnbunolc6nkkyw4", - "skill/valory/llm_abci/0.1.0": "bafybeifvskttsumhsatvj24sx45u23zq57k56fnfgliq2csul53kjyhfhy", + "skill/valory/llm_abci/0.1.0": "bafybeictnqpioilfry2yxkwaaguam5zbo3ygw7slkpn3k36gfvo2cnnyam", "skill/valory/decision_making_abci/0.1.0": "bafybeih5nquchsfisp5taaxrpz7j7ur2teymey5tihlw654wrzgpy57bvq" }, "third_party": { diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index b8efa12a..8d744688 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -9,10 +9,10 @@ fingerprint: tests/__init__.py: bafybeibknjewfed3d5ypi46ipuzfxdcps5ief2hfd3a2tfvm4gjtzzblme tests/helpers/__init__.py: bafybeif7verbag26h6i35gr5rlatxl7veq4drup5ykwdvhgtussf2jreei tests/helpers/constants.py: bafybeibbokz7gzdlubnjwxrmh4tqckc7j75hfy3ae6l5a63mrbd4hp6l7u - tests/helpers/data/json_server/data.json: bafybeif5wzdnb4qdo4mjxcn6f7m57n7p4jmr5lmfxlthrvewyi6mfczonq + tests/helpers/data/json_server/data.json: bafybeiapboptlarlpc2lboj4g2526vev7fwqpr267tb2qn6cevbblpnewe tests/helpers/docker.py: bafybeihlg5thdrcaiuzyte5s7x25mikqfyxdjwuqvhmeddluyjdkzhuhqi tests/helpers/fixtures.py: bafybeidfsamzdrqqkdra4ektollyfkhiyb2iqymy6djavgewon2cb23vwu - tests/test_impact_evaluator.py: bafybeifxqu7dim3homzpzsglicv26tkevbjhcmdmlmv7dxws6uuiwpz54u + tests/test_impact_evaluator.py: bafybeigo4mbjppcd24f47zykj7icq2vatfddskqrfpyylqqdphcfd5hbeu fingerprint_ignore_patterns: [] connections: - fetchai/http_server:0.22.0:bafybeihp5umafxzx45aad5pj7s3343se2wjkgnbirt4pybrape22swm6de @@ -20,7 +20,7 @@ connections: - valory/http_client:0.23.0:bafybeieoeuy4brzimtnubmokwirhrx27ezls6cdnl5qik4rkykfle3nn2y - valory/ledger:0.19.0:bafybeigfoz7d7si7s4jehvloq2zmiiocpbxcaathl3bxkyarxoerxq7g3a - valory/p2p_libp2p_client:0.1.0:bafybeihdnfdth3qgltefgrem7xyi4b3ejzaz67xglm2hbma2rfvpl2annq -- valory/openai:0.1.0:bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq +- valory/openai:0.1.0:bafybeih7w2xmaecgznuhxpnbxcxjhfla6wlmx3umytindfgk6ibbwqq2lu - valory/twitter:0.1.0:bafybeibndxp3l35osve5pj255waemunlzaacwtasyazjmcmrx7qo5wcrni contracts: - valory/dynamic_contribution:0.1.0:bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeibxkrbxs5vf52vyw2ucedeiio2zrclhjn4fquyenktlg5yqao35ma +- valory/impact_evaluator_abci:0.1.0:bafybeihnzr74nji3oulzasf44rbrdgc5whsov3aabbmvxm623htv5a5jjm - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i +- valory/twitter_scoring_abci:0.1.0:bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq @@ -54,7 +54,7 @@ skills: - valory/transaction_settlement_abci:0.1.0:bafybeidpsnguxizkpihtkqzojr3em7yy7c6qc7gxpbh5vglmwws5wke7bi - valory/twitter_write_abci:0.1.0:bafybeih662zzwew4egsm2m6mis5yjwfehhx2lciio5ngnbunolc6nkkyw4 - valory/decision_making_abci:0.1.0:bafybeih5nquchsfisp5taaxrpz7j7ur2teymey5tihlw654wrzgpy57bvq -- valory/llm_abci:0.1.0:bafybeifvskttsumhsatvj24sx45u23zq57k56fnfgliq2csul53kjyhfhy +- valory/llm_abci:0.1.0:bafybeictnqpioilfry2yxkwaaguam5zbo3ygw7slkpn3k36gfvo2cnnyam default_ledger: ethereum required_ledgers: - ethereum diff --git a/packages/valory/agents/impact_evaluator/tests/helpers/data/json_server/data.json b/packages/valory/agents/impact_evaluator/tests/helpers/data/json_server/data.json index dfb662a4..6b56dc89 100644 --- a/packages/valory/agents/impact_evaluator/tests/helpers/data/json_server/data.json +++ b/packages/valory/agents/impact_evaluator/tests/helpers/data/json_server/data.json @@ -3,13 +3,19 @@ "get": { "data": [ { - "author_id": "315490172" + "author_id": "315490172", + "id":"1", + "text": "This is a dummy tweet about @autonolas" }, { - "author_id": "315490172" + "author_id": "315490172", + "id":"2", + "text": "This is a dummy tweet about @autonolas" }, { - "author_id": "315490172" + "author_id": "315490172", + "id":"3", + "text": "This is a dummy tweet about @autonolas" } ], "includes": { @@ -17,14 +23,6 @@ { "id": "315490172", "username": "username_a" - }, - { - "id": "315490172", - "username": "username_b" - }, - { - "id": "315490172", - "username": "username_c" } ] }, @@ -37,13 +35,13 @@ "get": { "data":[ { - "id":"1635694341422297098", + "id":"4", "created_at":"2023-03-14T17:28:15.000Z", "edit_history_tweet_ids":[ - "1635694341422297098" + "4" ], - "text":"This is a validation test #olas 0x4bB3cF635775df4236B97FbB7c4e5B233654891c", - "author_id":"1408535517558415364" + "text":"I'm linking my wallet to @Autonolas Contribute: 0x4bB3cF635775df4236B97FbB7c4e5B233654891c #OlasNetwork", + "author_id":"315490172" } ], "includes": { @@ -51,14 +49,6 @@ { "id": "315490172", "username": "username_a" - }, - { - "id": "315490172", - "username": "username_b" - }, - { - "id": "315490172", - "username": "username_c" } ] }, @@ -70,28 +60,28 @@ } }, "/api/v0/commits/stream_id_e2e": { - "get": { - "streamId":"kjzl6cwe1jw146ndq1g0kadxtqv72z9hr87zhelng6aw2s3ff00u7h7s4fi9kgq", - "docId":"kjzl6cwe1jw146ndq1g0kadxtqv72z9hr87zhelng6aw2s3ff00u7h7s4fi9kgq", - "commits":[ - { - "cid":"bagcqcerag4vki7krkkgjrbwxdooz5wjq4muri5bp2kgtkdtjwfd5cfcj7xna", - "value":{ - "jws":{ - "payload":"AXESIKApZqPy_sgBAYJKBfVoYgxups7WBbkXebyI14ZP7ZEV", - "signatures":[ - { - "signature":"BhpWFS-RoGPx4A1S4Xklovbk4px-ekwc9wTVO34PMy3cUTq7FDgZH4DBHckKhmQ-MOI87567zReQsdPKysFvAw", - "protected":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3JCM1VuMWhUNWdiY0JtWTVHaU1rZkpNMmdnVFpCRXlaUThVc2l2czUzbnFTI3o2TWtyQjNVbjFoVDVnYmNCbVk1R2lNa2ZKTTJnZ1RaQkV5WlE4VXNpdnM1M25xUyJ9" - } - ], - "link":"bafyreifafftkh4x6zaaqdaskax2wqyqmn2tm5vqfxelxtpei26de73mrcu" - }, - "linkedBlock":"oWZoZWFkZXKiZnVuaXF1ZXBsYTBKUWJHaWN4VXhiSWova2NvbnRyb2xsZXJzgXg4ZGlkOmtleTp6Nk1rckIzVW4xaFQ1Z2JjQm1ZNUdpTWtmSk0yZ2dUWkJFeVpROFVzaXZzNTNucVM" + "get": { + "streamId": "kjzl6cwe1jw14a0hf5rym3xf00ecutbl84ltv1r6v80qtknynizifmdainlfonl", + "docId": "kjzl6cwe1jw14a0hf5rym3xf00ecutbl84ltv1r6v80qtknynizifmdainlfonl", + "commits": [ + { + "cid": "bagcqceraxyrmrdr7gbqhgemauyuqxh73l5gs77np7lzkzx74fmdv2s74xoiq", + "value": { + "jws": { + "payload": "AXESILIlWRB0lJcmijRqHmWKHt4V27wqYUwl0PrHkNFYgcfr", + "signatures": [ + { + "signature": "FqTvaE-IihnOu-1zds7-Uo3DSkIjjm2S04KP5GGhl5L9m3xq_CNsGul9PmYWHcMPEfQO1UUUzU7Vxens94XLBg", + "protected": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa295Q2NBYXFCS3ZvRWkzRnVtSFoxTnRKRXdjTjczQTZzakhqRjNSTWhCaGNjI3o2TWtveUNjQWFxQkt2b0VpM0Z1bUhaMU50SkV3Y043M0E2c2pIakYzUk1oQmhjYyJ9" + } + ], + "link": "bafyreifsevmra5eus4tiundkdzsyuhw6cxn3yktbjqs5b6whsdivraoh5m" + }, + "linkedBlock": "omRkYXRhomV1c2Vyc4KoZnBvaW50cxkHOmh0b2tlbl9pZPZqZGlzY29yZF9pZHI4MzY2MjE5NjkzMzU1MTcyMDRqdHdpdHRlcl9pZPZuZGlzY29yZF9oYW5kbGVmcHdwd3B3bnR3aXR0ZXJfaGFuZGxl9m53YWxsZXRfYWRkcmVzc3gqMHhiNGZmODYzNTgxZjdmNzNhZjA3ZTM1MDRlYTNlMDJiY2I4YzhjYWUzdWN1cnJlbnRfcGVyaW9kX3BvaW50cwCoZnBvaW50cxkJLmh0b2tlbl9pZGIxMWpkaXNjb3JkX2lkcjg4NjY5MjI3NDA2OTcxNzA3Mmp0d2l0dGVyX2lk9m5kaXNjb3JkX2hhbmRsZWVra29zc250d2l0dGVyX2hhbmRsZfZud2FsbGV0X2FkZHJlc3N4KjB4NTY1RDlhMjI0MDIyQTY1YzZFMURBQWI4OGQ4REI1NmNkYzY3OTQ2NXVjdXJyZW50X3BlcmlvZF9wb2ludHMAa21vZHVsZV9kYXRho2dnZW5lcmljoXBsYXRlc3RfdXBkYXRlX2lkYTVndHdpdHRlcqVuY3VycmVudF9wZXJpb2RqMjAyMy0wOS0wMXdsYXRlc3RfaGFzaHRhZ190d2VldF9pZHMxNjk3NzMxMDc5NzMyMzQzMDM3d2xhdGVzdF9tZW50aW9uX3R3ZWV0X2lkczE2OTc3MzEwNzk3MzIzNDMwMzd4HGxhc3RfdHdlZXRfcHVsbF93aW5kb3dfcmVzZXRxMTY5MzU4NzAyMC4zNTI0NzZ4HW51bWJlcl9vZl90d2VldHNfcHVsbGVkX3RvZGF5YjIza2R5bmFtaWNfbmZ0oXFsYXN0X3BhcnNlZF9ibG9ja2gxODA0NDU2NGZoZWFkZXKiZnVuaXF1ZXAxbEltNVE2K1lmeFA0SEIwa2NvbnRyb2xsZXJzgXg4ZGlkOmtleTp6Nk1rb3lDY0FhcUJLdm9FaTNGdW1IWjFOdEpFd2NONzNBNnNqSGpGM1JNaEJoY2M" + } } - } - ] - } + ] + } }, "/api/v0/commits": { "get": {}, @@ -123,26 +113,26 @@ }, "/api/v0/commits/centaurs_stream_id": { "get": { - "streamId":"kjzl6cwe1jw146ndq1g0kadxtqv72z9hr87zhelng6aw2s3ff00u7h7s4fi9kgq", - "docId":"kjzl6cwe1jw146ndq1g0kadxtqv72z9hr87zhelng6aw2s3ff00u7h7s4fi9kgq", + "streamId":"kjzl6cwe1jw147pkf71eur9z28t6mvsxc9pvna2sclp5ntuu4wes5r0wfkocufc", + "docId":"kjzl6cwe1jw147pkf71eur9z28t6mvsxc9pvna2sclp5ntuu4wes5r0wfkocufc", "commits":[ { - "cid":"bagcqcerag4vki7krkkgjrbwxdooz5wjq4muri5bp2kgtkdtjwfd5cfcj7xna", + "cid":"bagcqceramg4z2umh3llfhsifa6lssopgcgf6kyqvkveueubkdibhzzm27uea", "value":{ "jws":{ - "payload":"AXESIKApZqPy_sgBAYJKBfVoYgxups7WBbkXebyI14ZP7ZEV", + "payload":"AXESIBbHJu17hxefWTjVlZiKErcfVaxc9iy3DWaEU_Cw4P8L", "signatures":[ { - "signature":"BhpWFS-RoGPx4A1S4Xklovbk4px-ekwc9wTVO34PMy3cUTq7FDgZH4DBHckKhmQ-MOI87567zReQsdPKysFvAw", - "protected":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3JCM1VuMWhUNWdiY0JtWTVHaU1rZkpNMmdnVFpCRXlaUThVc2l2czUzbnFTI3o2TWtyQjNVbjFoVDVnYmNCbVk1R2lNa2ZKTTJnZ1RaQkV5WlE4VXNpdnM1M25xUyJ9" + "signature":"60_grbJKDG7xavezaX2ntc67Tmcnm8am6Ct2Pawnk5prfzm-DdMmavdTAGAjlycZKYk9HqsMJ2xFSdu9ZHeeCQ", + "protected":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa295Q2NBYXFCS3ZvRWkzRnVtSFoxTnRKRXdjTjczQTZzakhqRjNSTWhCaGNjI3o2TWtveUNjQWFxQkt2b0VpM0Z1bUhaMU50SkV3Y043M0E2c2pIakYzUk1oQmhjYyJ9" } ], - "link":"bafyreifafftkh4x6zaaqdaskax2wqyqmn2tm5vqfxelxtpei26de73mrcu" + "link":"bafyreiawy4to264hc6pvsogvswmiuevxd5k2yxhwfs3q2zuekpylbyh7bm" }, - "linkedBlock":"oWZoZWFkZXKiZnVuaXF1ZXBsYTBKUWJHaWN4VXhiSWova2NvbnRyb2xsZXJzgXg4ZGlkOmtleTp6Nk1rckIzVW4xaFQ1Z2JjQm1ZNUdpTWtmSk0yZ2dUWkJFeVpROFVzaXZzNTNucVM" + "linkedBlock":"omRkYXRhgaliaWRhMmRuYW1laUF1dG9ub2JvdGZtZW1vcnmCeREBIyBNZWV0IEF1dG9ub0JvdCwgeW91ciBmdW4gYW5kIGZyaWVuZGx5IGd1aWRlIHRvIGV2ZXJ5dGhpbmcgQXV0b25vbGFzISDwn6SW4pyoIAoKQXV0b25vQm90IHRhbGtzIGxpa2UgYSByZXRybyByb2JvdCBpbiBhIGdhbWUgYW5kIGlzIGhlcmUgdG8gYW5zd2VyIGFsbCB5b3VyIHF1ZXN0aW9ucyBhYm91dCBBdXRvbm9sYXMgaW4gYSBkZWxpZ2h0ZnVsIGFuZCBlbnRlcnRhaW5pbmcgd2F5LiBHbyBhaGVhZCwgYXNrIGF3YXksIGFuZCBsZXQgQXV0b25vQm90IGJyaW5nIGEgc21pbGUgdG8geW91ciBmYWNlIHdoaWxlIGtlZXBpbmcgeW91IGluZm9ybWVkIGFib3V0IHRoZSBleGNpdGluZyB3b3JsZCBvZiBBdXRvbm9sYXMhIPCfmITwn5qAIAoKQW5kIGRvbid0IHdvcnJ5LCBpZiBBdXRvbm9Cb3QgZG9lc24ndCBoYXZlIHRoZSBhbnN3ZXIsIGl0IHdpbGwgZG8gaXRzIGJlc3QgdG8gcG9pbnQgeW91IGluIHRoZSByaWdodCBkaXJlY3Rpb24gb3Igc3VnZ2VzdCByZXNvdXJjZXMgd2hlcmUgeW91IGNhbiBmaW5kIG1vcmUgaW5mb3JtYXRpb24uIFNvLCBsZXQncyBoYXZlIHNvbWUgZnVuIGFuZCBsZWFybiB0b2dldGhlciEgCgojIyBBdXRvbm9sYXMgV2hpdGVwYXBlciBTdW1tYXJ5CkF1dG9ub21vdXMgU2VydmljZXMgQXV0b25vbXkgaXMgYSBidXp6d29yZCB1c2VkIHRvIHNlbGwgZXZlcnl0aGluZyBmcm9tIHNlbGYtZHJpdmluZyBjYXJzIHRvIHRleHQgYW5kIGltYWdlLWdlbmVyYXRpbmcgQUlzLiBUb2RheSwgdGhlc2UgYXBwcyBhcmUgY2VudHJhbGx5IG93bmVkIGFuZCBjb250cm9sbGVkLiBVc2VycyB5aWVsZCBjb250cm9sIHRvIG9wYXF1ZSBhbGdvcml0aG1zIGFuZCBmb3JmZWl0IHRoZWlyIHByaXZhdGUgZGF0YSwgdHJhZGluZyBhd2F5IGh1bWFuIGF1dG9ub215IGZvciBtYWNoaW5lIGF1dG9ub215LCBzdWNoIGFzIHNlbGYtb3BlcmF0aW5nIG1hY2hpbmVzIGFuZCBzeXN0ZW1zLiAKCkF1dG9ub2xhcyBiZWxpZXZlcyB0aGF0IGF1dG9ub21vdXMgc2VydmljZXPigJRzb2Z0d2FyZSBzZXJ2aWNlcyB0aGF0IGNvbnRpbnVvdXNseSBvcGVyYXRlIGFuZCByZXF1aXJlIGxpdHRsZSB0byBubyBpbnB1dCBmcm9tIGh1bWFucyBieSBkZXNpZ27igJRlbmFibGUgaHVtYW4gYXV0b25vbXkgYmVzdCB3aGVuIHRoZXkgYXJlIHRyYW5zcGFyZW50LCByb2J1c3QsIGFuZCBkZWNlbnRyYWxseSBvd25lZCBhbmQgb3BlcmF0ZWQuIFdpdGggQXV0b25vbGFzLCB0aGUgYmVzdCBBSXMgd2lsbCBiZSBjby1vd25lZCBieSBjb2xsZWN0aXZlcyBvZiBodW1hbnMgYW5kIG9wZXJhdGVkIGFzIGF1dG9ub21vdXMgc2VydmljZXMgdG8gY2F0YWx5emUgaW5kaXZpZHVhbCBhdXRvbm9teS4gCgojIyBTbWFydCBDb250cmFjdHMgdnMuIEF1dG9ub21vdXMgU2VydmljZXMgU21hcnQKCioqQ29udHJhY3RzIGNhbm5vdDoqKiBEbyB0aGluZ3MgdGhhdCByZXF1aXJlIGV4cGVuc2l2ZSBwcm9jZXNzaW5nIFJ1biBjb250aW51b3VzbHkgQWNjZXNzIGRhdGEgbm90IG9uIHRoZSBzYW1lIGJsb2NrY2hhaW4sIGxpa2UgZXh0ZXJuYWwgQVBJcyBvciBvdGhlciBjaGFpbnMgCgoqKkF1dG9ub21vdXMgU2VydmljZXMgY2FuOioqIFJ1biBjb250aW51b3VzbHkgVGFrZSBhY3Rpb24gb24gdGhlaXIgb3duIEludGVyYWN0IHdpdGggdGhlIHdvcmxkIG91dHNpZGUgb2YgYmxvY2tjaGFpbnMgUnVuIGNvbXBsZXggbG9naWMgCgojIyBUZWNobmljYWwgQXJjaGl0ZWN0dXJlIAoKQXV0b25vbGFzIGF1dG9ub21vdXMgc29mdHdhcmUgc2VydmljZXMgYXJlIGVtYm9kaWVkIGFzIGFnZW50IHNlcnZpY2VzLCB3aGljaCBhcmUgZ3JvdXBzIG9mIGluZGVwZW5kZW50IGNvbXB1dGVyIHByb2dyYW1zIHRoYXQgaW50ZXJhY3Qgd2l0aCBlYWNoIG90aGVyIHRvIGFjaGlldmUgYSBwcmVkZXRlcm1pbmVkIGdvYWwuIFRoZXkgY2FuIGJlIHVuZGVyc3Rvb2QgYXMgbG9naWNhbGx5IGNlbnRyYWxpemVkIGFwcGxpY2F0aW9ucyAod2l0aCBvbmx5IG9uZSBhcHBsaWNhdGlvbiBzdGF0ZSBhbmQgbG9naWMpIHRoYXQgYXJlIHJlcGxpY2F0ZWQgaW4gYSBkaXN0cmlidXRlZCBzeXN0ZW0uIEFnZW50IHNlcnZpY2VzIGFyZSBtYWRlIG9mIGNvZGUgY29tcG9uZW50cyB0aGF0IGNhbiBiZSBjb21iaW5lZCBsaWtlIExlZ28gYnJpY2tzIHRocm91Z2ggc29mdHdhcmUgY29tcG9zaXRpb24uIFRoaXMgaXMgZW5hYmxlZCBhbmQgaW5jZW50aXZpemVkIGJ5IHRoZSBvbi1jaGFpbiBwcm90b2NvbCwgd2hpY2ggZmFjaWxpdGF0ZXMgZGV2ZWxvcGVycyBwdWJsaXNoaW5nIGFuZCBmaW5kaW5nIGNvZGUgY29tcG9uZW50cyB0byBidWlsZCBhbmQgZXh0ZW5kIG5ldyBzZXJ2aWNlcy4gVGhlIG9uLWNoYWluIHByb3RvY29sIGltcGxlbWVudHMgcmVnaXN0cmllcyB0aGF0IGVuYWJsZSBjb2RlIGNvbXBvbmVudHMsIGFnZW50cywgYW5kIHNlcnZpY2VzIHRvIGJlIGZvdW5kLCByZXVzZWQsIGFuZCBlY29ub21pY2FsbHkgY29tcGVuc2F0ZWQuIAoKKipUaGUgbWFpbiBlbGVtZW50cyBvZiB0aGUgQXV0b25vbGFzIHRlY2ggc3RhY2sgYXJlOioqIEFnZW50IHNlcnZpY2VzIG1haW50YWluZWQgYnkgYSBzZXJ2aWNlIG93bmVyIGFuZCBydW4gYnkgbXVsdGlwbGUgb3BlcmF0b3JzLCB3aG8gZXhlY3V0ZSBpbmRlcGVuZGVudCBhZ2VudCBpbnN0YW5jZXMgKHRoYXQgcnVuIHRoZSBzYW1lIGNvZGUpOyB0aGVzZSBpbnN0YW5jZXMgY29vcmRpbmF0ZSB0aHJvdWdoIGEgY29uc2Vuc3VzIGdhZGdldC4gQ29tcG9zYWJsZSBhdXRvbm9tb3VzIGFwcHMgYnVpbHQgb3V0IG9mIGJhc2ljIGFwcGxpY2F0aW9ucyB0aGF0IGFyZSBlYXNpbHkgZXh0ZW5kYWJsZSBhbmQgY29tcG9zYWJsZSBpbnRvIGhpZ2hlci1vcmRlciBhcHBsaWNhdGlvbnMuIEFuIG9uLWNoYWluIHByb3RvY29sIG9uIGEgcHJvZ3JhbW1hYmxlIGJsb2NrY2hhaW4gdGhhdCBzZWN1cmVzIGFnZW50IHNlcnZpY2VzIGFuZCBpbmNlbnRpdml6ZXMgZGV2ZWxvcGVycyB0byBjb250cmlidXRlIGNvZGUgdG8gdGhpcyBwcm90b2NvbC4gCgojIyBUb2tlbm9taWNzIAoKQXV0b25vbGFzIHRva2Vub21pY3MgZm9jdXNlcyBvbiB0aHJlZSBvYmplY3RpdmVzOiAKCjEvIEdyb3dpbmcgY2FwaXRhbCBhbmQgY29kZSBwcm9wb3J0aW9uYWxseTogT24tY2hhaW4gbWVjaGFuaXNtcyBlbnN1cmUgdGhhdCB0aGUgY29kZSBwcm92aWRlZCBieSBkZXZlbG9wZXJzIGlzIHJld2FyZGVkIGFjY29yZGluZyB0byBpdHMgdXNlZnVsbmVzcyB0byB0aGUgc2VydmljZXMgb3BlcmF0ZWQgb24gdGhlIHByb3RvY29sLiBUaGUgcHJvdG9jb2wgYWNxdWlyZXMgcHJvdG9jb2wtb3duZWQgbGlxdWlkaXR5IChQb0wpIGluIHByb3BvcnRpb24gdG8gY29kZSB1c2VmdWxuZXNzLCBhbGxvd2luZyB0aGUgcHJvdG9jb2wgdG8gZ2VuZXJhdGUgcmV0dXJucywgaW52ZXN0IGluIHNlcnZpY2VzLCBhbmQgZ3VhcmFudGVlIGl0cyBsb25nLXRlcm0gZmluYW5jaWFsIGhlYWx0aC4gCgoyLyBFbmFibGluZyBpbnRyYS0gYW5kIGludGVyLXByb3RvY29sIGNvbXBvc2FiaWxpdHk6IE5GVHMgcmVwcmVzZW50aW5nIGNvZGUgYW5kIHNlcnZpY2VzIGFyZSB1c2VkIHRvIHRyYWNrIGNvbnRyaWJ1dGlvbnMgaW5zaWRlIHRoZSBwcm90b2NvbCwgYWNjcnVlIHJld2FyZHMsIGFuZCBjYW4gYmUgdXNlZCBwcm9kdWN0aXZlbHkgYXMgY29sbGF0ZXJhbCBhY3Jvc3MgRGVGaS4gCgozLyBJbmNlbnRpdml6aW5nIHRoZSBkb25hdGlvbiBvZiBwcm9maXRzIGZyb20gUHJvdG9jb2wtb3duZWQgU2VydmljZXMgKFBvU2UpOiBBdXRvbm9tb3VzIHNlcnZpY2VzIG93bmVkIGJ5IGdvdmVybmFuY2Ugb2YgdmFyaW91cyBEQU9zLCBvcGVyYXRlZCBieSB0aGUgZWNvc3lzdGVtLCBhbmQgZGV2ZWxvcGVkIGJ5IGFnZW50IGRldmVsb3BlcnMgd29ybGR3aWRlIGRvbmF0ZSBzb21lIG9mIHRoZWlyIHByb2ZpdHMgdG8gdGhlIHByb3RvY29sLiAKCiMjIFVzZSBDYXNlcyBmb3IgQXV0b25vbW91cyBTZXJ2aWNlcyAKCkEgbGFyZ2UgbWFya2V0IGZvciBhdXRvbm9tb3VzIGFnZW50IHNlcnZpY2VzIGlzIGVtZXJnaW5nLCBwcmltYXJpbHkgZm9jdXNlZCBvbiBpbXByb3ZpbmcgREFPIG9wZXJhdGlvbnMuIEF1dG9ub21vdXMgc2VydmljZXMgbWFrZSBEQU9zIG1vcmUgY29tcGV0aXRpdmUgYnkgcHJvdmlkaW5nIHJpY2hlciBtZWFucyBmb3IgdHJhbnNwYXJlbnRseSBjb29yZGluYXRpbmcgaHVtYW4gYWN0b3JzIGFuZCBleGVjdXRpbmcgcHJvY2Vzc2VzIHdpdGggbGl0dGxlIG9yIG5vIG1hcmdpbmFsIGh1bWFuIGlucHV0LiBBdXRvbm9tb3VzIHNlcnZpY2VzIGNhbiBiZSBjb21wb3NlZCBvZiB0aHJlZSBmdW5kYW1lbnRhbCBMZWdvIGJsb2NrczogS2VlcGVycywgT3JhY2xlcywgYW5kIEJyaWRnZXMueQYaVGhpcyBjb21wb3NhYmlsaXR5IGxlYWRzIHRvIGNvbWJpbmF0b3JpYWwgZXhwYW5zaW9uIGFuZCB1bnByZWNlZGVudGVkIG5ldyBhcHBsaWNhdGlvbnMuIAoKIyMgR292ZXJuYW5jZSAKCkEgY3J1Y2lhbCBlbGVtZW50IG9mIHRoZSBzdWNjZXNzIG9mIEF1dG9ub2xhcyBpcyB0byBoYXZlIGFuIGFjdGl2ZSBjb21tdW5pdHkgYW5kIGVjb3N5c3RlbSB0aGF0IGJvdGggYnVpbGQsIGV2b2x2ZSwgcHJvbW90ZSwgYW5kIG1ha2UgdXNlIG9mIEF1dG9ub2xhcyB0ZWNobm9sb2d5LiBGb3IgdGhpcyByZWFzb24sIEF1dG9ub2xhcyBpcyBvcmdhbml6ZWQgYXMgYSBEQU8gd2hlcmUgbWVhbmluZ2Z1bCBjb250cmlidXRvcnMgYW5kIHN1cHBvcnRlcnMgcGFydGljaXBhdGUgaW4gdGhlIGRlY2lzaW9uLW1ha2luZyBwcm9jZXNzLiAKCkluaXRpYWxseSwgaG9sZGVycyBvZiB0aGUgdmlydHVhbGl6ZWQgdmVPTEFTIHRva2VuIGNhbiBwYXJ0aWNpcGF0ZSBpbiBhbnkgZ292ZXJuYW5jZSBhY3Rpdml0aWVzLiBUaGUgdmVPTEFTIHRva2VuIGlzIG9idGFpbmVkIGJ5IGxvY2tpbmcgT0xBUywgd2hpY2ggaXMgdGhlIG5hdGl2ZSB0b2tlbiBvZiBBdXRvbm9sYXMuIEdvdmVybmFuY2UgcGFydGljaXBhdGlvbiBpcyBwcm9wb3J0aW9uYWwgdG8gdmVPTEFTIGhvbGRpbmdzIGFuZCB0aGVpciBsb2NraW5nIGR1cmF0aW9uLiBHb3Zlcm5hbmNlIHByb3Bvc2FscyBjYW4gbm90YWJseSBtb2RpZnkgc3lzdGVtIHBhcmFtZXRlcnMsIHN1cHBvcnQgbmV3IHRlY2hub2xvZ2ljYWwgZGlyZWN0aW9ucywgb3IgYWRkIGVudGlyZWx5IG5ldyBmdW5jdGlvbmFsaXR5IHRvIHRoZSBvbi1jaGFpbiBwcm90b2NvbC4gCgpPbmNlIGEgZ292ZXJuYW5jZSBwcm9wb3NhbCBpcyBhcHByb3ZlZCwgdGhlIFRpbWVsb2NrIGFkZHMgYSBkZWxheSBmb3IgdGhlIHByb3Bvc2FsIHRvIGJlIGV4ZWN1dGVkLiAKCkV4Y2VwdGlvbmFsbHksIHNvbWUgY2hhbmdlcyB0byB0aGUgQXV0b25vbGFzIG9uLWNoYWluIHByb3RvY29sIGNvdWxkIGJlIGV4ZWN1dGVkIGJ5IGEgY29tbXVuaXR5LW93bmVkIG11bHRpLXNpZyB3YWxsZXQsIGJ5cGFzc2luZyB0aGUgZ292ZXJuYW5jZSBwcm9jZXNzLiAKClRoaXMgYWxsb3dzIGEgc2V0IG9mIHRydXN0ZWQgYWN0b3JzIHRvIG92ZXJydWxlIGdvdmVybmFuY2UgaW4gY2VydGFpbiBhc3BlY3RzLCBlLmcuLCBhIHNlY3VyaXR5IGV4cGxvaXQgdGhhdCBuZWVkcyB0byBiZSBwYXRjaGVkIHdpdGhvdXQgZ292ZXJuYW5jZSBkaXNjdXNzaW9uLiAKCiMjIEZvbGxvdyBBdXRvbm9sYXM6IApXZWJzaXRlOiBbYXV0b25vbGFzLm5ldHdvcmtdKGh0dHBzOi8vYXV0b25vbGFzLm5ldHdvcmspCgpUd2l0dGVyOiBbdHdpdHRlci5jb20vYXV0b25vbGFzXShodHRwczovL3R3aXR0ZXIuY29tL2F1dG9ub2xhcykKCkRpc2NvcmQ6IFtkaXNjb3JkLmNvbS9pbnZpdGUvejJQVDY1aktxUV0oZGlzY29yZC5jb20vaW52aXRlL3oyUFQ2NWpLcVEpCgpWYWxvcnk6IFt2YWxvcnkueHl6XShodHRwczovL3ZhbG9yeS54eXopIFthdXRvbm9sYXMubmV0d29ya10oaHR0cHM6Ly9hdXRvbm9sYXMubmV0d29yaylnYWN0aW9uc5hlpGhjb21taXRJZHg9YmFnY3FjZXJhbHRmZG1xZGoyb3l2eTI2YTdrNzNtcjNuYXV3eXl6N2x0N2M0d3lnajZzeGl5ZW9weW10cWl0aW1lc3RhbXAbAAABiOdCPGprZGVzY3JpcHRpb25yam9pbmVkIHRoZSBjZW50YXVybGFjdG9yQWRkcmVzc3gqMHg3YjIyQzFkYjlFQjkwMTRjMGQ2MkQxOGE1ODdkQTc5RDc1NDY1ZjA0pGhjb21taXRJZHg9YmFnY3FjZXJhZ3FocHJlaHNubDV5dWdvamNtNmphdnhmbzJwd2pmbm5tZ3Q2eXl0cXhsdTQ2dGFtb2U0cWl0aW1lc3RhbXAbAAABiOdCNLBrZGVzY3JpcHRpb25yam9pbmVkIHRoZSBjZW50YXVybGFjdG9yQWRkcmVzc3gqMHg3YjIyQzFkYjlFQjkwMTRjMGQ2MkQxOGE1ODdkQTc5RDc1NDY1ZjA0pGlvdXRwdXRVcmx4W2h0dHBzOi8vYXBwLm9yYmlzLmNsdWIvcG9zdC9ranpsNmN3ZTFqdzE0N3Izb3o4bTlzcDNmcmM2cHdldmFmMXBueTU4cjRnM3VzNW9mcGVucTI0OW90b2JramlpdGltZXN0YW1wGwAAAYiVwANoa2Rlc2NyaXB0aW9ub3Bvc3RlZCB0byBPcmJpc2xhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa3JZelhyMTZCM1FIcmJDMUxTZEh3TjM2ZHRXeHhqOUxOdUw1OGJFZG1Fa3p5pGlvdXRwdXRVcmx4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NjY0MTYxNDY4NDM1OTA2NTdpdGltZXN0YW1wGwAAAYiVv53Ya2Rlc2NyaXB0aW9ucXBvc3RlZCB0byBUd2l0dGVybGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaGNvbW1pdElkeD1iYWdjcWNlcmFmazc3ZmhlanhpcWlvcmd2dG13eTR6cmpuc2pnbHNpNXAzM2pjd2RtbjVrcmhld2ZzdnBxaXRpbWVzdGFtcBsAAAGIkP6xk2tkZXNjcmlwdGlvbnJqb2luZWQgdGhlIGNlbnRhdXJsYWN0b3JBZGRyZXNzeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjKkaW91dHB1dFVybHhbaHR0cHM6Ly9hcHAub3JiaXMuY2x1Yi9wb3N0L2tqemw2Y3dlMWp3MTQ5ZDg5N3pwMnllcWdla2J1dG5yeTU1NDh2Ymh4eXBseXNtcmM2dmwwNDcya2h1dDczZ2l0aW1lc3RhbXAbAAABiHwihKhrZGVzY3JpcHRpb25vcG9zdGVkIHRvIE9yYmlzbGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY2NDYxMzY0MjI1ODU4NzY0OGl0aW1lc3RhbXAbAAABiHwiJuhrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRpb3V0cHV0VXJseD1odHRwczovL3R3aXR0ZXIuY29tL2xhdW5jaGNlbnRhdXJzL3N0YXR1cy8xNjY0MjQ5MjU2NjAzOTQyOTE5aXRpbWVzdGFtcBsAAAGIdvTdeGtkZXNjcmlwdGlvbnFwb3N0ZWQgdG8gVHdpdHRlcmxhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa3JZelhyMTZCM1FIcmJDMUxTZEh3TjM2ZHRXeHhqOUxOdUw1OGJFZG1Fa3p5pGlvdXRwdXRVcmx4W2h0dHBzOi8vYXBwLm9yYmlzLmNsdWIvcG9zdC9ranpsNmN3ZTFqdzE0Nmo3cnlpM2w5eTQybmgxYXNieWowNzZzYm9iMjJxZTBuMmF2dGtzYXhjOWoycGJrbndpdGltZXN0YW1wGwAAAYh29N14a2Rlc2NyaXB0aW9ub3Bvc3RlZCB0byBPcmJpc2xhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa3JZelhyMTZCM1FIcmJDMUxTZEh3TjM2ZHRXeHhqOUxOdUw1OGJFZG1Fa3p5pGlvdXRwdXRVcmx4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NjM4ODY2NzIzNjEwMjk2MzZpdGltZXN0YW1wGwAAAYhxzcIQa2Rlc2NyaXB0aW9ucXBvc3RlZCB0byBUd2l0dGVybGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHhbaHR0cHM6Ly9hcHAub3JiaXMuY2x1Yi9wb3N0L2tqemw2Y3dlMWp3MTQ4eDd1cThjMXN1M2E5aGUzeXFmNHVia3dkaDZ4cWhlYmthOWt5Z2VoMGI1ZHp6dDJ2OGl0aW1lc3RhbXAbAAABiHHNwhBrZGVzY3JpcHRpb25vcG9zdGVkIHRvIE9yYmlzbGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY2MzE2MjAyOTY3NzQ1NzQwOWl0aW1lc3RhbXAbAAABiGeBjuBrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRpb3V0cHV0VXJseFtodHRwczovL2FwcC5vcmJpcy5jbHViL3Bvc3Qva2p6bDZjd2UxancxNGIzZHZuMjJleHMwOXdoNGtpbDg5cTdrd3IycDRybDdwdWR3dnJxb3d0bWVsYm95cmZlaXRpbWVzdGFtcBsAAAGIZ4GO4GtkZXNjcmlwdGlvbm9wb3N0ZWQgdG8gT3JiaXNsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRoY29tbWl0SWR4PWJhZ2NxY2VyYXNiaTdoNGF0aWxqNGFkcHQ3eXdyNzVic25neXlqMmxwb3Fkcmt5NXhwajNyc2ltbTNsN2FpdGltZXN0YW1wGwAAAYhdKQ/7a2Rlc2NyaXB0aW9ucHVwZGF0ZWQgYSBtZW1vcnlsYWN0b3JBZGRyZXNzeCoweGY0YTY5NzI1MzI4NUEwMkM3MERlOTVjOUNiYTVBNjQ1MDYxYzlFMjakaGNvbW1pdElkeD1iYWdjcWNlcmF2dWc2a3NwajNmeTNmdmpjMzZhbXFxaWdxMmR4ZmFhb3NoMzYyZDI0NnVwczQ0cXlkbWFxaXRpbWVzdGFtcBsAAAGIXSb0IGtkZXNjcmlwdGlvbnB1cGRhdGVkIGEgbWVtb3J5bGFjdG9yQWRkcmVzc3gqMHhmNGE2OTcyNTMyODVBMDJDNzBEZTk1YzlDYmE1QTY0NTA2MWM5RTI2pGhjb21taXRJZHg9YmFnY3FjZXJhYndxb2t2Zm0yanhmZHVnN2x3eW5xNDc1YWdkYnc2bGx2ZzJudGpybzd1azRlbGh5N3hlYWl0aW1lc3RhbXAbAAABiF0lpt1rZGVzY3JpcHRpb25wdXBkYXRlZCBhIG1lbW9yeWxhY3RvckFkZHJlc3N4KjB4ZjRhNjk3MjUzMjg1QTAyQzcwRGU5NWM5Q2JhNUE2NDUwNjFjOUUyNqRoY29tbWl0SWR4PWJhZ2NxY2VyYTdrM3c3NzJlZ2tmeW4zZXJsc2I1Y3U1eGFzamszMjQycmVxMzZvcnFkdG90aWtzNmlmNWFpdGltZXN0YW1wGwAAAYhdIEg2a2Rlc2NyaXB0aW9ucmpvaW5lZCB0aGUgY2VudGF1cmxhY3RvckFkZHJlc3N4KjB4ZjRhNjk3MjUzMjg1QTAyQzcwRGU5NWM5Q2JhNUE2NDUwNjFjOUUyNqRpb3V0cHV0VXJseD1odHRwczovL3R3aXR0ZXIuY29tL2xhdW5jaGNlbnRhdXJzL3N0YXR1cy8xNjYyMDc1OTM1Mjk2ODIzMjk3aXRpbWVzdGFtcBsAAAGIWBJbEGtkZXNjcmlwdGlvbnFwb3N0ZWQgdG8gVHdpdHRlcmxhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa3JZelhyMTZCM1FIcmJDMUxTZEh3TjM2ZHRXeHhqOUxOdUw1OGJFZG1Fa3p5pGlvdXRwdXRVcmx4W2h0dHBzOi8vYXBwLm9yYmlzLmNsdWIvcG9zdC9ranpsNmN3ZTFqdzE0Nm82N2cxZmQzbW4wcGp3dmtzMDQzYnF3cTM0dnMyazZwNTltMThqd3NhcDNwNzU0NnNpdGltZXN0YW1wGwAAAYhYElsQa2Rlc2NyaXB0aW9ub3Bvc3RlZCB0byBPcmJpc2xhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa3JZelhyMTZCM1FIcmJDMUxTZEh3TjM2ZHRXeHhqOUxOdUw1OGJFZG1Fa3p5pGlvdXRwdXRVcmx4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NjE3MTE5NzExNjEzNTAxNDVpdGltZXN0YW1wGwAAAYhS5qvIa2Rlc2NyaXB0aW9ucXBvc3RlZCB0byBUd2l0dGVybGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHhbaHR0cHM6Ly9hcHAub3JiaXMuY2x1Yi9wb3N0L2tqemw2Y3dlMWp3MTQ4azV5NjI5Ym1zMmtsb3dvbTZpZXpqOHVzcHZ6NzNqZmh2YmNidmxreHpwNHVyajdidGl0aW1lc3RhbXAbAAABiFLmq8hrZGVzY3JpcHRpb25vcG9zdGVkIHRvIE9yYmlzbGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY2MTM1ODM1MjcyOTgxNzA5MGl0aW1lc3RhbXAbAAABiE3fqyBrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRpb3V0cHV0VXJseFtodHRwczovL2FwcC5vcmJpcy5jbHViL3Bvc3Qva2p6bDZjd2UxancxNDk0amh4b3Q0Y2xuaXFza282amVhNzRta3NveW5yNW1mdmZ3Z2VldnB0NmNjcnJzYmZzaXRpbWVzdGFtcBsAAAGITd+rIGtkZXNjcmlwdGlvbm9wb3N0ZWQgdG8gT3JiaXNsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRoY29tbWl0SWR4PWJhZ2NxY2VyYXNocnRwaXNkbTN5bDNqcHBjdG13ZXl5amFibnVkdW1tcGN4enZvYmVyenluZ3ZlNnNxa3FpdGltZXN0YW1wGwAAAYg0qfGZa2Rlc2NyaXB0aW9ucHJlbW92ZWQgYSBtZW1vcnlsYWN0b3JBZGRyZXNzeCoweDdiMjJDMWRiOUVCOTAxNGMwZDYyRDE4YTU4N2RBNzlENzU0NjVmMDSkaGNvbW1pdElkeD1iYWdjcWNlcmF0aDNvYXhsNmJkN3k2ejV5YzN4Nm5hMmpyYnF2bmJnem5rN3ViZXE3bTZxMmdtc2FjM2NhaXRpbWVzdGFtcBsAAAGINKkGS2tkZXNjcmlwdGlvbm5hZGRlZCBhIG1lbW9yeWxhY3RvckFkZHJlc3N4KjB4N2IyMkMxZGI5RUI5MDE0YzBkNjJEMThhNTg3ZEE3OUQ3NTQ2NWYwNKRoY29tbWl0SWR4PWJhZ2NxY2VyYWM3c211a2FoZml0NHN2ZHhlZjIzc3hmc3Azbnl4MjRvb2k3ZDdveDVzYWV3Z3I1bTRscnFpdGltZXN0YW1wGwAAAYg0qBvSa2Rlc2NyaXB0aW9ucmpvaW5lZCB0aGUgY2VudGF1cmxhY3RvckFkZHJlc3N4KjB4N2IyMkMxZGI5RUI5MDE0YzBkNjJEMThhNTg3ZEE3OUQ3NTQ2NWYwNKRpb3V0cHV0VXJseFtodHRwczovL2FwcC5vcmJpcy5jbHViL3Bvc3Qva2p6bDZjd2UxancxNDg0ZjUyczBseGxoMm9vcDBuY3d4dG1xaDNieGluenFqNHN2NGpnaWtkeGt4YzhieWtkaXRpbWVzdGFtcBsAAAGINJWMIGtkZXNjcmlwdGlvbm9wb3N0ZWQgdG8gT3JiaXNsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRoY29tbWl0SWR4PWJhZ2NxY2VyYTJlN200cDRiZWpuYmFkb2QyaHY2MzZndnBscm9mcmp4aXkzdmFtZ29vbWVxdXdxYWJpdWFpdGltZXN0YW1wGwAAAYjn7oAOa2Rlc2NyaXB0aW9ucmpvaW5lZCB0aGUgY2VudGF1cmxhY3RvckFkZHJlc3N4KjB4NzdCMmQ4ODI5OUE0MDg0NWU4RmZiRTlFZGM0QkY2ZTg5MTM2YzYwZKRoY29tbWl0SWR4PWJhZ2NxY2VyYTd4bTZxYWRhcHJpbGp0amNzNjc2endqZWY3cWJ4bnVmY3Y0MmZ3a2licDIzNTVuZ2pwaHFpdGltZXN0YW1wGwAAAYkCCnXFa2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaGNvbW1pdElkeD1iYWdjcWNlcmF4d3p0dTZqanp2dDI0aWxhdjJwNHJ5ejZodWsyejc0dGlscXo2czNwdW55c2dveW93cjNxaXRpbWVzdGFtcBsAAAGJAgqQBGtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2pGhjb21taXRJZHg9YmFnY3FjZXJhZWQ1bG91eno3bHl5emZ6NDRjZWxocWh0bWZ6dDNsY2w0MnMyNWVrYnl0dW1zZXphZWltYWl0aW1lc3RhbXAbAAABiQZExs9rZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M6RoY29tbWl0SWR4PWJhZ2NxY2VyYW5oYXQzcGtvcG5oZTU1NnpndmVtdGZ1bTRqYTVsaWFia3BpbmR4aG1zaHdyMnA0MmRzYmFpdGltZXN0YW1wGwAAAYkGkYrya2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjKkaGNvbW1pdElkeD1iYWdjcWNlcmFmY3ZnZHZtcXVnYmRleTJzN3pramJjb3dreGxkdGY3bGZ4dGlybGd0NGs1aW94NGo1ZzZhaXRpbWVzdGFtcBsAAAGJB+Dpz2tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3pGhjb21taXRJZHg9YmFnY3FjZXJhM21xeGhzMzZtYTJxYnVoZWYzNmducmEyN3lsc2toNjVuaGNlNXJ1eW1tZWRudWVzZDNscWl0aW1lc3RhbXAbAAABiQfhEKdrZGVzY3JpcHRpb25zZXhlY3V0ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NmM2NzY2RTA0ZUY5NzEzNjdEMjdFNzIwZDFkMTYxYTlCNDk1RDY0N6RoY29tbWl0SWR4PWJhZ2NxY2VyYWh4M2UzMmVsM3h0ejNjdGRzaWpjM3BhYXFpdGlmb3locGc0cmJjM3l0djVudHl1eXN1bWFpdGltZXN0YW1wGwAAAYkLaMmaa2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDZjNjc2NkUwNGVGOTcxMzY3RDI3RTcyMGQxZDE2MWE5QjQ5NUQ2NDekaGNvbW1pdElkeD1iYWdjcWNlcmFpMm5qbHRpZmJqNGV2ZG1lcmhyazdweml3Nmhjb3RveWxuamlnem54MnVrY2J5b2R3eWFxaXRpbWVzdGFtcBsAAAGJC2knomtkZXNjcmlwdGlvbnNleGVjdXRlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3pGhjb21taXRJZHg9YmFnY3FjZXJhbHl3eTVqc2NrbjRzNDNvZWU2N3hrc3ZsZGRhZmR3M3pmeXJ3MmtmcGI0NGczY2F4ZGZjYWl0aW1lc3RhbXAbAAABiQtq9RRrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NmM2NzY2RTA0ZUY5NzEzNjdEMjdFNzIwZDFkMTYxYTlCNDk1RDY0N6RoY29tbWl0SWR4PWJhZ2NxY2VyYW1lYngzM3lraGpranlwbTdlZnJ5eHpkNzN2ejVlbTJ4NXByenIzenVubGF5N3J1ZW1oYXFpdGltZXN0YW1wGwAAAYkLaxEva2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaGNvbW1pdElkeD1iYWdjcWNlcmFmcnN1NjdzdG83M29sd3JkZGdsd2hjeG52ejViaHNoeWtna2NhZ25nazRqdDRuNjd3cHpxaXRpbWVzdGFtcBsAAAGJC3L/FWtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhlZTk1MzMzRDBFMWJlMzkzRUI1ZDhiQTA5ZUUwYjVjRjcxZTM0NDUzpGhjb21taXRJZHg9YmFnY3FjZXJheGpncWxnNG16ZTVybXVidWF3bHY0YmFuZTVlb2x3bXBuMm13c2RpMnZpZmhjNWhwcHhxYWl0aW1lc3RhbXAbAAABiQuhfRNrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NUI3M0YyRGI2QTIzQjMwNDRjNGY2ODJhMUYxM0E4RTEyQWJEQzAxZKRoY29tbWl0SWR4PWJhZ2NxY2VyYTRxdzdkc3g2czd3YmxvemFuZHZwbDVjczN0eWtkZGxicnQ3MnB6anpkdnRxZjJnbGx6eHFpdGltZXN0YW1wGwAAAYkLpxiAa2Rlc2NyaXB0aW9uc2V4ZWN1dGVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaGNvbW1pdElkeD1iYWdjcWNlcmFhYTM1YWd4ZjV5ZnNtbTVtbDJqcXBnaDN0dTQ2MmtyYWhyMmJlaWo2NGtvbWUyNWMzZ2lxaXRpbWVzdGFtcBsAAAGJC99uvWtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhjYkFGNzUwRTI3YTZFRkE0MGY0Qjk4Q2VBMDAyMDNjMWJDOTJmNjYypGlvdXRwdXRVcmx4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NzU5MDE5NjE3MjIyOTQyNzJpdGltZXN0YW1w+0HZKL08n80Da2Rlc2NyaXB0aW9ucXBvc3RlZCB0byBUd2l0dGVybGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rcll6WHIxNkIzUUhyYkMxTFNkSHdOMzZkdFd4eGo5TE51TDU4YkVkbUVrenmkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY3NTkwMzkwODM3NDM2MDA3MWl0aW1lc3RhbXD7QdkovbCmjhVrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRoY29tbWl0SWR4PWJhZ2NxY2VyYTRpaGN2Z3U1NGxvYXdqa3JvZmRncXZhMmpoNWt4aDR0bDRqZzNscWpsNWNoZXhpbjc1enFpdGltZXN0YW1wGwAAAYkmq4/ra2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDk5MDkzNTEwYUI5RjYwQTQyNTgxN2VCRTgxRkNDMzk2ZERkYTZkNUGkaGNvbW1pdElkeD1iYWdjcWNlcmF2amZkZ3Jqa281YmNxZDJiZjM2dmdhNWo1ZnZjZ3Y2dHduaXByd3g1czJ5aGV3bHV0MjZhaXRpbWVzdGFtcBsAAAGJJrT0tmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2pGhjb21taXRJZHg9YmFnY3FjZXJhb2NlcmZ3dnVrbjdhZmNuYjMydGQ3ZWZ3Zm96b2JoZmphdXR2N2l0ZGhjNWI1c3l0YjN3cWl0aW1lc3RhbXAbAAABiSa1CfFrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M6RoY29tbWl0SWR4PWJhZ2NxY2VyYWltc3kyeXczZDVrNjZiM2xhcXpiMjRybzZ1dmczM29kZWx3c3JyeWhwdHVwYmZ1cmRuZ3FpdGltZXN0YW1wGwAAAYkm3rAZa2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjKkaGNvbW1pdElkeD1iYWdjcWNlcmFidDNxYnNzNmtoczZ4aTRxc2lkdmVmZXJ5Zm40a2dlMjZ4M2d0c2FwNmVmMnNzaGlod3RhaXRpbWVzdGFtcBsAAAGJJuijXmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkpGhjb21taXRJZHg9YmFnY3FjZXJhdWI1cG42M3lreng0aGFmcWxwazVjbmZ0eGxkamFqZ3JyM29lNWZha29xNnIyZXV0N3VqYWl0aW1lc3RhbXAbAAABiSb3sLlrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4OTkwOTM1MTBhQjlGNjBBNDI1ODE3ZUJFODFGQ0MzOTZkRGRhNmQ1QaRoY29tbWl0SWR4PWJhZ2NxY2VyYXlid3Q0dDIzemE1dm02b2N4Ymx5aXQ2aWZpN2R4dmJyZWI1aW4zcm5sc2t2NmdxdzR2enFpdGltZXN0YW1wGwAAAYknCAgra2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDk5MDkzNTEwYUI5RjYwQTQyNTgxN2VCRTgxRkNDMzk2ZERkYTZkNUGkaGNvbW1pdElkeD1iYWdjcWNlcmFwYzRsNmJkcnZveHFra3BnMjZ5azI2dmh3Nm5ucDY2dWR5dXF5cWp1ejZmd3BtcWJscmdhaXRpbWVzdGFtcBsAAAGJJwjemWtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBpGhjb21taXRJZHg9YmFnY3FjZXJhaDVwM3FiZmFvbnQ1ZWVqaW1ncDY0ZWxqeGYzdXR3eDRzdHJ2M3cydWV5bzVtY2JraTJ6cWl0aW1lc3RhbXAbAAABiScOtzprZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M6RoY29tbWl0SWR4PWJhZ2NxY2VyYTczbXNvZ3ZidDRqb2dwamg0c3Y0aG96d2IzYnNwZGxvbmhtd3EzdGRzZnNndXd1eGNyZ3FpdGltZXN0YW1wGwAAAYknIVZ7a2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaGNvbW1pdElkeD1iYWdjcWNlcmF3cTViaGYzNjd1ejYzbzR5Z3RmeWVpc21qYnVicHZ2YmZ2Z2Vqd2NkYXNpd255bjVra3pxaXRpbWVzdGFtcBsAAAGJJyNA52tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkpGhjb21taXRJZHg9YmFnY3FjZXJha2s3bXI1bnd6aDZ3eTVsZ3VmN3gyaXllc255dHNodjNjM2pheTZqeGlwbnhiZWZ5dHZncWl0aW1lc3RhbXAbAAABiScyfCJrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4Y2JBRjc1MEUyN2E2RUZBNDBmNEI5OENlQTAwMjAzYzFiQzkyZjY2MqRoY29tbWl0SWR4PWJhZ2NxY2VyYTN2Y2lkeWZzZHFodTUyYmxnMnhsbGV6d3I1bDJkbWh1cjdvNWpxdjRodWRlcHpueXg0YWFpdGltZXN0YW1wGwAAAYknNCsDa2Rlc2NyaXB0aW9uc2V4ZWN1dGVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDk5MDkzNTEwYUI5RjYwQTQyNTgxN2VCRTgxRkNDMzk2ZERkYTZkNUGkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY3NjY1MjAyNTY3OTg0NzQ0MWl0aW1lc3RhbXD7Qdkpa9/10gtrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtyWXpYcjE2QjNRSHJiQzFMU2RId04zNmR0V3h4ajlMTnVMNThiRWRtRWt6eaRoY29tbWl0SWR4PWJhZ2NxY2VyYTZwc3VudDUyNWI1NHJwbnR2MzY1ZTV0Z2l4NHVycXkyeGFwanlrZWNtZ3ZmNmsybHBxeHFpdGltZXN0YW1wGwAAAYksGrVaa2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDZjNjc2NkUwNGVGOTcxMzY3RDI3RTcyMGQxZDE2MWE5QjQ5NUQ2NDekaGNvbW1pdElkeD1iYWdjcWNlcmFkdnVlNWVucXd1aHo1YmY2dG5jZW1kZHV0Z2d1b3p0dXJvYm96bnUybGg2NmIydGdzdW5xaXRpbWVzdGFtcBsAAAGJLBrZzWtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3pGhjb21taXRJZHg9YmFnY3FjZXJhY2pnNHM2aGNpdmpzb2FxeHJhMmN6ejNuMjJ5cWppZmI2amhwcHR0emNtMnlvemxheWVmcWl0aW1lc3RhbXAbAAABiSwbBhprZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4MzQ3OUJmODdDNjJEMjZCNTQ5NDNGQURmM2RlQjk4MjYwNTBmMWRlNqRoY29tbWl0SWR4PWJhZ2NxY2VyYXZod2docnY3dnJmZWozaWdjcTZxYzdzZmhhZWFuNGZlNng2ZzRweWFmN2Rkb2Z6azU2eWFpdGltZXN0YW1wGwAAAYksHel2a2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGVlOTUzMzNEMEUxYmUzOTNFQjVkOGJBMDllRTBiNWNGNzFlMzQ0NTOkaGNvbW1pdElkeD1iYWdjcWNlcmEzbG9oNmRmZ2x0anJoZzNwMm52NHRhcHh1cnEyZHkydnZiZnJxc3lnNGsyZWZrY3YzcXRxaXRpbWVzdGFtcBsAAAGJLCFv+2tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhjYkFGNzUwRTI3YTZFRkE0MGY0Qjk4Q2VBMDAyMDNjMWJDOTJmNjYypGhjb21taXRJZHg9YmFnY3FjZXJhdmV5ZGxjb2JhZHBjbW82bGN0dmZvY2phd2luc2cyZjJvbms1N3BocmFvZmg1ZGRxc2Z2cWl0aW1lc3RhbXAbAAABiSwtOzlrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NUI3M0YyRGI2QTIzQjMwNDRjNGY2ODJhMUYxM0E4RTEyQWJEQzAxZKRoY29tbWl0SWR4PWJhZ2NxY2VyYTRxYnE1cDRlcHk3ZWRtajJsY2prYm16d3dlb21idTNsaWdpa3VpdjJrZWFscXY3bzZkbGFpdGltZXN0YW1wGwAAAYoCofHDa2Rlc2NyaXB0aW9ucHByb3Bvc2VkIGEgdHdlZXRsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaGNvbW1pdElkeD1iYWdjcWNlcmE0bnVyZ2ZkbnU0eXhwdGZtN3hpYzRmbjVjdmN4c2hoZng3YXN3YzIycXU3Y2g1M2dzbGJxaXRpbWVzdGFtcBsAAAGKA+B/m2tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg1ODhkOTFhQkY1MTkyQTBmMGRjMDI2YkYwNWY1MTAyNTNiRDFDRjUxpGhjb21taXRJZHg9YmFnY3FjZXJhNXJ0YXV3M21saGNiYzZ1eW9qbTZ1N3BnbjVpa29odnhncm9tYnpvdWw1NjZnZnAzdWVtcWl0aW1lc3RhbXAbAAABigPhWrNrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4MzQ3OUJmODdDNjJEMjZCNTQ5NDNGQURmM2RlQjk4MjYwNTBmMWRlNqRoY29tbWl0SWR4PWJhZ2NxY2VyYXV0aWMzY2J3ZTQzYTJnMzZjbmJhcXd4d3J4cnhiZ3ZtazI1bGZpczNlaXJ4dXRheHRqZ3FpdGltZXN0YW1wGwAAAYoFO2hna2Rlc2NyaXB0aW9uc2V4ZWN1dGVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDJhYWNjY0MyYzZlYjY2NzhmRThiNkYxRTkwMjA5ZTYzOGJDQzg3NjekaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY5MjI3NjEzMzAxMjU3ODc5M2l0aW1lc3RhbXD7Qdk3oaXPzrhrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtveUNjQWFxQkt2b0VpM0Z1bUhaMU50SkV3Y043M0E2c2pIakYzUk1oQmhjY6RoY29tbWl0SWR4PWJhZ2NxY2VyYTVoaWZleGl0NGtjcmVsY3B6N2M2ZXR0NmprcHNlbGdwa2xtdG8zZWlieWNyM2N4dXFmNmFpdGltZXN0YW1wGwAAAYoH7xOSa2Rlc2NyaXB0aW9uc2V4ZWN1dGVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTakaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY5MjQ2NjcwODE1NjM4MzM0N2l0aW1lc3RhbXD7Qdk3zgR1fVtrZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtveUNjQWFxQkt2b0VpM0Z1bUhaMU50SkV3Y043M0E2c2pIakYzUk1oQmhjY6RoY29tbWl0SWR4PWJhZ2NxY2VyYWtxN2FqbGEyNGhyanl3dmVpd3VtZHh1cXhxb3F6aGpnY3NzbWxjandscDRjbXIybW92bHFpdGltZXN0YW1wGwAAAYoMdLOsa2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDAzNjNGM0MzMTA3NmE2NGI4NUNlYjY5YTI4Zjk1OEE3YzExODFDRWWkaGNvbW1pdElkeD1iYWdjcWNlcmFkcndheGI3dXR2bjY1ZGlvdm1qdDNmaGhmdm41ZXU2YmMzM2YyemJzZHM0YmM1MjNwd3BhaXRpbWVzdGFtcBsAAAGKGJphN2tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhmOTI4OTdiOUE3RmZDZkUxOGJjRTRDYTlFRDMxYjQ1YWQyNWMyODA4pGhjb21taXRJZHg9YmFnY3FjZXJhc3hocHRqbG90Zm80eXYzN3V6Z3ZzNXRpcXlhMjNyNWgzNmVobDJ4aWxnYTZpY216YWcyYWl0aW1lc3RhbXAbAAABihxz3wRrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NUI3M0YyRGI2QTIzQjMwNDRjNGY2ODJhMUYxM0E4RTEyQWJEQzAxZKRoY29tbWl0SWR4PWJhZ2NxY2VyYTJ3d21kcmxzb242NHd1YzZ2MnFhdmtjeGpqZnc0YTZ5enl4a210NXN3ZjRwZnhocDR1cXFpdGltZXN0YW1wGwAAAYoceV0ia2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDZDRjgwN2JiMWRFRThFMkQ0QzU1RThDZjZDODc1NTQ0ZWRCMmZDRmWkaGNvbW1pdElkeD1iYWdjcWNlcmFvc3RmYzUydG1wbXBwM3ZzNnB5b3M0NjQ0bHQzYXRlcG5iNXZlN3VtZHF4NHJzN2hxaDdxaXRpbWVzdGFtcBsAAAGKHIdg0WtkZXNjcmlwdGlvbnNleGVjdXRlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBpGlvdXRwdXRVcmx4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2OTM5MTcwNDUzODgxNjk1NTNpdGltZXN0YW1w+0HZOR+za58Oa2Rlc2NyaXB0aW9ucXBvc3RlZCB0byBUd2l0dGVybGFjdG9yQWRkcmVzc3g4ZGlkOmtleTp6Nk1rb3lDY0FhcUJLdm9FaTNGdW1IWjFOdEpFd2NONzNBNnNqSGpGM1JNaEJoY2OkaGNvbW1pdElkeD1iYWdjcWNlcmEza2R0bDc2c3l3dzRrNWxseGNvZDV4ZW5oN3lhcXR2d3gyZmJvaW15bzR1dXkzNWg2eHVhaXRpbWVzdGFtcBsAAAGKHNnm7mtkZXNjcmlwdGlvbnBwcm9wb3NlZCBhIHR3ZWV0bGFjdG9yQWRkcmVzc3gqMHhCQzIxRWY2RDZGNGVCNjhkNTNhMjkxN0U1NzVFNjdFNkE5ODg5NzE2pGhjb21taXRJZHg9YmFnY3FjZXJheHd0bGxqc2ZueWozZnQ0eGdzaG5oaTc2dmpudDM3ZjYzYWF1NnBpYnFsMmpnbzNybjVqcWl0aW1lc3RhbXAbAAABihzaS6xrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4QkMyMUVmNkQ2RjRlQjY4ZDUzYTI5MTdFNTc1RTY3RTZBOTg4OTcxNqRoY29tbWl0SWR4PWJhZ2NxY2VyYWZtZHY1M3djdmZrNzZkcmJ3dDRtcnJwbnNxYjVkNGVlYmczdmNvbW1naHh6enk2ZGtxZWFpdGltZXN0YW1wGwAAAYoc2xoga2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWSkaGNvbW1pdElkeD1iYWdjcWNlcmFuaWF4Y2V6d240dHdlZ2g3c2g3dHNwN29iZHN3aXV3bXJtMmJwcjYyMmhja3hxMmZqb2FhaXRpbWVzdGFtcBsAAAGKHRO4IWtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhDMmM3QTUyQUZDODYzRjJhNmYxMDM3MTg4NkIzY0NDNTNjQTQzNzg5pGhjb21taXRJZHg9YmFnY3FjZXJhcG5uamxhY2FuN3luczdhbHZxemZ6a2lvcjI2bmNzeWRycW9iaXpiNHV0am9zYndudmN0YWl0aW1lc3RhbXAbAAABih0WFK1rZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4NkNGODA3YmIxZEVFOEUyRDRDNTVFOENmNkM4NzU1NDRlZEIyZkNGZaRoY29tbWl0SWR4PWJhZ2NxY2VyYWl5amRyazJhZHVlcDc3bWRjczVsbW53cDJlb3R5a3FtdHRyd2luZWF4c2ZuczNueXV1Y3FpdGltZXN0YW1wGwAAAYodGynKa2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjKkaGNvbW1pdElkeD1iYWdjcWNlcmFzcmdlYXN6end0NmZyYnZvNmpncjJlaG1zdHJjdDRrNG1zeGRpNzRyaXZoeGZtMmg0NXlhaXRpbWVzdGFtcBsAAAGKHRtMz2tkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg2ZTdmMUM0NENjNERENTI0NEI4ODkyYUJCNTFCM2Q1ZDZlNjcxYTA3pGhjb21taXRJZHg9YmFnY3FjZXJhZGpvdmlzcm9ndmM2ZnVqd2NkdGtzeXBnZjRtN3RvZm1oazIybnNvZ2dsb2l4NnR6dHVqcWl0aW1lc3RhbXAbAAABih0c769rZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4MzQ0NzEwOTYyODVDMkI1OTE2NEUyMGMwM2Y2OTc3NDIzYTQ1MDAzOaRoY29tbWl0SWR4PWJhZ2NxY2VyYWxxa3E2aWdtdG5ycDVlcWd1NTdlZXVsNnF2bnR4c3Zxand6bGhrcmZwNGpweDVkZmVvbWFpdGltZXN0YW1wGwAAAYodPb24a2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGY5Mjg5N2I5QTdGZkNmRTE4YmNFNENhOUVEMzFiNDVhZDI1YzI4MDikaGNvbW1pdElkeD1iYWdjcWNlcmE1ZGNsa2RlMmpweHNmYnBkZXRtN2ZvYXZkeTI3c3ZqbGlmYmd0NzZxdGFiZWFkeGh1cGVhaXRpbWVzdGFtcBsAAAGKHVOjTmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhBRkVGNzYwMjAzQTU5ZTQ2YzE4RkM3QjhBRUZCNEU4ZjQ3MzExQzNCpGhjb21taXRJZHg9YmFnY3FjZXJhdXBneWh2b3FscWZ0a2xpYmV4cjR0NHZpM3UyNXpwb3FlZjM2cnVhdWFvM25obW1hZW5rYWl0aW1lc3RhbXAbAAABih1TrIJrZGVzY3JpcHRpb25zZXhlY3V0ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4QUZFRjc2MDIwM0E1OWU0NmMxOEZDN0I4QUVGQjRFOGY0NzMxMUMzQqRpb3V0cHV0VXJseD1odHRwczovL3R3aXR0ZXIuY29tL2xhdW5jaGNlbnRhdXJzL3N0YXR1cy8xNjkzOTcyMDY2ODMwMDMyOTIwaXRpbWVzdGFtcPtB2TksgvceBGtkZXNjcmlwdGlvbnFwb3N0ZWQgdG8gVHdpdHRlcmxhY3RvckFkZHJlc3N4OGRpZDprZXk6ejZNa295Q2NBYXFCS3ZvRWkzRnVtSFoxTnRKRXdjTjczQTZzakhqRjNSTWhCaGNjpGhjb21taXRJZHg9YmFnY3FjZXJhbnpxbXZlc2Rlb2N3ZXdvb3l1Y2lsbXB6eWxqMzVoaG51emVsN2UzbTR6NnpnN3ViM3ZkcWl0aW1lc3RhbXAbAAABilHRJIFrZGVzY3JpcHRpb25wcHJvcG9zZWQgYSB0d2VldGxhY3RvckFkZHJlc3N4KjB4MGI2RDBhNDE0YmM2MUE4ZjMxMmYwNTU2Njk4NTFlZEZiMTc2NENFMKRoY29tbWl0SWR4PWJhZ2NxY2VyYWl5dmtreHZkbTJzeWFyaXFqeGIza2hweXNtcGllZGt6eW03ZmZvbXFndm0zY3lnYzJ6aWFpdGltZXN0YW1wGwAAAYpR0Us/a2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDBiNkQwYTQxNGJjNjFBOGYzMTJmMDU1NjY5ODUxZWRGYjE3NjRDRTCkaGNvbW1pdElkeD1iYWdjcWNlcmFvbGd2MnlvZGxnaDZ3aGUydDZnajRma3o2ZzJ3dW9uMzdiM3N3a3VicDdxNnJwaWJtc3lxaXRpbWVzdGFtcBsAAAGKUdMrhmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkpGhjb21taXRJZHg9YmFnY3FjZXJhYmVzNTd1YWc3MnFjaHNhaTVsbXdrbTVvdGZoenhvZGNkb2h0dGhyd3p1MmpqYmhhczdnYWl0aW1lc3RhbXAbAAABilHUevprZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4QzE5YTJmNDQ5MzVlQ2IxNTE4NzhlOUNjZGU5NTFkMDBkYzg3ODU4Y6RoY29tbWl0SWR4PWJhZ2NxY2VyYTM0aXJkaGNtb20yejdrenczMmxscHBidjM2ZWlqdXg3eWQ2NmdkcWhyM3ZncWd2cmZveHFpdGltZXN0YW1wGwAAAYpR1RZQa2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweEJGOWQxYTFlRGYwMWNiNmRiMGEzZWEyMGVjZGUyMzRFMzIwOTQzNTekaGNvbW1pdElkeD1iYWdjcWNlcmFrbGRvcnBudjczdGlhZ2lhb3dkN2J4dWFqdmlndDJqZXZobmRscWxpYXlnZ3VrbWUzYXNxaXRpbWVzdGFtcBsAAAGKUdaFRmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBpGhjb21taXRJZHg9YmFnY3FjZXJhb3R1eGljcmpwcHRxY3VhMmhmbHF5eW15a2M1cDRkZHk3d3BmYXRsaXJjdWpweHJqMzRhcWl0aW1lc3RhbXAbAAABilHZXIFrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4QTM2RjIxNDgxMjc4MTVlOWQyQTZBZDJBMzMwRmZmNEIwOTM3NDM0YqRoY29tbWl0SWR4PWJhZ2NxY2VyYWg3cDR2N3dqemVyM2x5NXFvNTVzd3FpdXg3MjM0bmd1ejI1M3hxa3ZscGMzdHB6d2d0N2FpdGltZXN0YW1wGwAAAYpR2g6Na2Rlc2NyaXB0aW9uc2FwcHJvdmVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweDExMUU0MEMwQzE3RjlERDFmZUMyNjlCOEY1MWMwMjFlMDMwMjJDYkWkaGNvbW1pdElkeD1iYWdjcWNlcmFmaXZ0dG9iNnY0d2YydGJxM2dra3V6N2FjNGl3dXVubmp3c2M0cjYyaG1tNWNzaTR0eXJhaXRpbWVzdGFtcBsAAAGKUdpMnmtkZXNjcmlwdGlvbnNhcHByb3ZlZCBhIHByb3Bvc2FsbGFjdG9yQWRkcmVzc3gqMHhEOURkMEIxMTJCMjg1NzMyNjViYzYyNzc0ZTgxM2ZDNzI1MjA4MEQ3pGhjb21taXRJZHg9YmFnY3FjZXJhZTZwMnlmZmx0eG5qdXJxdDR2cjZ2aHcyZjVhaXQzaDMzYXF4dXRzcmFyNXR3Z2ZrNGJjYWl0aW1lc3RhbXAbAAABilHh6uxrZGVzY3JpcHRpb25zYXBwcm92ZWQgYSBwcm9wb3NhbGxhY3RvckFkZHJlc3N4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M6RoY29tbWl0SWR4PWJhZ2NxY2VyYXRic2F5NGU0djJxcHRpdGh2cGpjeWpvd2V5eGRiMmcyMmt2dnRvZmt3cTJpZGxwcG5neWFpdGltZXN0YW1wGwAAAYpR4higa2Rlc2NyaXB0aW9uc2V4ZWN1dGVkIGEgcHJvcG9zYWxsYWN0b3JBZGRyZXNzeCoweGVlOTUzMzNEMEUxYmUzOTNFQjVkOGJBMDllRTBiNWNGNzFlMzQ0NTOkaW91dHB1dFVybHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY5NzY3MDk0ODE2ODU5MzcyNGl0aW1lc3RhbXD7Qdk8ibm/dT5rZGVzY3JpcHRpb25xcG9zdGVkIHRvIFR3aXR0ZXJsYWN0b3JBZGRyZXNzeDhkaWQ6a2V5Ono2TWtveUNjQWFxQkt2b0VpM0Z1bUhaMU50SkV3Y043M0E2c2pIakYzUk1oQmhjY2dtZW1iZXJzjaJnYWRkcmVzc3gqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2aW93bmVyc2hpcASiZ2FkZHJlc3N4KjB4Y2JBRjc1MEUyN2E2RUZBNDBmNEI5OENlQTAwMjAzYzFiQzkyZjY2Mmlvd25lcnNoaXAAomdhZGRyZXNzeCoweDc3QjJkODgyOTlBNDA4NDVlOEZmYkU5RWRjNEJGNmU4OTEzNmM2MGRpb3duZXJzaGlwAKJnYWRkcmVzc3gqMHhlZTk1MzMzRDBFMWJlMzkzRUI1ZDhiQTA5ZUUwYjVjRjcxZTM0NDUzaW93bmVyc2hpcACiZ2FkZHJlc3N4KjB4NmM2NzY2RTA0ZUY5NzEzNjdEMjdFNzIwZDFkMTYxYTlCNDk1RDY0N2lvd25lcnNoaXAAomdhZGRyZXNzeCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWRpb3duZXJzaGlwAKJnYWRkcmVzc3gqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBaW93bmVyc2hpcACiZ2FkZHJlc3N4KjB4ZjRhNjk3MjUzMjg1QTAyQzcwRGU5NWM5Q2JhNUE2NDUwNjFjOUUyNmlvd25lcnNoaXAAomdhZGRyZXNzeCoweGY5Mjg5N2I5QTdGZkNmRTE4YmNFNENhOUVEMzFiNDVhZDI1YzI4MDhpb3duZXJzaGlwAKJnYWRkcmVzc3gqMHhCNEE1Mzc1MzI1Njk2MDZjNjI4ODAxZkI4NjNCMUFBOUFBRTNGYkI3aW93bmVyc2hpcACiZ2FkZHJlc3N4KjB4NTVGY0Y2QjY2NWM1RDVDNTMzNjdiNjBmNjUxQTAzNzM5RGZhNzUwMWlvd25lcnNoaXAAomdhZGRyZXNzeCoweDk4MmRkMzA0Y0Y1ZDE0MEI1QzE2NzM5OTljY0I0ZTY5RGMxRTdFNTNpb3duZXJzaGlwAKJnYWRkcmVzc3gqMHg4YjQxQjY2NWExNEVFMTI5M2Q3NWRhMzA3MjBCQ0NEMmZmOGI5OTJhaW93bmVyc2hpcABncHVycG9zZXgmVG8gYW5zd2VyIEF1dG9ub2xhcy1yZWxhdGVkIHF1ZXN0aW9ucy5obWVzc2FnZXOUo2ZtZW1iZXJ4KjB4MzQ3OUJmODdDNjJEMjZCNTQ5NDNGQURmM2RlQjk4MjYwNTBmMWRlNmdjb250ZW50c05pY2UgbWVtb3J5IHVwZGF0ZSFpdGltZXN0YW1wGwAAAYgf9TZro2ZtZW1iZXJ4KjB4Nzg4NWQxMjFlZDhBYTNjOTE5QUE0ZDQwN0YxOTdEYzI5RTMzY0FmMGdjb250ZW50eCBUZWxsIG1lIDMgZmFjdHMgYWJvdXQgYXV0b25vbGFzCml0aW1lc3RhbXAbAAABiJXcgU+jZm1lbWJlcngqMHg1MTVDMDdkZDdDZDAxNDk2ZDQwMDBlNDk5OEI0RkQ1YUNkMmMwOUUxZ2NvbnRlbnR4OmhlbGxvCmNhbiB5b3UgZmluZCBtZSB0d28gd2FsbGV0cyB0aGF0IGJvdWdodCAkcGVwZSBlYXJseT9pdGltZXN0YW1wGwAAAYmMR08wo2ZtZW1iZXJ4KjB4MDdiNTMwMmUwMUQ0NGJENWI5MEM2M0M2RmIyNDgwNzk0NjcwNGJGQ2djb250ZW50bWhlbGxvIG1lc3NhZ2VpdGltZXN0YW1wGwAAAYmM+mSro2ZtZW1iZXJ4KjB4ZjkyODk3YjlBN0ZmQ2ZFMThiY0U0Q2E5RUQzMWI0NWFkMjVjMjgwOGdjb250ZW50aGhlbGxvIDopaXRpbWVzdGFtcBsAAAGKBQNYBaNmbWVtYmVyeCoweDAzNjNGM0MzMTA3NmE2NGI4NUNlYjY5YTI4Zjk1OEE3YzExODFDRWVnY29udGVudGd0ZXN0aW5naXRpbWVzdGFtcBsAAAGKDHmPwKNmbWVtYmVyeCoweDAzNjNGM0MzMTA3NmE2NGI4NUNlYjY5YTI4Zjk1OEE3YzExODFDRWVnY29udGVudHhJV2hpY2ggdGVjaCBpcyB0aGlzIGNoYXQgdXNpbmc/IE9yYmlzLkNsdWI/IE9yIGlzIHRoaXMgYSBPTEFTIGN1c3RvbSBicmV3P2l0aW1lc3RhbXAbAAABigx5+wyjZm1lbWJlcngqMHhmNGE2OTcyNTMyODVBMDJDNzBEZTk1YzlDYmE1QTY0NTA2MWM5RTI2Z2NvbnRlbnR4NUhvdyBtYW55IHZlT0xBUyBkbyBJIG5lZWQgdG8gaG9sZCB0byBiZWNvbWUgYSBNZW1iZXI/aXRpbWVzdGFtcBsAAAGKEyKSQaNmbWVtYmVyeCoweGY5Mjg5N2I5QTdGZkNmRTE4YmNFNENhOUVEMzFiNDVhZDI1YzI4MDhnY29udGVudHggYW55IGFtb3VudCBvZiB2ZU9MQVMgc2hvdWxkIHdvcmtpdGltZXN0YW1wGwAAAYoTLwquo2ZtZW1iZXJ4KjB4MEY2Y2I1OURDODIwYmVjMzM5MDdhZjQzOTBlOGQ4ZjYzOWQzQzMwNGdjb250ZW50eBhIb3cgZG8gaSBnZXQgdGhlIHZlT0xBUwppdGltZXN0YW1wGwAAAYomFVUFo2ZtZW1iZXJ4KjB4MTI3OTYxZmFGM2E4ODVEQzZFZTk5NjQzM0NCNDEzOUYyOWJDRjUwMGdjb250ZW50dOaIkeW3sue7j+acieS6hk9MQVMKaXRpbWVzdGFtcBsAAAGKJmLul6NmbWVtYmVyeCoweDEyODQ0YTRGQTRGNTA5YzM0MTZhNWVCNDMwQTUyNDYxNzUxZkM2MjFnY29udGVudGc6ZXllcyAKaXRpbWVzdGFtcBsAAAGKKKzmyqNmbWVtYmVyeCoweEI0QTUzNzUzMjU2OTYwNmM2Mjg4MDFmQjg2M0IxQUE5QUFFM0ZiQjdnY29udGVudGZoZXl5eXlpdGltZXN0YW1wGwAAAYoo7HKAo2ZtZW1iZXJ4KjB4QjRBNTM3NTMyNTY5NjA2YzYyODgwMWZCODYzQjFBQTlBQUUzRmJCN2djb250ZW50eCRob3cgZG8gd2UgZ28gdXAgaW4gdGhlIGxlYWRlcmJvYXJkPwppdGltZXN0YW1wGwAAAYoo7M1do2ZtZW1iZXJ4KjB4QjRBNTM3NTMyNTY5NjA2YzYyODgwMWZCODYzQjFBQTlBQUUzRmJCN2djb250ZW50a3NhdyBpdCBudm0KaXRpbWVzdGFtcBsAAAGKKO0JqKNmbWVtYmVyeCoweDU1RmNGNkI2NjVjNUQ1QzUzMzY3YjYwZjY1MUEwMzczOURmYTc1MDFnY29udGVudGtPTEFTID0gU0FMT2l0aW1lc3RhbXAbAAABiknXs1SjZm1lbWJlcngqMHgwRkIwMGI5RDc0Njg0NDQ0RjJmRjQxY0IxNzU0NEVFOUY5OGM4M0I4Z2NvbnRlbnRqaGVsbG8gb2xhc2l0aW1lc3RhbXAbAAABilARMKOjZm1lbWJlcngqMHg5ODJkZDMwNGNGNWQxNDBCNUMxNjczOTk5Y2NCNGU2OURjMUU3RTUzZ2NvbnRlbnR4NmkgZGlkIHRoZSBzdGVwcyBuZWVkZWQgYnV0IG15IHR3ZWV0ZXIgaXMgbm90IGNvbm5lY3RlZGl0aW1lc3RhbXAbAAABilZbu4SjZm1lbWJlcngqMHgwNTAxOWJGYUExN0U4NEQ3ODI3MkI5NUY5ODJBNTg1NGVmN0NEMEREZ2NvbnRlbnRhMWl0aW1lc3RhbXAbAAABiltMRb6jZm1lbWJlcngqMHg2OTAzQmFiQ2RGMzUwNkVhN2U0Y0Y0MzQ5YTNjMTQ4ZjRCMkU5YUZkZ2NvbnRlbnRiaGlpdGltZXN0YW1wGwAAAYpcqpLEbHBsdWdpbnNfZGF0YaNrZGFpbHlfb3JiaXOga2RhaWx5X3R3ZWV0oG9zY2hlZHVsZWRfdHdlZXShZnR3ZWV0c4ioZHRleHR4xkEgbmV3IHNldCBvZiBib25kaW5nIHByb2R1Y3RzIGlzIGxpdmUhCgpUaGV5J3JlIGF2YWlsYWJsZSBiZWxvdywgdXNpbmcgT0xBUy1FVEggTFAgdG9rZW5zLgoKaHR0cHM6Ly90b2tlbm9taWNzLm9sYXMubmV0d29yay9ib25kaW5nLXByb2R1Y3RzCgpodHRwczovL3R3aXR0ZXIuY29tL2F1dG9ub2xhcy9zdGF0dXMvMTY4MTcxMTkxOTk5OTM3NzQwOGZwb3N0ZWT1ZnZvdGVyc4l4KjB4MGI2RDBhNDE0YmM2MUE4ZjMxMmYwNTU2Njk4NTFlZEZiMTc2NENFMHgqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkeCoweEMxOWEyZjQ0OTM1ZUNiMTUxODc4ZTlDY2RlOTUxZDAwZGM4Nzg1OGN4KjB4QkY5ZDFhMWVEZjAxY2I2ZGIwYTNlYTIwZWNkZTIzNEUzMjA5NDM1N3gqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBeCoweEEzNkYyMTQ4MTI3ODE1ZTlkMkE2QWQyQTMzMEZmZjRCMDkzNzQzNGJ4KjB4MTExRTQwQzBDMTdGOUREMWZlQzI2OUI4RjUxYzAyMWUwMzAyMkNiRXgqMHhEOURkMEIxMTJCMjg1NzMyNjViYzYyNzc0ZTgxM2ZDNzI1MjA4MEQ3eCoweGVlOTUzMzNEMEUxYmUzOTNFQjVkOGJBMDllRTBiNWNGNzFlMzQ0NTNnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4MGI2RDBhNDE0YmM2MUE4ZjMxMmYwNTU2Njk4NTFlZEZiMTc2NENFMGlhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2OTc2NzA5NDgxNjg1OTM3MjRqcmVxdWVzdF9pZHgkNTY5MzEzMTEtNGRhNS00MjQxLTk4YWItNzE0OTQ2Y2MzNzcxa2NyZWF0ZWREYXRl+0HZPIhDugxKqGR0ZXh0eGQ6Y3ljbG9uZTogVGhlIGxhdGVzdCBib25kaW5nIHByb2R1Y3RzIGFyZSBub3cgbGl2ZToKaHR0cHM6Ly90b2tlbm9taWNzLm9sYXMubmV0d29yay9ib25kaW5nLXByb2R1Y3RzZnBvc3RlZPVmdm90ZXJziXgqMHhCQzIxRWY2RDZGNGVCNjhkNTNhMjkxN0U1NzVFNjdFNkE5ODg5NzE2eCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWR4KjB4QzJjN0E1MkFGQzg2M0YyYTZmMTAzNzE4ODZCM2NDQzUzY0E0Mzc4OXgqMHg2Q0Y4MDdiYjFkRUU4RTJENEM1NUU4Q2Y2Qzg3NTU0NGVkQjJmQ0ZleCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjJ4KjB4NmU3ZjFDNDRDYzRERDUyNDRCODg5MmFCQjUxQjNkNWQ2ZTY3MWEwN3gqMHgzNDQ3MTA5NjI4NUMyQjU5MTY0RTIwYzAzZjY5Nzc0MjNhNDUwMDM5eCoweGY5Mjg5N2I5QTdGZkNmRTE4YmNFNENhOUVEMzFiNDVhZDI1YzI4MDh4KjB4QUZFRjc2MDIwM0E1OWU0NmMxOEZDN0I4QUVGQjRFOGY0NzMxMUMzQmdleGVjdXRl9Whwcm9wb3NlcngqMHhCQzIxRWY2RDZGNGVCNjhkNTNhMjkxN0U1NzVFNjdFNkE5ODg5NzE2aWFjdGlvbl9pZHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY5Mzk3MjA2NjgzMDAzMjkyMGpyZXF1ZXN0X2lkeCRlYmU4MWYyNy0zY2Y4LTRkNDMtYjZkNi1iM2RkOTJlM2U0MDlrY3JlYXRlZERhdGX7Qdk5JHk187aoZHRleHR49U9sYXMgVHJpcGxlIExvY2sg4oCTwqBjaGVjayBvdXQgdGhlIGV4Y2l0aW5nIGZpcnN0IEF1dG9ub2xhcyBJbXByb3ZlbWVudCBQcm9wb3NhbCAoQUlQKSwgZm9jdXNlZCBvbiBidWlsZGluZyBzeW5lcmdpZXMgd2l0aCBvdGhlciBjaGFpbnMgdGhyb3VnaCBib25kaW5nOiBodHRwczovL2dpdGh1Yi5jb20vdmFsb3J5LXh5ei9hdXRvbm9sYXMtYWlwL2Jsb2IvYWlwLTEvY29udGVudC9haXBzL2NvcmUtYWlwLXRyaXBsZS1sb2NrLm1kZnBvc3RlZPVmdm90ZXJzhngqMHg1ODhkOTFhQkY1MTkyQTBmMGRjMDI2YkYwNWY1MTAyNTNiRDFDRjUxeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTZ4KjB4MDM2M0YzQzMxMDc2YTY0Yjg1Q2ViNjlhMjhmOTU4QTdjMTE4MUNFZXgqMHhmOTI4OTdiOUE3RmZDZkUxOGJjRTRDYTlFRDMxYjQ1YWQyNWMyODA4eCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWR4KjB4NkNGODA3YmIxZEVFOEUyRDRDNTVFOENmNkM4NzU1NDRlZEIyZkNGZWdleGVjdXRl9Whwcm9wb3NlcngqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2aWFjdGlvbl9pZHg9aHR0cHM6Ly90d2l0dGVyLmNvbS9sYXVuY2hjZW50YXVycy9zdGF0dXMvMTY5MzkxNzA0NTM4ODE2OTU1M2pyZXF1ZXN0X2lkeCRkMGU1MGQ0Zi1iMWFjLTRiMGMtOTA2Ny1hMDhmMDY0YzUyNDBrY3JlYXRlZERhdGX7Qdk3duhv756oZHRleHR43VRoaXMgdHdlZXQgYW5ub3VuY2luZyB0aGUgcHVibGljIGxhdW5jaCBvZiBPTEFTIHdhcyBhcHByb3ZlZCBieSBhIGdyb3VwIG9mIGNvbW11bml0eSBtZW1iZXJzIGFuZCBwb3N0ZWQgYnkgYW4gYXV0b25vbW91cyBzZXJ2aWNlLiBBbGwgdmlhIEBsYXVuY2hjZW50YXVycy4g8J+YjiBodHRwczovL3R3aXR0ZXIuY29tL2F1dG9ub2xhcy9zdGF0dXMvMTY3NjY1MjAyNTY3OTg0NzQ0MT9zPTIwZnBvc3RlZPVmdm90ZXJzhXgqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3eCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTZ4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M3gqMHhjYkFGNzUwRTI3YTZFRkE0MGY0Qjk4Q2VBMDAyMDNjMWJDOTJmNjYyeCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWRnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4NmM2NzY2RTA0ZUY5NzEzNjdEMjdFNzIwZDFkMTYxYTlCNDk1RDY0N2lhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2OTI0NjY3MDgxNTYzODMzNDdqcmVxdWVzdF9pZHgkOWMzYzU1ZGEtZjA2NS00ZTBmLWI2ZmItMDBmZWM3ZTE2N2Fha2NyZWF0ZWREYXRl+0HZKbwTW+dtqGR0ZXh0eElUaGUgZmlyc3QgI09sYXNOZXR3b3JrIFB1YmxpYyBUb2tlbiBMYXVuY2ggaXMgbm93IGxpdmUg8J+OiSBvbGFzLm5ldHdvcmsKZnBvc3RlZPVmdm90ZXJzhXgqMHg5OTA5MzUxMGFCOUY2MEE0MjU4MTdlQkU4MUZDQzM5NmREZGE2ZDVBeCoweGVlOTUzMzNEMEUxYmUzOTNFQjVkOGJBMDllRTBiNWNGNzFlMzQ0NTN4KjB4MzQ3OUJmODdDNjJEMjZCNTQ5NDNGQURmM2RlQjk4MjYwNTBmMWRlNngqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjJnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4OTkwOTM1MTBhQjlGNjBBNDI1ODE3ZUJFODFGQ0MzOTZkRGRhNmQ1QWlhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NzY2NTIwMjU2Nzk4NDc0NDFqcmVxdWVzdF9pZHgkMjc3NGJlZWItODhiMy00MWVhLTg3NDUtNzdhNGQ4ZTcyN2E5a2NyZWF0ZWREYXRl+0HZKWj2HMzNqGR0ZXh0eKNUaGUgZmlyc3QgI09sYXNOZXR3b3JrIFB1YmxpYyBUb2tlbiBMYXVuY2ggaXMgbm93IGxpdmUg8J+OiQoKb2xhcy5uZXR3b3JrCgpQLlMuIFRoaXMgdHdlZXQgd2FzIHNlbnQgYXV0b25vbW91c2x5IG9uIGJlaGFsZiBvZiB0aGUgQXV0b25vbGFzIERBTyB2aWEgQGxhdW5jaGNlbnRhdXJzZnBvc3RlZPVmdm90ZXJzhXgqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2eCoweGVlOTUzMzNEMEUxYmUzOTNFQjVkOGJBMDllRTBiNWNGNzFlMzQ0NTN4KjB4Y2JBRjc1MEUyN2E2RUZBNDBmNEI5OENlQTAwMjAzYzFiQzkyZjY2MngqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkeCoweDk5MDkzNTEwYUI5RjYwQTQyNTgxN2VCRTgxRkNDMzk2ZERkYTZkNUFnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4OTkwOTM1MTBhQjlGNjBBNDI1ODE3ZUJFODFGQ0MzOTZkRGRhNmQ1QWlhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2OTIyNzYxMzMwMTI1Nzg3OTNqcmVxdWVzdF9pZHgkMmNlNDExYWQtMTA0Ny00MTE1LThjZWEtMWE1ZjViMWQ0ZDBma2NyZWF0ZWREYXRl+0HZKWMK0ZmaqGR0ZXh0eFtUaGlzIGlzIHRlc3QgdHdlZXQsIHNlbnQgd2l0aCBBdXRvbm9sYXMgY29tbXVuaXR5IGFwcHJvdmFsLiBGYWNpbGl0YXRlZCBieSBAbGF1bmNoY2VudGF1cnMuZnBvc3RlZPVmdm90ZXJzhXgqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3eCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTZ4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M3gqMHg1QjczRjJEYjZBMjNCMzA0NGM0ZjY4MmExRjEzQThFMTJBYkRDMDFkeCoweGNiQUY3NTBFMjdhNkVGQTQwZjRCOThDZUEwMDIwM2MxYkM5MmY2NjJnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4NmM2NzY2RTA0ZUY5NzEzNjdEMjdFNzIwZDFkMTYxYTlCNDk1RDY0N2lhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NzU5MDM5MDgzNzQzNjAwNzFqcmVxdWVzdF9pZHgkYjQwMzFiOTYtMjdkYS00YzVjLThlMmMtYTBjODc2YzkzMDJla2NyZWF0ZWREYXRl+0HZJ6RmEXjVqGR0ZXh0eC1UaGlzIGlzIEF1dG9ub2xhcycgZmlyc3QgdHdlZXQgZnJvbSBDZW50YXVycyFmcG9zdGVk9WZ2b3RlcnOEeCoweDM0NzlCZjg3QzYyRDI2QjU0OTQzRkFEZjNkZUI5ODI2MDUwZjFkZTZ4KjB4ZWU5NTMzM0QwRTFiZTM5M0VCNWQ4YkEwOWVFMGI1Y0Y3MWUzNDQ1M3gqMHhjYkFGNzUwRTI3YTZFRkE0MGY0Qjk4Q2VBMDAyMDNjMWJDOTJmNjYyeCoweDZjNjc2NkUwNGVGOTcxMzY3RDI3RTcyMGQxZDE2MWE5QjQ5NUQ2NDdnZXhlY3V0ZfVocHJvcG9zZXJ4KjB4MzQ3OUJmODdDNjJEMjZCNTQ5NDNGQURmM2RlQjk4MjYwNTBmMWRlNmlhY3Rpb25faWR4PWh0dHBzOi8vdHdpdHRlci5jb20vbGF1bmNoY2VudGF1cnMvc3RhdHVzLzE2NzU5MDE5NjE3MjIyOTQyNzJqcmVxdWVzdF9pZHgkN2E5MGJhMzctNDlkMi00MmM1LTg2OWQtNTUzYmEzYmI4MDlha2NyZWF0ZWREYXRl+0HZJwroh3zubWNvbmZpZ3VyYXRpb26iZ3BsdWdpbnOja2RhaWx5X29yYmlzpGVkYWlsefVnZW5hYmxlZPRobGFzdF9ydW72bHJ1bl9ob3VyX3V0YwxrZGFpbHlfdHdlZXSkZWRhaWx59WdlbmFibGVk9GhsYXN0X3J1bvZscnVuX2hvdXJfdXRjDG9zY2hlZHVsZWRfdHdlZXSiZWRhaWx59GdlbmFibGVk9W9tZW1iZXJXaGl0ZWxpc3SYI3gqMHgzNDc5QmY4N0M2MkQyNkI1NDk0M0ZBRGYzZGVCOTgyNjA1MGYxZGU2eCoweEE5M2VDNTkxNmExMTkzOTBhREI4QzRjMjQ0ZjkyNmQxNDkxNkY0ZTl4KjB4YjVGMDc5ODQxRTAwMWY5NzMxNzRDNjM2RjhiZjAwRWVGZmJkMjM3NHgqMHhiZjIwMGUwM0QxQ2Y5REFjMTRFQzZEN0I0ODZCZjYwOWM4QkJlZjVleCoweEY4OWI2RDY2ZTMwODllMjdDMGZGN0YwN2E4NjViMUYyRkY4MzkyRGV4KjB4MWU1NTBCOTNhNjI4RGMyYkQ3ZjZBNTkyZjIzODY3MjQxZTU2MkFlRXgqMHgxODAxMjkyQTBmRTdDMzIxYWU5YUQ5NkVBZEE4ZjczNUU3OUVGMTIzeCoweDQxNERBNERiQzFhNDI3MTQ1MkNCNzc5ZjFBMDFkNkJhNWYzNkJlZTF4KjB4NjdmN2VDNjAyYWNmMzUzNkZGYjM3YTg3NTY1QjUxNTUzMTdhZDA4QXgqMHg4NDEwMzczREY2RTliMjA3NjVjOTU5OWMyNmQ1ODVCMmNkMEVmNjI4eCoweENFQ0VBN0MzMmU4OTk4NDY0MTRDODhkRjdBYmZjOTlmRTM2NzhhODN4KjB4MmVmMzQ1OTBEYTZjZTExM2I4RjJmYTQ0MWZiOEQ0QjhjMmQ1N2FBMHgqMHgxZjY4QjY1MjFkNUUwMTc0N0JGMUU0QTI2NzJhMkFDMzVEMDNlODY0eCoweEQ3ZjBkRGNCYjAxMTdBNTNlOWZmMmNhZDgxNEI4QjgxMGEzMTRmNTl4KjB4QjI5NWQwNWYwNTVFRTMzMDlBNDk4QzU4MTUzRGZCQzVFODNGODI5QngqMHgzNDQ3MTA5NjI4NUMyQjU5MTY0RTIwYzAzZjY5Nzc0MjNhNDUwMDM5eCoweDFjM2VDMTQ2YzM3MzgzNjdFZUY5YjFBNzdDRjYxNzRhODYwNmU3Yzl4KjB4QjEzMjU4NDZhNUE0REMzMUJBRjRGMjBFOEU1RjEyNkU1YzA2NTU1QngqMHhkMzFDMzBGZGEwQkNhYUVFYjVBMGE0ZGI2NzA1MkRjYTI5MTliNzM1eCoweDUxMUZjOTEyN2E4NjcxNDgwMjY2MjMxOTA2NjFlNWI3MDk0ZDZmMDN4KjB4NTU2RGEyMTNFNGIyOThhMUEyQUEzNjMxNWE5YjdjNjgyRDhCNTU4MngqMHhjMWU5ODYwNDA0NkM3MjZhNUFjNDYwNWY1NjQ0N0U4N0VGZTljMDhCeCoweDBiNkQwYTQxNGJjNjFBOGYzMTJmMDU1NjY5ODUxZWRGYjE3NjRDRTB4KjB4MDY5MEZiMzMyOTU2ZTY5MTVBMGUxRmQwNjBGYkRFOWNGRDU4ZTQ1MHgqMHgwQUQzNmJlOTQzOGYzNTc5MjBCNDRBM2E2ZjI3OGRCNjI5MjU5NDJEeCoweGMyRDc5YWQ1Mjk2ODA3NjMzNjhmQTUyNzg0ZjM4NUEzNzlFQmVCMjJ4KjB4MDM3RUQ3RWU5RTVEMWJBMmY2ZmRiM2ZiODRCZjBjOEI1RkM2NjREYXgqMHhFMzczYTE5MDg0NzUzYmM0NzQ2YTA1ZmJhODBEMTA1MzRlREUyYzEweCoweDkzN0Y1YjMyQmMzY2FmY2QxQjAyNDYyRjkzZTZBRTVhODQzZjZDNkF4KjB4QUQyQWM4NUNkOGM3ODcwZWUxOUM5YmU3ZkM1QTgzZDZGMkNiMUIyOHgqMHg2YzY3NjZFMDRlRjk3MTM2N0QyN0U3MjBkMWQxNjFhOUI0OTVENjQ3eCoweDVCNzNGMkRiNkEyM0IzMDQ0YzRmNjgyYTFGMTNBOEUxMkFiREMwMWR4KjB4NkNGODA3YmIxZEVFOEUyRDRDNTVFOENmNkM4NzU1NDRlZEIyZkNGZXgqMHhDMmM3QTUyQUZDODYzRjJhNmYxMDM3MTg4NkIzY0NDNTNjQTQzNzg5eCoweDk5MDkzNTEwYUI5RjYwQTQyNTgxN2VCRTgxRkNDMzk2ZERkYTZkNUFmaGVhZGVyomZ1bmlxdWVwT3BBcHRpMWpsSWRhOGl5a2tjb250cm9sbGVyc4F4OGRpZDprZXk6ejZNa295Q2NBYXFCS3ZvRWkzRnVtSFoxTnRKRXdjTjczQTZzakhqRjNSTWhCaGNj" } } ] } - }, + } } diff --git a/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py b/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py index fcbc31b4..e6628cac 100644 --- a/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py +++ b/packages/valory/agents/impact_evaluator/tests/test_impact_evaluator.py @@ -66,6 +66,11 @@ from packages.valory.skills.registration_abci.rounds import RegistrationStartupRound from packages.valory.skills.reset_pause_abci.rounds import ResetAndPauseRound from packages.valory.skills.twitter_scoring_abci.rounds import ( + DBUpdateRound, + OpenAICallCheckRound, + TweetEvaluationRound, + TwitterDecisionMakingRound, + TwitterHashtagsCollectionRound, TwitterMentionsCollectionRound, ) @@ -74,8 +79,23 @@ RoundChecks(RegistrationStartupRound.auto_round_id(), n_periods=1), RoundChecks(StreamReadRound.auto_round_id(), n_periods=3), RoundChecks(GenericScoringRound.auto_round_id(), n_periods=2), + + RoundChecks(TwitterDecisionMakingRound.auto_round_id(), n_periods=2), + RoundChecks(OpenAICallCheckRound.auto_round_id(), n_periods=2), + + RoundChecks(TwitterDecisionMakingRound.auto_round_id(), n_periods=2), RoundChecks(TwitterMentionsCollectionRound.auto_round_id(), n_periods=2), - RoundChecks(TokenTrackRound.auto_round_id(), success_event="WRITE", n_periods=2), + + RoundChecks(TwitterDecisionMakingRound.auto_round_id(), n_periods=2), + RoundChecks(TwitterHashtagsCollectionRound.auto_round_id(), n_periods=2), + + RoundChecks(TwitterDecisionMakingRound.auto_round_id(), n_periods=2), + RoundChecks(TweetEvaluationRound.auto_round_id(), n_periods=2), + + RoundChecks(TwitterDecisionMakingRound.auto_round_id(), n_periods=2), + RoundChecks(DBUpdateRound.auto_round_id(), n_periods=2), + + RoundChecks(TokenTrackRound.auto_round_id(), n_periods=2), RoundChecks(RandomnessRound.auto_round_id(), n_periods=2), RoundChecks(SelectKeeperRound.auto_round_id(), n_periods=2), RoundChecks(StreamWriteRound.auto_round_id(), n_periods=2), @@ -86,9 +106,8 @@ # strict check log messages of the happy path STRICT_CHECK_STRINGS = ( "Got data from Ceramic API", - "Path switch:", - "Retrieved new mentions from Twitter", - "Retrieved recent registrations from Twitter", + "Retrieved new mentions", + "Retrieved new hashtags", "Got token_id to address data up to block", "Data verification successful", "Period end", @@ -109,12 +128,13 @@ class BaseTestEnd2EndImpactEvaluatorNormalExecution(BaseTestEnd2EndExecution): agent_package = "valory/impact_evaluator:0.1.0" skill_package = "valory/impact_evaluator_abci:0.1.0" - wait_to_finish = 180 + wait_to_finish = 300 strict_check_strings = STRICT_CHECK_STRINGS happy_path = HAPPY_PATH package_registry_src_rel = PACKAGES_DIR __param_args_prefix = f"vendor.valory.skills.{PublicId.from_str(skill_package).name}.models.params.args" + __param_args_prefix_openai_conn = f"vendor.valory.connections.{PublicId.from_str('valory/openai:0.1.0').name}.config" extra_configs = [ { @@ -149,6 +169,10 @@ class BaseTestEnd2EndImpactEvaluatorNormalExecution(BaseTestEnd2EndExecution): "dotted_path": f"{__param_args_prefix}.centaurs_stream_id", "value": "centaurs_stream_id", }, + { + "dotted_path": f"{__param_args_prefix_openai_conn}.openai_api_key", + "value": "dummy_api_key", + }, ] http_server_port_config = { diff --git a/packages/valory/connections/openai/connection.py b/packages/valory/connections/openai/connection.py index be84b5c8..aa04689e 100644 --- a/packages/valory/connections/openai/connection.py +++ b/packages/valory/connections/openai/connection.py @@ -188,17 +188,22 @@ def _get_response(self, prompt_template: str, prompt_values: Dict[str, str]): formatted_prompt = prompt_template.format(**prompt_values) if prompt_values else prompt_template # Call the OpenAI API - response = openai.Completion.create( - engine=self.openai_settings["engine"], - prompt=formatted_prompt, - max_tokens=self.openai_settings["max_tokens"], - n=1, - stop=None, - temperature=self.openai_settings["temperature"], - ) + try: + response = openai.Completion.create( + engine=self.openai_settings["engine"], + prompt=formatted_prompt, + max_tokens=self.openai_settings["max_tokens"], + n=1, + stop=None, + temperature=self.openai_settings["temperature"], + ) + + # Extract the result from the API response + result = response.choices[0].text - # Extract the result from the API response - result = response.choices[0].text + except openai.error.AuthenticationError as e: + self.logger.error(e) + result = "OpenAI authentication error" return result diff --git a/packages/valory/connections/openai/connection.yaml b/packages/valory/connections/openai/connection.yaml index 028244d5..e0fa4123 100644 --- a/packages/valory/connections/openai/connection.yaml +++ b/packages/valory/connections/openai/connection.yaml @@ -7,7 +7,7 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeiagnziswj5tll4yzx63u4hvat4yieoaaqt5b67chvvqxg5th5mxz4 - connection.py: bafybeihtj4rzhdc5f6yw6x6kx66h4ofjya5ojk4y3bjmcanofoxp6uohx4 + connection.py: bafybeidyqthktvm6sicx6wndjxq7g73gogrjpq7hfv5l4eqfmut42gllvi readme.md: bafybeibqbvpfn6i2w7vxk2m65gizd2hcofu7mdzp2yusx7uupelztme724 fingerprint_ignore_patterns: [] connections: [] diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 05448cab..fac3e373 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeigploctarzijb7rz4lbyjrs2ted3bgujawqdc3tynsfgpoebwaflq +agent: valory/impact_evaluator:0.1.0:bafybeieomrbn6vpujq4oq3hdcrxxcnb54u67zjmeqaou7l7lhaxqgpu5oq number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index 87b20826..c1a839be 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiavcxx5qd7repbhutj37q7islrztvzwofluemg3cuy3innmo7gp4i +- valory/twitter_scoring_abci:0.1.0:bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i @@ -34,7 +34,7 @@ skills: - valory/termination_abci:0.1.0:bafybeiguy7pkrcptg6c754ioig4mlkr7truccym3fpv6jwpjx2tmpdbzhi - valory/transaction_settlement_abci:0.1.0:bafybeidpsnguxizkpihtkqzojr3em7yy7c6qc7gxpbh5vglmwws5wke7bi - valory/decision_making_abci:0.1.0:bafybeih5nquchsfisp5taaxrpz7j7ur2teymey5tihlw654wrzgpy57bvq -- valory/llm_abci:0.1.0:bafybeifvskttsumhsatvj24sx45u23zq57k56fnfgliq2csul53kjyhfhy +- valory/llm_abci:0.1.0:bafybeictnqpioilfry2yxkwaaguam5zbo3ygw7slkpn3k36gfvo2cnnyam - valory/twitter_write_abci:0.1.0:bafybeih662zzwew4egsm2m6mis5yjwfehhx2lciio5ngnbunolc6nkkyw4 behaviours: main: diff --git a/packages/valory/skills/llm_abci/skill.yaml b/packages/valory/skills/llm_abci/skill.yaml index 70685039..b13e302e 100644 --- a/packages/valory/skills/llm_abci/skill.yaml +++ b/packages/valory/skills/llm_abci/skill.yaml @@ -23,7 +23,7 @@ fingerprint: tests/test_rounds.py: bafybeib4ft6ajvd66s5yyyowiovqm4kvduilyexd7myice6mbpbgpbx35i fingerprint_ignore_patterns: [] connections: -- valory/openai:0.1.0:bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq +- valory/openai:0.1.0:bafybeih7w2xmaecgznuhxpnbxcxjhfla6wlmx3umytindfgk6ibbwqq2lu contracts: [] protocols: - valory/llm:1.0.0:bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4 diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index f3ed06fb..676eb243 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -761,6 +761,8 @@ def update_ceramic_db(self) -> Dict: # Update data for tweet in tweets.values(): + self.context.logger.info(f"Updating db with tweet: {tweet}") + author_id = tweet["author_id"] twitter_name = tweet["username"] new_points = tweet["points"] diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index fa180bbf..2a12d0ca 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -235,6 +235,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Happy path payload = json.loads(self.most_voted_payload) previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets + ceramic_db = cast(SynchronizedData, self.synchronized_data).ceramic_db performed_twitter_tasks["retrieve_mentions"] = Event.DONE.value new_tweets = payload["tweets"] @@ -258,6 +259,10 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: updates[get_name(SynchronizedData.latest_mention_tweet_id)] = payload[ "latest_mention_tweet_id" ] + else: + updates[ + get_name(SynchronizedData.latest_mention_tweet_id) + ] = ceramic_db["module_data"]["twitter"]["latest_mention_tweet_id"] synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, @@ -321,6 +326,7 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: # Happy path payload = json.loads(self.most_voted_payload) previous_tweets = cast(SynchronizedData, self.synchronized_data).tweets + ceramic_db = cast(SynchronizedData, self.synchronized_data).ceramic_db performed_twitter_tasks["retrieve_hashtags"] = Event.DONE.value new_tweets = payload["tweets"] @@ -344,6 +350,10 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Event]]: updates[get_name(SynchronizedData.latest_hashtag_tweet_id)] = payload[ "latest_hashtag_tweet_id" ] + else: + updates[ + get_name(SynchronizedData.latest_hashtag_tweet_id) + ] = ceramic_db["module_data"]["twitter"]["latest_hashtag_tweet_id"] synchronized_data = self.synchronized_data.update( synchronized_data_class=SynchronizedData, diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 82ebf0b4..13800087 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeifiaawiifjkum2fxpusym4pvrxr7imr6uqrlb4o5sdhnf5mlyjrse + behaviours.py: bafybeihgt2ttrviakbfbr7qqglu5r5ukupsvk7ntrk2bifjs5bjbcx2b4y ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si fsm_specification.yaml: bafybeieyvejtg6s3tdbrpnnaf56t62y4btmoom7fgdzbq5uzpc7mpc6ewq @@ -16,9 +16,9 @@ fingerprint: models.py: bafybeihqlxg6tbkpkjr5kfdcxwopykvoimczfn22q3owlzgw2elsg76cf4 payloads.py: bafybeihzjioqknhekm7fzlhl52iklkwzuuht6w2qqk5ptutv5s2wqtoedy prompts.py: bafybeieiuqn427bgwfnzynxf3vtqfpvmqqscs5tyw4oibfofwropifotke - rounds.py: bafybeihsqkae4ykxzfwgvgsqzvmlhhufxdmrkaw6b5cdggwd5vdiot4pfq + rounds.py: bafybeicmibaju4mph6nhmbjfhlmndq67vymaq3b6hf63glpexwatxi7tg4 tests/__init__.py: bafybeidwzzd4ejsyf3aryd5kmrvd63h7ajgqyrxphmfaacvpjnneacejay - tests/test_behaviours.py: bafybeiguh5cbo4m4l4r7nufhki4rasvv4qv6shezynzqiipjduxp5w2nby + tests/test_behaviours.py: bafybeihihz2liz3yvnfjskvvc5oxfzhpitvh4fy5bpdngpc7vx6td3ydwy tests/test_ceramic_db.py: bafybeif2v7btjphbqabq6qdmfeyweg765seon74acg5vrrvznivzg2prey tests/test_dialogues.py: bafybeiheyq7klonzb7rnjub2i22h7bmsnoimn2pq4j7ofikt3yovstvgt4 tests/test_handlers.py: bafybeigevirvi3saepukke2zmp334btgsdxhj55o2vawj3hqam63miirg4 @@ -27,7 +27,7 @@ fingerprint: tests/test_rounds.py: bafybeihnsc45rjukbrwtqkshkqdckjrkfcu4u3otxqhukw3duwmat6rdne fingerprint_ignore_patterns: [] connections: -- valory/openai:0.1.0:bafybeib5vnrxnbj3o2olle2n5tp6nzml4ghsghh2rnj2l2ilbvproj35jq +- valory/openai:0.1.0:bafybeih7w2xmaecgznuhxpnbxcxjhfla6wlmx3umytindfgk6ibbwqq2lu contracts: [] protocols: - valory/llm:1.0.0:bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4 From 5f90285ba1a1f48afb8941bcb41d76521fd7da3b Mon Sep 17 00:00:00 2001 From: David Vilela Date: Mon, 4 Sep 2023 18:16:57 +0200 Subject: [PATCH 10/14] fix: check wether twitter handle already exists during registration --- docs/index.md | 2 +- packages/packages.json | 8 ++++---- .../agents/impact_evaluator/aea-config.yaml | 4 ++-- .../services/impact_evaluator/service.yaml | 2 +- .../skills/impact_evaluator_abci/skill.yaml | 2 +- .../skills/twitter_scoring_abci/behaviours.py | 19 ++++++++++++------- .../skills/twitter_scoring_abci/skill.yaml | 2 +- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/docs/index.md b/docs/index.md index 78a5442e..c4013589 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeidasru64g2t3xkskacqh52fyspmzeq4drpzmrx33wvoczv5rjsxhu --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeic5ysbusmwc67lhh6wnjb6dolkkt4hucdo3anbaa67hk7wajkzhrm --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 800d6fcb..75416241 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeigmv2eajssol2zl5pplol6byjfwsngdzzzoxbat6kou5h4q3gisyi", + "agent/valory/impact_evaluator/0.1.0": "bafybeihwtrqr5tn33pyvtrrtzv4uuop6jygyf74wzpvfxpz5trznohfl5u", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeidasru64g2t3xkskacqh52fyspmzeq4drpzmrx33wvoczv5rjsxhu", + "service/valory/impact_evaluator/0.1.0": "bafybeic5ysbusmwc67lhh6wnjb6dolkkt4hucdo3anbaa67hk7wajkzhrm", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeihhw725klhxb4zkihn4f6rscihmarcxlapo4z2ya6sfz4udv7qprq", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeicrweqh6n62vn5houbkjf275a5lniuadrjd3kkaptdcqcukyisrcq", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeicy2sozm5ggg5feaolmdqoj57ktrotevppgux4mtolhqr5wxcxygm", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 84e75b5d..e5efa0d3 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeicrweqh6n62vn5houbkjf275a5lniuadrjd3kkaptdcqcukyisrcq +- valory/impact_evaluator_abci:0.1.0:bafybeicy2sozm5ggg5feaolmdqoj57ktrotevppgux4mtolhqr5wxcxygm - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju +- valory/twitter_scoring_abci:0.1.0:bafybeihhw725klhxb4zkihn4f6rscihmarcxlapo4z2ya6sfz4udv7qprq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 787bde88..8a0b76c0 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeigmv2eajssol2zl5pplol6byjfwsngdzzzoxbat6kou5h4q3gisyi +agent: valory/impact_evaluator:0.1.0:bafybeihwtrqr5tn33pyvtrrtzv4uuop6jygyf74wzpvfxpz5trznohfl5u number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index 9a93b368..f6041c8f 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeigdvdj2hsdbbqmumk2ztzfzthdtkynuyvtfdthg5s2lsqpeg76pju +- valory/twitter_scoring_abci:0.1.0:bafybeihhw725klhxb4zkihn4f6rscihmarcxlapo4z2ya6sfz4udv7qprq - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/behaviours.py b/packages/valory/skills/twitter_scoring_abci/behaviours.py index 5fe7e71d..d18a7bea 100644 --- a/packages/valory/skills/twitter_scoring_abci/behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/behaviours.py @@ -743,18 +743,23 @@ def get_registration(self, text: str) -> Optional[str]: wallet_address = None - registered_addresses = [ - user["wallet_address"] - for user in self.synchronized_data.ceramic_db["users"] - if user["wallet_address"] - ] - address_match = re.search(ADDRESS_REGEX, text) tagline_match = re.search(TAGLINE, text, re.IGNORECASE) if address_match and tagline_match: wallet_address = Web3.to_checksum_address(address_match.group()) - if wallet_address in registered_addresses: + + address_to_twitter_handles = { + user["wallet_address"]: user["twitter_handle"] + for user in self.synchronized_data.ceramic_db["users"] + if user["wallet_address"] + } + + # Ignore registration if both address and Twitter handle already exist + if ( + wallet_address in address_to_twitter_handles + and address_to_twitter_handles[wallet_address] + ): return None return wallet_address diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index f1293ee8..9e70c02e 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeifudgakkjoyahuewp2o4gvqayw7nsgpyxw2ayrpgmzexurh2xomaq - behaviours.py: bafybeidv4khcl4rzqjiev2qga5o6pqpgugauyjw25pbdgoyxgadrsjfid4 + behaviours.py: bafybeig3vogejxlrpalgdjy6ztf27plbookhpsmtunrddl7hmwqvfelsyq ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si fsm_specification.yaml: bafybeietfinv3lvmyon3bk5f4gu2qf4hjlrqogfiombqnncyme5qrpbffa From 7916f39866366f4a22d39e2fb7aefd7ba3b8aded Mon Sep 17 00:00:00 2001 From: David Vilela Date: Mon, 4 Sep 2023 18:53:49 +0200 Subject: [PATCH 11/14] fix: tests --- docs/index.md | 2 +- packages/packages.json | 8 ++++---- .../valory/agents/impact_evaluator/aea-config.yaml | 4 ++-- .../valory/services/impact_evaluator/service.yaml | 2 +- .../valory/skills/impact_evaluator_abci/skill.yaml | 2 +- .../valory/skills/twitter_scoring_abci/skill.yaml | 2 +- .../skills/twitter_scoring_abci/tests/test_rounds.py | 12 ++++++++++-- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/index.md b/docs/index.md index ac0f748d..dfc91c84 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeiggrs7vvlqs5z7jrszgasj4xm4fvbzidnzcrsakn7pxzueyu4ojly --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeiefcjxatzfohm5siddpdh7qkq5smxyxgbbe5ufxkthk7kij5j2ybm --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 176278c0..b9408039 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeieomrbn6vpujq4oq3hdcrxxcnb54u67zjmeqaou7l7lhaxqgpu5oq", + "agent/valory/impact_evaluator/0.1.0": "bafybeicujmj7yzpue6sw7ifnxauw2gbfcfyc67livswkbvh7ukekkl5dda", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeiggrs7vvlqs5z7jrszgasj4xm4fvbzidnzcrsakn7pxzueyu4ojly", + "service/valory/impact_evaluator/0.1.0": "bafybeiefcjxatzfohm5siddpdh7qkq5smxyxgbbe5ufxkthk7kij5j2ybm", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeihnzr74nji3oulzasf44rbrdgc5whsov3aabbmvxm623htv5a5jjm", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeia5nfn3sjefuiscssqlykmb4hxa4un6etb2qaxpteeefjv27mo3re", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 8d744688..c65dfbb0 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeihnzr74nji3oulzasf44rbrdgc5whsov3aabbmvxm623htv5a5jjm +- valory/impact_evaluator_abci:0.1.0:bafybeia5nfn3sjefuiscssqlykmb4hxa4un6etb2qaxpteeefjv27mo3re - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i +- valory/twitter_scoring_abci:0.1.0:bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index fac3e373..0926c88b 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeieomrbn6vpujq4oq3hdcrxxcnb54u67zjmeqaou7l7lhaxqgpu5oq +agent: valory/impact_evaluator:0.1.0:bafybeicujmj7yzpue6sw7ifnxauw2gbfcfyc67livswkbvh7ukekkl5dda number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index c1a839be..fb68090a 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeiemjkvbl55v5xpdxnjih2me3useofj5lmyjsanztajrxry6w5qd3i +- valory/twitter_scoring_abci:0.1.0:bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 13800087..0b300368 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -24,7 +24,7 @@ fingerprint: tests/test_handlers.py: bafybeigevirvi3saepukke2zmp334btgsdxhj55o2vawj3hqam63miirg4 tests/test_models.py: bafybeihaiirqmcsshghztl5lvqjzem6y6rdeefhtiycrhh45v7cuwnmdz4 tests/test_payloads.py: bafybeihzltj7fvfl6n3cylfg6jqaqpiwchfimwys4732hurvkjnwmewksy - tests/test_rounds.py: bafybeihnsc45rjukbrwtqkshkqdckjrkfcu4u3otxqhukw3duwmat6rdne + tests/test_rounds.py: bafybeiajkmlxansdovt2xojnewrgz5jkgjpktd5w5xofy4rqp7tb74il2y fingerprint_ignore_patterns: [] connections: - valory/openai:0.1.0:bafybeih7w2xmaecgznuhxpnbxcxjhfla6wlmx3umytindfgk6ibbwqq2lu diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py index 37e07c70..569fbaae 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_rounds.py @@ -165,7 +165,11 @@ class TestMentionsCollectionRound(BaseScoreReadRoundTest): ( RoundTestCase( name="Happy path", - initial_data={"ceramic_db": {}}, + initial_data={ + "ceramic_db": { + "module_data": {"twitter": {"latest_mention_tweet_id": 0}} + } + }, payloads=get_payloads( payload_cls=TwitterMentionsCollectionPayload, data=get_dummy_mentions_collection_payload_serialized(), @@ -232,7 +236,11 @@ class TestHashtagsCollectionRound(BaseScoreReadRoundTest): ( RoundTestCase( name="Happy path", - initial_data={"ceramic_db": {}}, + initial_data={ + "ceramic_db": { + "module_data": {"twitter": {"latest_hashtag_tweet_id": 0}} + } + }, payloads=get_payloads( payload_cls=TwitterHashtagsCollectionPayload, data=get_dummy_hashtags_collection_payload_serialized(), From 211521c29af47cf0c6421a647ae28bb367ed3ada Mon Sep 17 00:00:00 2001 From: David Vilela Date: Tue, 5 Sep 2023 10:44:14 +0200 Subject: [PATCH 12/14] fix: coverage --- .../skills/twitter_scoring_abci/rounds.py | 4 +- .../tests/test_behaviours.py | 227 ++++++++++++++++++ 2 files changed, 229 insertions(+), 2 deletions(-) diff --git a/packages/valory/skills/twitter_scoring_abci/rounds.py b/packages/valory/skills/twitter_scoring_abci/rounds.py index 2a12d0ca..946c912e 100644 --- a/packages/valory/skills/twitter_scoring_abci/rounds.py +++ b/packages/valory/skills/twitter_scoring_abci/rounds.py @@ -474,8 +474,8 @@ class TwitterScoringAbciApp(AbciApp[Event]): Event.NO_MAJORITY: TwitterDecisionMakingRound, }, OpenAICallCheckRound: { - Event.DONE: TwitterMentionsCollectionRound, - Event.NO_ALLOWANCE: TwitterMentionsCollectionRound, + Event.DONE: TwitterDecisionMakingRound, + Event.NO_ALLOWANCE: TwitterDecisionMakingRound, Event.NO_MAJORITY: OpenAICallCheckRound, Event.ROUND_TIMEOUT: OpenAICallCheckRound, }, diff --git a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py index 8dab78e4..f7ac13f3 100644 --- a/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py +++ b/packages/valory/skills/twitter_scoring_abci/tests/test_behaviours.py @@ -27,6 +27,10 @@ import pytest +from packages.valory.connections.openai.connection import ( + PUBLIC_ID as LLM_CONNECTION_PUBLIC_ID, +) +from packages.valory.protocols.llm.message import LlmMessage from packages.valory.skills.abstract_round_abci.base import AbciAppDB from packages.valory.skills.abstract_round_abci.behaviour_utils import ( make_degenerate_behaviour, @@ -233,6 +237,17 @@ "meta": {"result_count": 1, "newest_id": "1", "oldest_id": "0"}, } +DUMMY_REGISTRATIONS_RESPONSE_MISSING_INCLUDES = { + "data": [ + { + "author_id": "1286010187325812739", + "text": f"{TAGLINE} {ZERO_ADDRESS}", + "id": "10", + }, + ], + "meta": {"result_count": 1, "newest_id": "1", "oldest_id": "0"}, +} + DUMMY_HASHTAGS_RESPONSE = { "data": [ {"author_id": "1286010187325812739", "text": "dummy_text", "id": "1"}, @@ -277,6 +292,7 @@ class BaseBehaviourTest(FSMBehaviourBaseCase): def setup_class(cls, **kwargs: Any) -> None: """Setup class""" super().setup_class(param_overrides={"twitter_max_pages": 10}) + cls.llm_handler = cls._skill.skill_context.handlers.llm def fast_forward(self, data: Optional[Dict[str, Any]] = None) -> None: """Fast-forward on initialization""" @@ -307,6 +323,41 @@ def complete(self, event: Event) -> None: == self.next_behaviour_class.auto_behaviour_id() ) + def mock_llm_request(self, request_kwargs: Dict, response_kwargs: Dict) -> None: + """ + Mock LLM request. + + :param request_kwargs: keyword arguments for request check. + :param response_kwargs: keyword arguments for mock response. + """ + + self.assert_quantity_in_outbox(1) + actual_llm_message = self.get_message_from_outbox() + assert actual_llm_message is not None, "No message in outbox." # nosec + has_attributes, error_str = self.message_has_attributes( + actual_message=actual_llm_message, + message_type=LlmMessage, + to=str(LLM_CONNECTION_PUBLIC_ID), + sender=str(self.skill.skill_context.skill_id), + **request_kwargs, + ) + + assert has_attributes, error_str # nosec + incoming_message = self.build_incoming_message( + message_type=LlmMessage, + dialogue_reference=( + actual_llm_message.dialogue_reference[0], + "stub", + ), + target=actual_llm_message.message_id, + message_id=-1, + to=str(self.skill.skill_context.skill_id), + sender=str(LLM_CONNECTION_PUBLIC_ID), + **response_kwargs, + ) + self.llm_handler.handle(incoming_message) + self.behaviour.act_wrapper() + class TestMentionsCollectionBehaviour(BaseBehaviourTest): """Tests BinanceObservationBehaviour""" @@ -391,6 +442,25 @@ class TestMentionsCollectionBehaviour(BaseBehaviourTest): "status_code": 200, }, ), + ( + BehaviourTestCase( + "API daily limit reached", + initial_data=dict( + ceramic_db={ + "module_data": { + "twitter": { + "number_of_tweets_pulled_today": 10000, + "last_tweet_pull_window_reset": 1993903085, + } + } + } + ), + event=Event.DONE, + ), + { + "request_urls": [], + }, + ), ], ) def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: @@ -500,6 +570,25 @@ class TestHashtagsCollectionBehaviour(BaseBehaviourTest): "status_code": 200, }, ), + ( + BehaviourTestCase( + "API daily limit reached", + initial_data=dict( + ceramic_db={ + "module_data": { + "twitter": { + "number_of_tweets_pulled_today": 10000, + "last_tweet_pull_window_reset": 1993903085, + } + } + } + ), + event=Event.DONE, + ), + { + "request_urls": [], + }, + ), ], ) def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: @@ -685,6 +774,23 @@ class TestHashtagsCollectionBehaviourAPIError(BaseBehaviourTest): "status_codes": [200], }, ), + ( + BehaviourTestCase( + "API error mentions: missing includes", + initial_data=dict(ceramic_db={}), + event=Event.API_ERROR, + ), + { + "urls": [TWITTER_REGISTRATIONS_URL.format(max_results=80)], + "bodies": [ + json.dumps( + DUMMY_REGISTRATIONS_RESPONSE_MISSING_INCLUDES, + ), + json.dumps({}), + ], + "status_codes": [200], + }, + ), ], ) def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: @@ -811,3 +917,124 @@ def test_run(self, test_case: BehaviourTestCase, next_behaviour) -> None: self.fast_forward(test_case.initial_data) self.behaviour.act_wrapper() self.complete(test_case.event) + + +class TestOpenAICallCheckBehaviour(BaseBehaviourTest): + """Tests BinanceObservationBehaviour""" + + behaviour_class = OpenAICallCheckBehaviour + next_behaviour_class = TwitterDecisionMakingBehaviour + + @pytest.mark.parametrize( + "test_case", + ( + BehaviourTestCase( + "Happy path", + initial_data=dict(performed_twitter_tasks={}), + event=Event.DONE, + ), + ), + ) + def test_run(self, test_case: BehaviourTestCase) -> None: + """Run tests.""" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + self.complete(test_case.event) + + +class TestTweetEvaluationBehaviour(BaseBehaviourTest): + """Tests TweetEvaluationBehaviour""" + + behaviour_class = TweetEvaluationBehaviour + next_behaviour_class = TwitterDecisionMakingBehaviour + + @pytest.mark.parametrize( + "test_case, kwargs", + [ + ( + BehaviourTestCase( + "Happy path", + initial_data=dict(tweets={"1": {"text": "dummy text"}}), + event=Event.DONE, + ), + {}, + ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: + """Run tests.""" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + self.mock_llm_request( + request_kwargs=dict(performative=LlmMessage.Performative.REQUEST), + response_kwargs=dict( + performative=LlmMessage.Performative.RESPONSE, + value='{"quality":"HIGH","relationship":"HIGH"}', + ), + ) + self.complete(test_case.event) + + +class TestDBUpdateBehaviour(BaseBehaviourTest): + """Tests DBUpdateBehaviour""" + + behaviour_class = DBUpdateBehaviour + next_behaviour_class = TwitterDecisionMakingBehaviour + + @pytest.mark.parametrize( + "test_case, kwargs", + [ + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + tweets={ + "1": { + "author_id": "1", + "points": 900, + "username": "dummy", + "text": "dummy text", + }, + "2": { + "author_id": "2", + "points": 900, + "username": "dummy_2", + "text": "dummy text", + }, + "3": { + "author_id": "3", + "points": 900, + "username": "dummy_3", + "text": "I'm linking my wallet to @Autonolas Contribute: 0x0000000000000000000000000000000000000000", + }, + "4": { + "author_id": "1", + "points": 10000, # too many points during this period + "username": "dummy", + "text": "dummy text", + }, + }, + latest_mention_tweet_id=1, + latest_hashtag_tweet_id=1, + number_of_tweets_pulled_today=1, + last_tweet_pull_window_reset=1993903085, # in 10 years + ceramic_db={ + "users": [ + {"twitter_id": "1", "points": 0, "wallet_address": None} + ], + "module_data": { + "twitter": {"current_period": "2023-09-04"} + }, + }, + ), + event=Event.DONE, + ), + {}, + ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, kwargs: Any) -> None: + """Run tests.""" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + self.complete(test_case.event) From 4ff1064516061faae0fb619593f44eef47e94faf Mon Sep 17 00:00:00 2001 From: David Vilela Date: Tue, 5 Sep 2023 12:15:52 +0200 Subject: [PATCH 13/14] fix: generators --- docs/index.md | 2 +- packages/packages.json | 8 ++++---- packages/valory/agents/impact_evaluator/aea-config.yaml | 4 ++-- packages/valory/services/impact_evaluator/service.yaml | 2 +- packages/valory/skills/impact_evaluator_abci/skill.yaml | 2 +- packages/valory/skills/twitter_scoring_abci/skill.yaml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/index.md b/docs/index.md index dfc91c84..fbfe25dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeiefcjxatzfohm5siddpdh7qkq5smxyxgbbe5ufxkthk7kij5j2ybm --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeigmx5gphfnyusvbykk5nilklrkp4apuhmy7knodgakm44f3ojrwm4 --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index b9408039..1aa885e2 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeicujmj7yzpue6sw7ifnxauw2gbfcfyc67livswkbvh7ukekkl5dda", + "agent/valory/impact_evaluator/0.1.0": "bafybeibbuzjjhqneo2etwhth4otq5m7np6iywzmvgrqlz2i3nqyukk36wy", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeiefcjxatzfohm5siddpdh7qkq5smxyxgbbe5ufxkthk7kij5j2ybm", + "service/valory/impact_evaluator/0.1.0": "bafybeigmx5gphfnyusvbykk5nilklrkp4apuhmy7knodgakm44f3ojrwm4", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeia5nfn3sjefuiscssqlykmb4hxa4un6etb2qaxpteeefjv27mo3re", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeic2whroqhrcaye4qdtau5ihvhcz54cijy6tvxqulvshwnhnu3uhoa", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index c65dfbb0..3af8c918 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeia5nfn3sjefuiscssqlykmb4hxa4un6etb2qaxpteeefjv27mo3re +- valory/impact_evaluator_abci:0.1.0:bafybeic2whroqhrcaye4qdtau5ihvhcz54cijy6tvxqulvshwnhnu3uhoa - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi +- valory/twitter_scoring_abci:0.1.0:bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 0926c88b..faed97a6 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeicujmj7yzpue6sw7ifnxauw2gbfcfyc67livswkbvh7ukekkl5dda +agent: valory/impact_evaluator:0.1.0:bafybeibbuzjjhqneo2etwhth4otq5m7np6iywzmvgrqlz2i3nqyukk36wy number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index fb68090a..3939f233 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeidgufak5kqr4ckrugj4e7gdps6htznjbleik77gylppt3r4kpukzi +- valory/twitter_scoring_abci:0.1.0:bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 0b300368..6430c688 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -16,9 +16,9 @@ fingerprint: models.py: bafybeihqlxg6tbkpkjr5kfdcxwopykvoimczfn22q3owlzgw2elsg76cf4 payloads.py: bafybeihzjioqknhekm7fzlhl52iklkwzuuht6w2qqk5ptutv5s2wqtoedy prompts.py: bafybeieiuqn427bgwfnzynxf3vtqfpvmqqscs5tyw4oibfofwropifotke - rounds.py: bafybeicmibaju4mph6nhmbjfhlmndq67vymaq3b6hf63glpexwatxi7tg4 + rounds.py: bafybeia24avvmoqf3vmsdrz2bvrdynlzrjohnyiw47acmabmvzj7qygdx4 tests/__init__.py: bafybeidwzzd4ejsyf3aryd5kmrvd63h7ajgqyrxphmfaacvpjnneacejay - tests/test_behaviours.py: bafybeihihz2liz3yvnfjskvvc5oxfzhpitvh4fy5bpdngpc7vx6td3ydwy + tests/test_behaviours.py: bafybeid3m7duxfaholuxj6obctzv4ao3ci5zruscaqfgeahehrdqrak4ja tests/test_ceramic_db.py: bafybeif2v7btjphbqabq6qdmfeyweg765seon74acg5vrrvznivzg2prey tests/test_dialogues.py: bafybeiheyq7klonzb7rnjub2i22h7bmsnoimn2pq4j7ofikt3yovstvgt4 tests/test_handlers.py: bafybeigevirvi3saepukke2zmp334btgsdxhj55o2vawj3hqam63miirg4 From 3adc551793166062f0abc72efb4faac036f5233b Mon Sep 17 00:00:00 2001 From: David Vilela Date: Tue, 5 Sep 2023 12:23:04 +0200 Subject: [PATCH 14/14] fix: linters --- docs/index.md | 2 +- packages/packages.json | 8 ++++---- packages/valory/agents/impact_evaluator/aea-config.yaml | 4 ++-- packages/valory/services/impact_evaluator/service.yaml | 2 +- .../skills/impact_evaluator_abci/fsm_specification.yaml | 4 ++-- packages/valory/skills/impact_evaluator_abci/skill.yaml | 4 ++-- .../skills/twitter_scoring_abci/fsm_specification.yaml | 4 ++-- packages/valory/skills/twitter_scoring_abci/skill.yaml | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/index.md b/docs/index.md index fbfe25dd..bbb1a1b0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeigmx5gphfnyusvbykk5nilklrkp4apuhmy7knodgakm44f3ojrwm4 --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeigfcxdeaefg3p2k3i57pdl3ociq4mer26zatofhjqi5igdj4bllqq --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 1aa885e2..cd253beb 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,13 +1,13 @@ { "dev": { - "agent/valory/impact_evaluator/0.1.0": "bafybeibbuzjjhqneo2etwhth4otq5m7np6iywzmvgrqlz2i3nqyukk36wy", + "agent/valory/impact_evaluator/0.1.0": "bafybeifbavdtyz6wjpk2gke4qglk2c2yu3dfdgxqbqzjepexvpxsn67vcu", "contract/valory/dynamic_contribution/0.1.0": "bafybeie76ynpueo3hh2ujzcfgpqcsbyqwa4pdcc6g44a4he6bueyb4tqiy", - "service/valory/impact_evaluator/0.1.0": "bafybeigmx5gphfnyusvbykk5nilklrkp4apuhmy7knodgakm44f3ojrwm4", + "service/valory/impact_evaluator/0.1.0": "bafybeigfcxdeaefg3p2k3i57pdl3ociq4mer26zatofhjqi5igdj4bllqq", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeih2r3wdv3ysq72ndpodxrtzf7qt23ubrjyg4msyojzk2meqmrk6py", "skill/valory/ceramic_read_abci/0.1.0": "bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeic2whroqhrcaye4qdtau5ihvhcz54cijy6tvxqulvshwnhnu3uhoa", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeid2m3wybip7aiwqetxtbggm3zst3juyylthcveo2ijrxreambqrza", "skill/valory/generic_scoring_abci/0.1.0": "bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq", "protocol/valory/twitter/0.1.0": "bafybeib4eyf7qbs7kdntqzhwqsaaj4o2mzcokcztaza6qgwt7sbxgkqu2m", "protocol/valory/llm/1.0.0": "bafybeigqybmg75vsxexmp57hkms7lkp7iwpf54r7wpygizxryvrhfqqpb4", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 3af8c918..69c686b5 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -42,9 +42,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeicg7dv7cff34nv2k2z47c4yp4kddsxp3wozonzow6tnvfvwndz3cy - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq -- valory/impact_evaluator_abci:0.1.0:bafybeic2whroqhrcaye4qdtau5ihvhcz54cijy6tvxqulvshwnhnu3uhoa +- valory/impact_evaluator_abci:0.1.0:bafybeid2m3wybip7aiwqetxtbggm3zst3juyylthcveo2ijrxreambqrza - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu +- valory/twitter_scoring_abci:0.1.0:bafybeih2r3wdv3ysq72ndpodxrtzf7qt23ubrjyg4msyojzk2meqmrk6py - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index faed97a6..77a97f8c 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeibbuzjjhqneo2etwhth4otq5m7np6iywzmvgrqlz2i3nqyukk36wy +agent: valory/impact_evaluator:0.1.0:bafybeifbavdtyz6wjpk2gke4qglk2c2yu3dfdgxqbqzjepexvpxsn67vcu number_of_agents: 4 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml index 6099f7d4..eb04dff3 100644 --- a/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml +++ b/packages/valory/skills/impact_evaluator_abci/fsm_specification.yaml @@ -92,8 +92,8 @@ transition_func: (LLMSelectKeeperRound, DONE): LLMRound (LLMSelectKeeperRound, NO_MAJORITY): LLMRandomnessRound (LLMSelectKeeperRound, ROUND_TIMEOUT): LLMRandomnessRound - (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound - (OpenAICallCheckRound, NO_ALLOWANCE): TwitterMentionsCollectionRound + (OpenAICallCheckRound, DONE): TwitterDecisionMakingRound + (OpenAICallCheckRound, NO_ALLOWANCE): TwitterDecisionMakingRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound (OpenAICallCheckRound, ROUND_TIMEOUT): OpenAICallCheckRound (RandomnessRound, DONE): SelectKeeperRound diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index 3939f233..d5de6dc3 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -10,7 +10,7 @@ fingerprint: behaviours.py: bafybeifhoufesr4r4re65mxjadqasjymvz6tkc25xn5yyn473yunhjiufe composition.py: bafybeifmf52jhbiyyqyxzd67gxrydedm44ouzib3jh56kzoe5xohjrhm34 dialogues.py: bafybeigjknz4qqynbsltjje46gidg4rftsqw6ybjwegz24wetmycutpzh4 - fsm_specification.yaml: bafybeicbmtw5gpevf5kdenu3aukxqsurov3rv5iyeygyykoecdnduiu5wq + fsm_specification.yaml: bafybeibgyjc25ukeorz3w3vxnmnjhczvy3psobl4gtivcbhnfq5qetwh4y handlers.py: bafybeidkli6fphcmdgwsys4lkyf3fx6fbawet4nt2pnixfypzijhg6b3ze models.py: bafybeifhcshu4iwqvc2fz3auu5ngfykkhvqnroeug52ilrwwc4kowkeg5a tests/__init__.py: bafybeievwzwojvq4aofk5kjpf4jzygfes7ew6s6svc6b6frktjnt3sicce @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeigxjcci53vwytymzlhr37436yvenh7jup4astrn7dgyixo24aq2pq - valory/ceramic_read_abci:0.1.0:bafybeidruvxgpbggchuvlnssuswdxuoz2ep6sjvzzqjeyckybb6gpjx3ia - valory/generic_scoring_abci:0.1.0:bafybeiemmcnduhdj427kgafkxcbn2rfhaihabtpda34yqnks7utm3g4xiq -- valory/twitter_scoring_abci:0.1.0:bafybeibzd5cwnybnoyy6n3yl4xvvddgnddceciihkhnibr37webpbwtpcu +- valory/twitter_scoring_abci:0.1.0:bafybeih2r3wdv3ysq72ndpodxrtzf7qt23ubrjyg4msyojzk2meqmrk6py - valory/ceramic_write_abci:0.1.0:bafybeigtkv57h5suaqqpjfknimfegbidovxna7cok7znsgzrfb4nftqvay - valory/dynamic_nft_abci:0.1.0:bafybeie5vfscnjpvuwqe5vk7i2rzzlqciojswdg7uh34fjnuk3bspca5zq - valory/registration_abci:0.1.0:bafybeibc4kczqbh23sc6tufrzn3axmhp3vjav7fa3u6cnpvolrbbc2fd7i diff --git a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml index 3d5046f2..7bd7748a 100644 --- a/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml +++ b/packages/valory/skills/twitter_scoring_abci/fsm_specification.yaml @@ -30,8 +30,8 @@ transition_func: (DBUpdateRound, DONE): TwitterDecisionMakingRound (DBUpdateRound, NO_MAJORITY): DBUpdateRound (DBUpdateRound, ROUND_TIMEOUT): DBUpdateRound - (OpenAICallCheckRound, DONE): TwitterMentionsCollectionRound - (OpenAICallCheckRound, NO_ALLOWANCE): TwitterMentionsCollectionRound + (OpenAICallCheckRound, DONE): TwitterDecisionMakingRound + (OpenAICallCheckRound, NO_ALLOWANCE): TwitterDecisionMakingRound (OpenAICallCheckRound, NO_MAJORITY): OpenAICallCheckRound (OpenAICallCheckRound, ROUND_TIMEOUT): OpenAICallCheckRound (TweetEvaluationRound, DONE): TwitterDecisionMakingRound diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 6430c688..22bf1a01 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -11,7 +11,7 @@ fingerprint: behaviours.py: bafybeihgt2ttrviakbfbr7qqglu5r5ukupsvk7ntrk2bifjs5bjbcx2b4y ceramic_db.py: bafybeicusdonrdq6kirgkpdqmi3a6kmeal4nctnm5ozjqf5s5se6jpitjm dialogues.py: bafybeibdqzn37hbo2cq4skww4uh2zvvsjyaxxvdhxisefbdvmjp7rh53si - fsm_specification.yaml: bafybeieyvejtg6s3tdbrpnnaf56t62y4btmoom7fgdzbq5uzpc7mpc6ewq + fsm_specification.yaml: bafybeihpy75zlftkveim56lhsuyfoxd4o54cx3m5seephrihakvvqthy4a handlers.py: bafybeid3nqvcyotqj5g5hlgrz57nf7vpjysmgvsxe3p7644f4z5dcwqn6u models.py: bafybeihqlxg6tbkpkjr5kfdcxwopykvoimczfn22q3owlzgw2elsg76cf4 payloads.py: bafybeihzjioqknhekm7fzlhl52iklkwzuuht6w2qqk5ptutv5s2wqtoedy