intentkit 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +17 -0
- intentkit/abstracts/__init__.py +0 -0
- intentkit/abstracts/agent.py +60 -0
- intentkit/abstracts/api.py +4 -0
- intentkit/abstracts/engine.py +38 -0
- intentkit/abstracts/exception.py +9 -0
- intentkit/abstracts/graph.py +25 -0
- intentkit/abstracts/skill.py +129 -0
- intentkit/abstracts/twitter.py +54 -0
- intentkit/clients/__init__.py +14 -0
- intentkit/clients/cdp.py +53 -0
- intentkit/clients/twitter.py +445 -0
- intentkit/config/__init__.py +0 -0
- intentkit/config/config.py +164 -0
- intentkit/core/__init__.py +0 -0
- intentkit/core/agent.py +191 -0
- intentkit/core/api.py +40 -0
- intentkit/core/client.py +45 -0
- intentkit/core/credit.py +1767 -0
- intentkit/core/engine.py +1018 -0
- intentkit/core/node.py +223 -0
- intentkit/core/prompt.py +58 -0
- intentkit/core/skill.py +124 -0
- intentkit/models/agent.py +1689 -0
- intentkit/models/agent_data.py +810 -0
- intentkit/models/agent_schema.json +733 -0
- intentkit/models/app_setting.py +156 -0
- intentkit/models/base.py +9 -0
- intentkit/models/chat.py +581 -0
- intentkit/models/conversation.py +286 -0
- intentkit/models/credit.py +1406 -0
- intentkit/models/db.py +120 -0
- intentkit/models/db_mig.py +102 -0
- intentkit/models/generator.py +347 -0
- intentkit/models/llm.py +746 -0
- intentkit/models/redis.py +132 -0
- intentkit/models/skill.py +466 -0
- intentkit/models/user.py +243 -0
- intentkit/skills/__init__.py +12 -0
- intentkit/skills/acolyt/__init__.py +83 -0
- intentkit/skills/acolyt/acolyt.jpg +0 -0
- intentkit/skills/acolyt/ask.py +128 -0
- intentkit/skills/acolyt/base.py +28 -0
- intentkit/skills/acolyt/schema.json +89 -0
- intentkit/skills/aixbt/README.md +71 -0
- intentkit/skills/aixbt/__init__.py +73 -0
- intentkit/skills/aixbt/aixbt.jpg +0 -0
- intentkit/skills/aixbt/base.py +21 -0
- intentkit/skills/aixbt/projects.py +153 -0
- intentkit/skills/aixbt/schema.json +99 -0
- intentkit/skills/allora/__init__.py +83 -0
- intentkit/skills/allora/allora.jpeg +0 -0
- intentkit/skills/allora/base.py +28 -0
- intentkit/skills/allora/price.py +130 -0
- intentkit/skills/allora/schema.json +89 -0
- intentkit/skills/base.py +174 -0
- intentkit/skills/carv/README.md +95 -0
- intentkit/skills/carv/__init__.py +121 -0
- intentkit/skills/carv/base.py +183 -0
- intentkit/skills/carv/carv.webp +0 -0
- intentkit/skills/carv/fetch_news.py +92 -0
- intentkit/skills/carv/onchain_query.py +164 -0
- intentkit/skills/carv/schema.json +137 -0
- intentkit/skills/carv/token_info_and_price.py +110 -0
- intentkit/skills/cdp/__init__.py +137 -0
- intentkit/skills/cdp/base.py +21 -0
- intentkit/skills/cdp/cdp.png +0 -0
- intentkit/skills/cdp/get_balance.py +81 -0
- intentkit/skills/cdp/schema.json +473 -0
- intentkit/skills/chainlist/README.md +38 -0
- intentkit/skills/chainlist/__init__.py +54 -0
- intentkit/skills/chainlist/base.py +21 -0
- intentkit/skills/chainlist/chain_lookup.py +208 -0
- intentkit/skills/chainlist/chainlist.png +0 -0
- intentkit/skills/chainlist/schema.json +47 -0
- intentkit/skills/common/__init__.py +82 -0
- intentkit/skills/common/base.py +21 -0
- intentkit/skills/common/common.jpg +0 -0
- intentkit/skills/common/current_time.py +84 -0
- intentkit/skills/common/schema.json +57 -0
- intentkit/skills/cookiefun/README.md +121 -0
- intentkit/skills/cookiefun/__init__.py +78 -0
- intentkit/skills/cookiefun/base.py +41 -0
- intentkit/skills/cookiefun/constants.py +18 -0
- intentkit/skills/cookiefun/cookiefun.png +0 -0
- intentkit/skills/cookiefun/get_account_details.py +171 -0
- intentkit/skills/cookiefun/get_account_feed.py +282 -0
- intentkit/skills/cookiefun/get_account_smart_followers.py +181 -0
- intentkit/skills/cookiefun/get_sectors.py +128 -0
- intentkit/skills/cookiefun/schema.json +155 -0
- intentkit/skills/cookiefun/search_accounts.py +225 -0
- intentkit/skills/cryptocompare/__init__.py +130 -0
- intentkit/skills/cryptocompare/api.py +159 -0
- intentkit/skills/cryptocompare/base.py +303 -0
- intentkit/skills/cryptocompare/cryptocompare.png +0 -0
- intentkit/skills/cryptocompare/fetch_news.py +96 -0
- intentkit/skills/cryptocompare/fetch_price.py +99 -0
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +113 -0
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +109 -0
- intentkit/skills/cryptocompare/fetch_top_volume.py +108 -0
- intentkit/skills/cryptocompare/fetch_trading_signals.py +107 -0
- intentkit/skills/cryptocompare/schema.json +168 -0
- intentkit/skills/cryptopanic/__init__.py +108 -0
- intentkit/skills/cryptopanic/base.py +51 -0
- intentkit/skills/cryptopanic/cryptopanic.png +0 -0
- intentkit/skills/cryptopanic/fetch_crypto_news.py +153 -0
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +136 -0
- intentkit/skills/cryptopanic/schema.json +103 -0
- intentkit/skills/dapplooker/README.md +92 -0
- intentkit/skills/dapplooker/__init__.py +83 -0
- intentkit/skills/dapplooker/base.py +26 -0
- intentkit/skills/dapplooker/dapplooker.jpg +0 -0
- intentkit/skills/dapplooker/dapplooker_token_data.py +476 -0
- intentkit/skills/dapplooker/schema.json +91 -0
- intentkit/skills/defillama/__init__.py +323 -0
- intentkit/skills/defillama/api.py +315 -0
- intentkit/skills/defillama/base.py +135 -0
- intentkit/skills/defillama/coins/__init__.py +0 -0
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +116 -0
- intentkit/skills/defillama/coins/fetch_block.py +98 -0
- intentkit/skills/defillama/coins/fetch_current_prices.py +105 -0
- intentkit/skills/defillama/coins/fetch_first_price.py +100 -0
- intentkit/skills/defillama/coins/fetch_historical_prices.py +110 -0
- intentkit/skills/defillama/coins/fetch_price_chart.py +109 -0
- intentkit/skills/defillama/coins/fetch_price_percentage.py +93 -0
- intentkit/skills/defillama/config/__init__.py +0 -0
- intentkit/skills/defillama/config/chains.py +433 -0
- intentkit/skills/defillama/defillama.jpeg +0 -0
- intentkit/skills/defillama/fees/__init__.py +0 -0
- intentkit/skills/defillama/fees/fetch_fees_overview.py +130 -0
- intentkit/skills/defillama/schema.json +383 -0
- intentkit/skills/defillama/stablecoins/__init__.py +0 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +100 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +129 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +83 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +126 -0
- intentkit/skills/defillama/tests/__init__.py +0 -0
- intentkit/skills/defillama/tests/api_integration.test.py +192 -0
- intentkit/skills/defillama/tests/api_unit.test.py +583 -0
- intentkit/skills/defillama/tvl/__init__.py +0 -0
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +106 -0
- intentkit/skills/defillama/tvl/fetch_chains.py +107 -0
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +91 -0
- intentkit/skills/defillama/tvl/fetch_protocol.py +207 -0
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +93 -0
- intentkit/skills/defillama/tvl/fetch_protocols.py +196 -0
- intentkit/skills/defillama/volumes/__init__.py +0 -0
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +157 -0
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +123 -0
- intentkit/skills/defillama/volumes/fetch_options_overview.py +131 -0
- intentkit/skills/defillama/yields/__init__.py +0 -0
- intentkit/skills/defillama/yields/fetch_pool_chart.py +100 -0
- intentkit/skills/defillama/yields/fetch_pools.py +126 -0
- intentkit/skills/dexscreener/__init__.py +93 -0
- intentkit/skills/dexscreener/base.py +133 -0
- intentkit/skills/dexscreener/dexscreener.png +0 -0
- intentkit/skills/dexscreener/model/__init__.py +0 -0
- intentkit/skills/dexscreener/model/search_token_response.py +82 -0
- intentkit/skills/dexscreener/schema.json +48 -0
- intentkit/skills/dexscreener/search_token.py +321 -0
- intentkit/skills/dune_analytics/__init__.py +103 -0
- intentkit/skills/dune_analytics/base.py +46 -0
- intentkit/skills/dune_analytics/dune.png +0 -0
- intentkit/skills/dune_analytics/fetch_kol_buys.py +128 -0
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +237 -0
- intentkit/skills/dune_analytics/schema.json +99 -0
- intentkit/skills/elfa/README.md +100 -0
- intentkit/skills/elfa/__init__.py +123 -0
- intentkit/skills/elfa/base.py +28 -0
- intentkit/skills/elfa/elfa.jpg +0 -0
- intentkit/skills/elfa/mention.py +504 -0
- intentkit/skills/elfa/schema.json +153 -0
- intentkit/skills/elfa/stats.py +118 -0
- intentkit/skills/elfa/tokens.py +126 -0
- intentkit/skills/enso/README.md +75 -0
- intentkit/skills/enso/__init__.py +114 -0
- intentkit/skills/enso/abi/__init__.py +0 -0
- intentkit/skills/enso/abi/approval.py +279 -0
- intentkit/skills/enso/abi/erc20.py +14 -0
- intentkit/skills/enso/abi/route.py +129 -0
- intentkit/skills/enso/base.py +44 -0
- intentkit/skills/enso/best_yield.py +286 -0
- intentkit/skills/enso/enso.jpg +0 -0
- intentkit/skills/enso/networks.py +105 -0
- intentkit/skills/enso/prices.py +93 -0
- intentkit/skills/enso/route.py +300 -0
- intentkit/skills/enso/schema.json +212 -0
- intentkit/skills/enso/tokens.py +223 -0
- intentkit/skills/enso/wallet.py +381 -0
- intentkit/skills/github/README.md +63 -0
- intentkit/skills/github/__init__.py +54 -0
- intentkit/skills/github/base.py +21 -0
- intentkit/skills/github/github.jpg +0 -0
- intentkit/skills/github/github_search.py +183 -0
- intentkit/skills/github/schema.json +59 -0
- intentkit/skills/heurist/__init__.py +143 -0
- intentkit/skills/heurist/base.py +26 -0
- intentkit/skills/heurist/heurist.png +0 -0
- intentkit/skills/heurist/image_generation_animagine_xl.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_comics.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_real.py +162 -0
- intentkit/skills/heurist/image_generation_braindance.py +162 -0
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +162 -0
- intentkit/skills/heurist/image_generation_flux_1_dev.py +162 -0
- intentkit/skills/heurist/image_generation_sdxl.py +161 -0
- intentkit/skills/heurist/schema.json +196 -0
- intentkit/skills/lifi/README.md +294 -0
- intentkit/skills/lifi/__init__.py +141 -0
- intentkit/skills/lifi/base.py +21 -0
- intentkit/skills/lifi/lifi.png +0 -0
- intentkit/skills/lifi/schema.json +89 -0
- intentkit/skills/lifi/token_execute.py +472 -0
- intentkit/skills/lifi/token_quote.py +190 -0
- intentkit/skills/lifi/utils.py +656 -0
- intentkit/skills/moralis/README.md +490 -0
- intentkit/skills/moralis/__init__.py +110 -0
- intentkit/skills/moralis/api.py +281 -0
- intentkit/skills/moralis/base.py +55 -0
- intentkit/skills/moralis/fetch_chain_portfolio.py +191 -0
- intentkit/skills/moralis/fetch_nft_portfolio.py +284 -0
- intentkit/skills/moralis/fetch_solana_portfolio.py +331 -0
- intentkit/skills/moralis/fetch_wallet_portfolio.py +301 -0
- intentkit/skills/moralis/moralis.png +0 -0
- intentkit/skills/moralis/schema.json +156 -0
- intentkit/skills/moralis/tests/__init__.py +0 -0
- intentkit/skills/moralis/tests/test_wallet.py +511 -0
- intentkit/skills/nation/__init__.py +62 -0
- intentkit/skills/nation/base.py +31 -0
- intentkit/skills/nation/nation.png +0 -0
- intentkit/skills/nation/nft_check.py +106 -0
- intentkit/skills/nation/schema.json +58 -0
- intentkit/skills/openai/__init__.py +107 -0
- intentkit/skills/openai/base.py +32 -0
- intentkit/skills/openai/dalle_image_generation.py +128 -0
- intentkit/skills/openai/gpt_image_generation.py +152 -0
- intentkit/skills/openai/gpt_image_to_image.py +186 -0
- intentkit/skills/openai/image_to_text.py +126 -0
- intentkit/skills/openai/openai.png +0 -0
- intentkit/skills/openai/schema.json +139 -0
- intentkit/skills/portfolio/README.md +55 -0
- intentkit/skills/portfolio/__init__.py +151 -0
- intentkit/skills/portfolio/base.py +107 -0
- intentkit/skills/portfolio/constants.py +9 -0
- intentkit/skills/portfolio/moralis.png +0 -0
- intentkit/skills/portfolio/schema.json +237 -0
- intentkit/skills/portfolio/token_balances.py +155 -0
- intentkit/skills/portfolio/wallet_approvals.py +102 -0
- intentkit/skills/portfolio/wallet_defi_positions.py +80 -0
- intentkit/skills/portfolio/wallet_history.py +155 -0
- intentkit/skills/portfolio/wallet_net_worth.py +112 -0
- intentkit/skills/portfolio/wallet_nfts.py +139 -0
- intentkit/skills/portfolio/wallet_profitability.py +101 -0
- intentkit/skills/portfolio/wallet_profitability_summary.py +91 -0
- intentkit/skills/portfolio/wallet_stats.py +79 -0
- intentkit/skills/portfolio/wallet_swaps.py +147 -0
- intentkit/skills/skills.toml +103 -0
- intentkit/skills/slack/__init__.py +98 -0
- intentkit/skills/slack/base.py +55 -0
- intentkit/skills/slack/get_channel.py +109 -0
- intentkit/skills/slack/get_message.py +136 -0
- intentkit/skills/slack/schedule_message.py +92 -0
- intentkit/skills/slack/schema.json +135 -0
- intentkit/skills/slack/send_message.py +81 -0
- intentkit/skills/slack/slack.jpg +0 -0
- intentkit/skills/system/__init__.py +90 -0
- intentkit/skills/system/base.py +22 -0
- intentkit/skills/system/read_agent_api_key.py +87 -0
- intentkit/skills/system/regenerate_agent_api_key.py +77 -0
- intentkit/skills/system/schema.json +53 -0
- intentkit/skills/system/system.svg +76 -0
- intentkit/skills/tavily/README.md +86 -0
- intentkit/skills/tavily/__init__.py +91 -0
- intentkit/skills/tavily/base.py +27 -0
- intentkit/skills/tavily/schema.json +119 -0
- intentkit/skills/tavily/tavily.jpg +0 -0
- intentkit/skills/tavily/tavily_extract.py +147 -0
- intentkit/skills/tavily/tavily_search.py +139 -0
- intentkit/skills/token/README.md +89 -0
- intentkit/skills/token/__init__.py +107 -0
- intentkit/skills/token/base.py +154 -0
- intentkit/skills/token/constants.py +9 -0
- intentkit/skills/token/erc20_transfers.py +145 -0
- intentkit/skills/token/moralis.png +0 -0
- intentkit/skills/token/schema.json +141 -0
- intentkit/skills/token/token_analytics.py +81 -0
- intentkit/skills/token/token_price.py +132 -0
- intentkit/skills/token/token_search.py +121 -0
- intentkit/skills/twitter/__init__.py +146 -0
- intentkit/skills/twitter/base.py +68 -0
- intentkit/skills/twitter/follow_user.py +69 -0
- intentkit/skills/twitter/get_mentions.py +124 -0
- intentkit/skills/twitter/get_timeline.py +111 -0
- intentkit/skills/twitter/get_user_by_username.py +84 -0
- intentkit/skills/twitter/get_user_tweets.py +123 -0
- intentkit/skills/twitter/like_tweet.py +65 -0
- intentkit/skills/twitter/post_tweet.py +90 -0
- intentkit/skills/twitter/reply_tweet.py +98 -0
- intentkit/skills/twitter/retweet.py +76 -0
- intentkit/skills/twitter/schema.json +258 -0
- intentkit/skills/twitter/search_tweets.py +115 -0
- intentkit/skills/twitter/twitter.png +0 -0
- intentkit/skills/unrealspeech/__init__.py +55 -0
- intentkit/skills/unrealspeech/base.py +21 -0
- intentkit/skills/unrealspeech/schema.json +100 -0
- intentkit/skills/unrealspeech/text_to_speech.py +177 -0
- intentkit/skills/unrealspeech/unrealspeech.jpg +0 -0
- intentkit/skills/venice_audio/__init__.py +106 -0
- intentkit/skills/venice_audio/base.py +119 -0
- intentkit/skills/venice_audio/input.py +41 -0
- intentkit/skills/venice_audio/schema.json +152 -0
- intentkit/skills/venice_audio/venice_audio.py +240 -0
- intentkit/skills/venice_audio/venice_logo.jpg +0 -0
- intentkit/skills/venice_image/README.md +119 -0
- intentkit/skills/venice_image/__init__.py +154 -0
- intentkit/skills/venice_image/api.py +138 -0
- intentkit/skills/venice_image/base.py +188 -0
- intentkit/skills/venice_image/config.py +35 -0
- intentkit/skills/venice_image/image_enhance/README.md +119 -0
- intentkit/skills/venice_image/image_enhance/__init__.py +0 -0
- intentkit/skills/venice_image/image_enhance/image_enhance.py +80 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_base.py +23 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_input.py +40 -0
- intentkit/skills/venice_image/image_generation/README.md +144 -0
- intentkit/skills/venice_image/image_generation/__init__.py +0 -0
- intentkit/skills/venice_image/image_generation/image_generation_base.py +117 -0
- intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -0
- intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -0
- intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -0
- intentkit/skills/venice_image/image_upscale/README.md +111 -0
- intentkit/skills/venice_image/image_upscale/__init__.py +0 -0
- intentkit/skills/venice_image/image_upscale/image_upscale.py +90 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_base.py +23 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -0
- intentkit/skills/venice_image/image_vision/README.md +112 -0
- intentkit/skills/venice_image/image_vision/__init__.py +0 -0
- intentkit/skills/venice_image/image_vision/image_vision.py +100 -0
- intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -0
- intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -0
- intentkit/skills/venice_image/schema.json +267 -0
- intentkit/skills/venice_image/utils.py +78 -0
- intentkit/skills/venice_image/venice_image.jpg +0 -0
- intentkit/skills/web_scraper/README.md +82 -0
- intentkit/skills/web_scraper/__init__.py +92 -0
- intentkit/skills/web_scraper/base.py +21 -0
- intentkit/skills/web_scraper/langchain.png +0 -0
- intentkit/skills/web_scraper/schema.json +115 -0
- intentkit/skills/web_scraper/scrape_and_index.py +327 -0
- intentkit/utils/__init__.py +1 -0
- intentkit/utils/chain.py +436 -0
- intentkit/utils/error.py +134 -0
- intentkit/utils/logging.py +70 -0
- intentkit/utils/middleware.py +61 -0
- intentkit/utils/random.py +16 -0
- intentkit/utils/s3.py +267 -0
- intentkit/utils/slack_alert.py +79 -0
- intentkit/utils/tx.py +37 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/METADATA +1 -1
- intentkit-0.5.2.dist-info/RECORD +365 -0
- intentkit-0.5.0.dist-info/RECORD +0 -4
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/WHEEL +0 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import string
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def generate_tx_confirm_string(length) -> str:
|
|
6
|
+
"""
|
|
7
|
+
Generates a random string of the specified length for the transaction reference.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
length: The desired length of the random string.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
A random string of the specified length.
|
|
14
|
+
"""
|
|
15
|
+
letters_and_digits = string.ascii_letters + string.digits
|
|
16
|
+
return "tx-" + "".join(random.choice(letters_and_digits) for _ in range(length))
|
intentkit/utils/s3.py
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""
|
|
2
|
+
S3 utility module for storing and retrieving images from AWS S3.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from io import BytesIO
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import boto3
|
|
11
|
+
import filetype
|
|
12
|
+
import httpx
|
|
13
|
+
from botocore.exceptions import ClientError
|
|
14
|
+
from mypy_boto3_s3.client import S3Client
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
# Global variables for S3 configuration
|
|
19
|
+
_bucket: Optional[str] = None
|
|
20
|
+
_client: Optional[S3Client] = None
|
|
21
|
+
_prefix: Optional[str] = None
|
|
22
|
+
_cdn_url: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def init_s3(bucket: str, cdn_url: str, env: str) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Initialize S3 configuration.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
bucket: S3 bucket name
|
|
31
|
+
cdn_url: CDN URL for the S3 bucket
|
|
32
|
+
env: Environment name for the prefix
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ValueError: If bucket or cdn_url is empty
|
|
36
|
+
"""
|
|
37
|
+
global _bucket, _client, _prefix, _cdn_url
|
|
38
|
+
|
|
39
|
+
if not bucket:
|
|
40
|
+
raise ValueError("S3 bucket name cannot be empty")
|
|
41
|
+
if not cdn_url:
|
|
42
|
+
raise ValueError("S3 CDN URL cannot be empty")
|
|
43
|
+
|
|
44
|
+
_bucket = bucket
|
|
45
|
+
_cdn_url = cdn_url
|
|
46
|
+
_prefix = f"{env}/intentkit/"
|
|
47
|
+
_client = boto3.client("s3")
|
|
48
|
+
|
|
49
|
+
logger.info(f"S3 initialized with bucket: {bucket}, prefix: {_prefix}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
async def store_image(url: str, key: str) -> str:
|
|
53
|
+
"""
|
|
54
|
+
Store an image from a URL to S3 asynchronously.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
url: Source URL of the image
|
|
58
|
+
key: Key to store the image under (without prefix)
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
str: The CDN URL of the stored image, or the original URL if S3 is not initialized
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ClientError: If the upload fails
|
|
65
|
+
httpx.HTTPError: If the download fails
|
|
66
|
+
"""
|
|
67
|
+
if not _client or not _bucket or not _prefix or not _cdn_url:
|
|
68
|
+
# If S3 is not initialized, log and return the original URL
|
|
69
|
+
logger.info("S3 not initialized. Returning original URL.")
|
|
70
|
+
return url
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
# Download the image from the URL asynchronously
|
|
74
|
+
async with httpx.AsyncClient() as client:
|
|
75
|
+
response = await client.get(url, follow_redirects=True)
|
|
76
|
+
response.raise_for_status()
|
|
77
|
+
|
|
78
|
+
# Prepare the S3 key with prefix
|
|
79
|
+
prefixed_key = f"{_prefix}{key}"
|
|
80
|
+
|
|
81
|
+
# Use BytesIO to create a file-like object that implements read
|
|
82
|
+
file_obj = BytesIO(response.content)
|
|
83
|
+
|
|
84
|
+
# Determine the correct content type
|
|
85
|
+
content_type = response.headers.get("Content-Type", "")
|
|
86
|
+
if content_type == "binary/octet-stream" or not content_type:
|
|
87
|
+
# Try to detect the image type from the content
|
|
88
|
+
kind = filetype.guess(response.content)
|
|
89
|
+
if kind and kind.mime.startswith("image/"):
|
|
90
|
+
content_type = kind.mime
|
|
91
|
+
else:
|
|
92
|
+
# Default to JPEG if detection fails
|
|
93
|
+
content_type = "image/jpeg"
|
|
94
|
+
|
|
95
|
+
# Upload to S3
|
|
96
|
+
_client.upload_fileobj(
|
|
97
|
+
file_obj,
|
|
98
|
+
_bucket,
|
|
99
|
+
prefixed_key,
|
|
100
|
+
ExtraArgs={"ContentType": content_type, "ContentDisposition": "inline"},
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Return the CDN URL
|
|
104
|
+
cdn_url = f"{_cdn_url}/{prefixed_key}"
|
|
105
|
+
logger.info(f"Image uploaded successfully to {cdn_url}")
|
|
106
|
+
return cdn_url
|
|
107
|
+
|
|
108
|
+
except httpx.HTTPError as e:
|
|
109
|
+
logger.error(f"Failed to download image from URL {url}: {str(e)}")
|
|
110
|
+
raise
|
|
111
|
+
except ClientError as e:
|
|
112
|
+
logger.error(f"Failed to upload image to S3: {str(e)}")
|
|
113
|
+
raise
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
async def store_image_bytes(
|
|
117
|
+
image_bytes: bytes, key: str, content_type: Optional[str] = None
|
|
118
|
+
) -> str:
|
|
119
|
+
"""
|
|
120
|
+
Store raw image bytes to S3.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
image_bytes: Raw bytes of the image to store
|
|
124
|
+
key: Key to store the image under (without prefix)
|
|
125
|
+
content_type: Content type of the image. If None, will attempt to detect it.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
str: The CDN URL of the stored image, or an empty string if S3 is not initialized
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
ClientError: If the upload fails
|
|
132
|
+
ValueError: If S3 is not initialized or image_bytes is empty
|
|
133
|
+
"""
|
|
134
|
+
if not _client or not _bucket or not _prefix or not _cdn_url:
|
|
135
|
+
# If S3 is not initialized, log and return empty string
|
|
136
|
+
logger.info("S3 not initialized. Cannot store image bytes.")
|
|
137
|
+
return ""
|
|
138
|
+
|
|
139
|
+
if not image_bytes:
|
|
140
|
+
raise ValueError("Image bytes cannot be empty")
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
# Prepare the S3 key with prefix
|
|
144
|
+
prefixed_key = f"{_prefix}{key}"
|
|
145
|
+
|
|
146
|
+
# Use BytesIO to create a file-like object that implements read
|
|
147
|
+
file_obj = BytesIO(image_bytes)
|
|
148
|
+
|
|
149
|
+
# Determine the correct content type if not provided
|
|
150
|
+
if not content_type:
|
|
151
|
+
# Try to detect the image type from the content
|
|
152
|
+
kind = filetype.guess(image_bytes)
|
|
153
|
+
if kind and kind.mime.startswith("image/"):
|
|
154
|
+
content_type = kind.mime
|
|
155
|
+
else:
|
|
156
|
+
# Default to JPEG if detection fails
|
|
157
|
+
content_type = "image/jpeg"
|
|
158
|
+
|
|
159
|
+
logger.info("uploading image to s3")
|
|
160
|
+
# Upload to S3
|
|
161
|
+
_client.upload_fileobj(
|
|
162
|
+
file_obj,
|
|
163
|
+
_bucket,
|
|
164
|
+
prefixed_key,
|
|
165
|
+
ExtraArgs={"ContentType": content_type, "ContentDisposition": "inline"},
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Return the CDN URL
|
|
169
|
+
cdn_url = f"{_cdn_url}/{prefixed_key}"
|
|
170
|
+
logger.info(f"image is uploaded to {cdn_url}")
|
|
171
|
+
return cdn_url
|
|
172
|
+
|
|
173
|
+
except ClientError as e:
|
|
174
|
+
logger.error(f"Failed to upload image bytes to S3: {str(e)}")
|
|
175
|
+
raise
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class FileType(str, Enum):
|
|
179
|
+
IMAGE = "image"
|
|
180
|
+
VIDEO = "video"
|
|
181
|
+
AUDIO = "audio"
|
|
182
|
+
PDF = "pdf"
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
async def store_file_bytes(
|
|
186
|
+
file_bytes: bytes,
|
|
187
|
+
key: str,
|
|
188
|
+
file_type: FileType,
|
|
189
|
+
size_limit_bytes: Optional[int] = None,
|
|
190
|
+
) -> str:
|
|
191
|
+
"""
|
|
192
|
+
Store raw file bytes (image, video, sound, pdf) to S3.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
file_bytes: Raw bytes of the file to store
|
|
196
|
+
key: Key to store the file under (without prefix)
|
|
197
|
+
file_type: Type of the file (image, video, sound, pdf)
|
|
198
|
+
size_limit_bytes: Optional size limit in bytes
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
str: The CDN URL of the stored file, or an empty string if S3 is not initialized
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
ClientError: If the upload fails
|
|
205
|
+
ValueError: If S3 is not initialized, file_bytes is empty, or file exceeds size limit
|
|
206
|
+
"""
|
|
207
|
+
if not _client or not _bucket or not _prefix or not _cdn_url:
|
|
208
|
+
logger.info("S3 not initialized. Cannot store file bytes.")
|
|
209
|
+
return ""
|
|
210
|
+
if not file_bytes:
|
|
211
|
+
raise ValueError("File bytes cannot be empty")
|
|
212
|
+
|
|
213
|
+
if size_limit_bytes is not None and len(file_bytes) > size_limit_bytes:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
f"File size exceeds the allowed limit of {size_limit_bytes} bytes"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
# Prepare the S3 key with prefix
|
|
220
|
+
prefixed_key = f"{_prefix}{key}"
|
|
221
|
+
|
|
222
|
+
# Use BytesIO to create a file-like object that implements read
|
|
223
|
+
file_obj = BytesIO(file_bytes)
|
|
224
|
+
|
|
225
|
+
# Determine content type based on file_type
|
|
226
|
+
content_type = ""
|
|
227
|
+
if file_type == FileType.IMAGE:
|
|
228
|
+
kind = filetype.guess(file_bytes)
|
|
229
|
+
if kind and kind.mime.startswith("image/"):
|
|
230
|
+
content_type = kind.mime
|
|
231
|
+
else:
|
|
232
|
+
content_type = "image/jpeg"
|
|
233
|
+
elif file_type == FileType.VIDEO:
|
|
234
|
+
kind = filetype.guess(file_bytes)
|
|
235
|
+
if kind and kind.mime.startswith("video/"):
|
|
236
|
+
content_type = kind.mime
|
|
237
|
+
else:
|
|
238
|
+
content_type = "video/mp4"
|
|
239
|
+
elif file_type == FileType.AUDIO:
|
|
240
|
+
kind = filetype.guess(file_bytes)
|
|
241
|
+
if kind and kind.mime.startswith("audio/"):
|
|
242
|
+
content_type = kind.mime
|
|
243
|
+
else:
|
|
244
|
+
content_type = "audio/mpeg"
|
|
245
|
+
elif file_type == FileType.PDF:
|
|
246
|
+
content_type = "application/pdf"
|
|
247
|
+
else:
|
|
248
|
+
raise ValueError(f"Unsupported file type: {file_type}")
|
|
249
|
+
|
|
250
|
+
logger.info(f"Uploading {file_type} to S3 with content type {content_type}")
|
|
251
|
+
|
|
252
|
+
# Upload to S3
|
|
253
|
+
_client.upload_fileobj(
|
|
254
|
+
file_obj,
|
|
255
|
+
_bucket,
|
|
256
|
+
prefixed_key,
|
|
257
|
+
ExtraArgs={"ContentType": content_type, "ContentDisposition": "inline"},
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Return the CDN URL
|
|
261
|
+
cdn_url = f"{_cdn_url}/{prefixed_key}"
|
|
262
|
+
logger.info(f"{file_type} uploaded successfully to {cdn_url}")
|
|
263
|
+
return cdn_url
|
|
264
|
+
|
|
265
|
+
except ClientError as e:
|
|
266
|
+
logger.error(f"Failed to upload {file_type} bytes to S3: {str(e)}")
|
|
267
|
+
raise
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Slack notification module for sending messages to Slack channels.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from slack_sdk import WebClient
|
|
9
|
+
from slack_sdk.errors import SlackApiError
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
# Global variables for Slack configuration
|
|
14
|
+
_slack_token: Optional[str] = None
|
|
15
|
+
_slack_channel: Optional[str] = None
|
|
16
|
+
_slack_client: Optional[WebClient] = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def init_slack(token: str, channel: str) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initialize Slack configuration.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
token: Slack bot token
|
|
25
|
+
channel: Default Slack channel ID or name
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
ValueError: If token or channel is empty
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
global _slack_token, _slack_channel, _slack_client
|
|
32
|
+
_slack_token = token
|
|
33
|
+
_slack_channel = channel
|
|
34
|
+
_slack_client = WebClient(token=token)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def send_slack_message(
|
|
38
|
+
message: str,
|
|
39
|
+
blocks: Optional[list] = None,
|
|
40
|
+
attachments: Optional[list] = None,
|
|
41
|
+
thread_ts: Optional[str] = None,
|
|
42
|
+
channel: Optional[str] = None,
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Send a message to a Slack channel.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
message: The message text to send
|
|
49
|
+
blocks: Optional blocks for rich message formatting (see Slack Block Kit)
|
|
50
|
+
attachments: Optional attachments for the message
|
|
51
|
+
thread_ts: Optional thread timestamp to reply to a thread
|
|
52
|
+
channel: Optional channel override. If not provided, uses the default channel
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
RuntimeError: If slack is not initialized
|
|
56
|
+
SlackApiError: If the message fails to send
|
|
57
|
+
"""
|
|
58
|
+
if not _slack_client or not _slack_channel:
|
|
59
|
+
# Write the input message to the log and return
|
|
60
|
+
logger.info("Slack not initialized")
|
|
61
|
+
logger.info(message)
|
|
62
|
+
if blocks:
|
|
63
|
+
logger.info(blocks)
|
|
64
|
+
if attachments:
|
|
65
|
+
logger.info(attachments)
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
response = _slack_client.chat_postMessage(
|
|
70
|
+
channel=channel or _slack_channel,
|
|
71
|
+
text=message,
|
|
72
|
+
blocks=blocks,
|
|
73
|
+
attachments=attachments,
|
|
74
|
+
thread_ts=thread_ts,
|
|
75
|
+
)
|
|
76
|
+
logger.info(f"Message sent successfully to channel {channel or _slack_channel}")
|
|
77
|
+
return response
|
|
78
|
+
except SlackApiError as e:
|
|
79
|
+
logger.error(f"Failed to send Slack message: {str(e)}")
|
intentkit/utils/tx.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from web3 import Web3
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EvmContractWrapper:
|
|
6
|
+
def __init__(self, rpc_url: str, abi: list[dict], tx_data: str):
|
|
7
|
+
w3 = Web3(Web3.HTTPProvider(rpc_url))
|
|
8
|
+
contract = w3.eth.contract(abi=abi)
|
|
9
|
+
|
|
10
|
+
self.evm_tx = EvmTx(**tx_data)
|
|
11
|
+
self.fn, self.fn_args = contract.decode_function_input(self.evm_tx.data)
|
|
12
|
+
|
|
13
|
+
for i, arg in self.fn_args.items():
|
|
14
|
+
if isinstance(arg, bytes):
|
|
15
|
+
self.fn_args[i] = arg.hex() # Convert bytes to hexadecimal string
|
|
16
|
+
elif isinstance(arg, list) and all(isinstance(item, bytes) for item in arg):
|
|
17
|
+
self.fn_args[i] = [
|
|
18
|
+
item.hex() for item in arg
|
|
19
|
+
] # Convert list of bytes to list of hex strings
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def fn_and_args(self):
|
|
23
|
+
return self.fn, self.fn_args
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def dst_addr(self):
|
|
27
|
+
return self.evm_tx.to
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class EvmTx(BaseModel):
|
|
31
|
+
data: str = Field(None, description="Data of the transaction.")
|
|
32
|
+
to: str = Field(None, description="Address of the receiver of the transaction.")
|
|
33
|
+
from_: str = Field(None, description="Address of the sender of the transaction.")
|
|
34
|
+
value: str = Field(None, description="Amount of token to send.")
|
|
35
|
+
gas: int | None = Field(None, description="Gas amount.")
|
|
36
|
+
gasPrice: int | None = Field(None, description="Gas Price.")
|
|
37
|
+
nonce: int | None = Field(None, description="Nonce of transaction.")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: intentkit
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Intent-based AI Agent Platform - Core Package
|
|
5
5
|
Project-URL: Homepage, https://github.com/crestal-network/intentkit
|
|
6
6
|
Project-URL: Repository, https://github.com/crestal-network/intentkit
|