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,168 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "CryptoCompare",
|
|
5
|
+
"description": "Integration with CryptoCompare API providing cryptocurrency market data, price information, and crypto news with rate limiting capabilities",
|
|
6
|
+
"x-icon": "https://ai.service.crestal.dev/skills/cryptocompare/cryptocompare.png",
|
|
7
|
+
"x-tags": [
|
|
8
|
+
"Blockchain",
|
|
9
|
+
"Finance"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"enabled": {
|
|
13
|
+
"type": "boolean",
|
|
14
|
+
"title": "Enabled",
|
|
15
|
+
"description": "Whether this skill is enabled",
|
|
16
|
+
"default": false
|
|
17
|
+
},
|
|
18
|
+
"states": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"fetch_news": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"title": "Fetch News",
|
|
24
|
+
"enum": [
|
|
25
|
+
"disabled",
|
|
26
|
+
"public",
|
|
27
|
+
"private"
|
|
28
|
+
],
|
|
29
|
+
"x-enum-title": [
|
|
30
|
+
"Disabled",
|
|
31
|
+
"Agent Owner + All Users",
|
|
32
|
+
"Agent Owner Only"
|
|
33
|
+
],
|
|
34
|
+
"description": "This tool fetches the latest cryptocurrency news articles for a specific token.\nYou can optionally specify a timestamp to get historical news, otherwise it uses the current time.\nReturns articles in English with details like title, body, source, and publish time.",
|
|
35
|
+
"default": "disabled"
|
|
36
|
+
},
|
|
37
|
+
"fetch_price": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"title": "Fetch Price",
|
|
40
|
+
"enum": [
|
|
41
|
+
"disabled",
|
|
42
|
+
"public",
|
|
43
|
+
"private"
|
|
44
|
+
],
|
|
45
|
+
"x-enum-title": [
|
|
46
|
+
"Disabled",
|
|
47
|
+
"Agent Owner + All Users",
|
|
48
|
+
"Agent Owner Only"
|
|
49
|
+
],
|
|
50
|
+
"description": "Provides real-time cryptocurrency pricing with multi-exchange aggregation and historical comparisons",
|
|
51
|
+
"default": "disabled"
|
|
52
|
+
},
|
|
53
|
+
"fetch_trading_signals": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"title": "Fetch Trading Signals",
|
|
56
|
+
"enum": [
|
|
57
|
+
"disabled",
|
|
58
|
+
"public",
|
|
59
|
+
"private"
|
|
60
|
+
],
|
|
61
|
+
"x-enum-title": [
|
|
62
|
+
"Disabled",
|
|
63
|
+
"Agent Owner + All Users",
|
|
64
|
+
"Agent Owner Only"
|
|
65
|
+
],
|
|
66
|
+
"description": "Generates technical analysis signals using indicators like RSI, MACD, and Bollinger Bands",
|
|
67
|
+
"default": "disabled"
|
|
68
|
+
},
|
|
69
|
+
"fetch_top_market_cap": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"title": "Fetch Top Market Cap",
|
|
72
|
+
"enum": [
|
|
73
|
+
"disabled",
|
|
74
|
+
"public",
|
|
75
|
+
"private"
|
|
76
|
+
],
|
|
77
|
+
"x-enum-title": [
|
|
78
|
+
"Disabled",
|
|
79
|
+
"Agent Owner + All Users",
|
|
80
|
+
"Agent Owner Only"
|
|
81
|
+
],
|
|
82
|
+
"description": "Tracks top cryptocurrencies by market capitalization with sector breakdowns",
|
|
83
|
+
"default": "disabled"
|
|
84
|
+
},
|
|
85
|
+
"fetch_top_exchanges": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"title": "Fetch Top Exchanges",
|
|
88
|
+
"enum": [
|
|
89
|
+
"disabled",
|
|
90
|
+
"public",
|
|
91
|
+
"private"
|
|
92
|
+
],
|
|
93
|
+
"x-enum-title": [
|
|
94
|
+
"Disabled",
|
|
95
|
+
"Agent Owner + All Users",
|
|
96
|
+
"Agent Owner Only"
|
|
97
|
+
],
|
|
98
|
+
"description": "Ranks cryptocurrency exchanges by liquidity and trading volume with market pair analysis",
|
|
99
|
+
"default": "disabled"
|
|
100
|
+
},
|
|
101
|
+
"fetch_top_volume": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"title": "Fetch Top Volume",
|
|
104
|
+
"enum": [
|
|
105
|
+
"disabled",
|
|
106
|
+
"public",
|
|
107
|
+
"private"
|
|
108
|
+
],
|
|
109
|
+
"x-enum-title": [
|
|
110
|
+
"Disabled",
|
|
111
|
+
"Agent Owner + All Users",
|
|
112
|
+
"Agent Owner Only"
|
|
113
|
+
],
|
|
114
|
+
"description": "Analyzes 24h trading volume trends across exchanges and currency pairs",
|
|
115
|
+
"default": "disabled"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"description": "States for each CryptoCompare skill (disabled, public, or private)"
|
|
119
|
+
},
|
|
120
|
+
"api_key_provider": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"title": "API Key Provider",
|
|
123
|
+
"description": "Provider of the API key for AIXBT API service",
|
|
124
|
+
"enum": [
|
|
125
|
+
"agent_owner"
|
|
126
|
+
],
|
|
127
|
+
"x-enum-title": [
|
|
128
|
+
"Owner Provided"
|
|
129
|
+
],
|
|
130
|
+
"default": "agent_owner"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"required": [
|
|
134
|
+
"states",
|
|
135
|
+
"enabled"
|
|
136
|
+
],
|
|
137
|
+
"if": {
|
|
138
|
+
"properties": {
|
|
139
|
+
"api_key_provider": {
|
|
140
|
+
"const": "agent_owner"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"then": {
|
|
145
|
+
"properties": {
|
|
146
|
+
"api_key": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"title": "CryptoCompare API Key",
|
|
149
|
+
"x-link": "[Get your API key](https://www.cryptocompare.com/cryptopian/api-keys)",
|
|
150
|
+
"x-sensitive": true,
|
|
151
|
+
"description": "CryptoCompare API key for authentication"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"if": {
|
|
155
|
+
"properties": {
|
|
156
|
+
"enabled": {
|
|
157
|
+
"const": true
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"then": {
|
|
162
|
+
"required": [
|
|
163
|
+
"api_key"
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"additionalProperties": true
|
|
168
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""CryptoPanic skill module for IntentKit.
|
|
2
|
+
|
|
3
|
+
Loads and initializes skills for fetching crypto news and providing market insights using CryptoPanic API.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Dict, List, Optional, TypedDict
|
|
8
|
+
|
|
9
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
10
|
+
from intentkit.skills.base import SkillConfig, SkillState
|
|
11
|
+
|
|
12
|
+
from .base import CryptopanicBaseTool
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
# Cache for skill instances
|
|
17
|
+
_skill_cache: Dict[str, CryptopanicBaseTool] = {}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SkillStates(TypedDict):
|
|
21
|
+
"""Type definition for CryptoPanic skill states."""
|
|
22
|
+
|
|
23
|
+
fetch_crypto_news: SkillState
|
|
24
|
+
fetch_crypto_sentiment: SkillState
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Config(SkillConfig):
|
|
28
|
+
"""Configuration schema for CryptoPanic skills."""
|
|
29
|
+
|
|
30
|
+
states: SkillStates
|
|
31
|
+
api_key: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def get_skills(
|
|
35
|
+
config: Config,
|
|
36
|
+
is_private: bool,
|
|
37
|
+
store: SkillStoreABC,
|
|
38
|
+
**kwargs,
|
|
39
|
+
) -> List[CryptopanicBaseTool]:
|
|
40
|
+
"""Load CryptoPanic skills based on configuration.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
config: Skill configuration with states and API key.
|
|
44
|
+
is_private: Whether the context is private (affects skill visibility).
|
|
45
|
+
store: Skill store for accessing other skills.
|
|
46
|
+
**kwargs: Additional keyword arguments.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
List of loaded CryptoPanic skill instances.
|
|
50
|
+
"""
|
|
51
|
+
logger.info("Loading CryptoPanic skills")
|
|
52
|
+
available_skills = []
|
|
53
|
+
|
|
54
|
+
for skill_name, state in config["states"].items():
|
|
55
|
+
logger.debug("Checking skill: %s, state: %s", skill_name, state)
|
|
56
|
+
if state == "disabled":
|
|
57
|
+
continue
|
|
58
|
+
if state == "public" or (state == "private" and is_private):
|
|
59
|
+
available_skills.append(skill_name)
|
|
60
|
+
|
|
61
|
+
loaded_skills = []
|
|
62
|
+
for name in available_skills:
|
|
63
|
+
skill = get_cryptopanic_skill(name, store)
|
|
64
|
+
if skill:
|
|
65
|
+
logger.info("Successfully loaded skill: %s", name)
|
|
66
|
+
loaded_skills.append(skill)
|
|
67
|
+
else:
|
|
68
|
+
logger.warning("Failed to load skill: %s", name)
|
|
69
|
+
|
|
70
|
+
return loaded_skills
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_cryptopanic_skill(
|
|
74
|
+
name: str,
|
|
75
|
+
store: SkillStoreABC,
|
|
76
|
+
) -> Optional[CryptopanicBaseTool]:
|
|
77
|
+
"""Retrieve a CryptoPanic skill instance by name.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
name: Name of the skill (e.g., 'fetch_crypto_news', 'fetch_crypto_sentiment').
|
|
81
|
+
store: Skill store for accessing other skills.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
CryptoPanic skill instance or None if not found or import fails.
|
|
85
|
+
"""
|
|
86
|
+
if name in _skill_cache:
|
|
87
|
+
logger.debug("Retrieved cached skill: %s", name)
|
|
88
|
+
return _skill_cache[name]
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
if name == "fetch_crypto_news":
|
|
92
|
+
from .fetch_crypto_news import FetchCryptoNews
|
|
93
|
+
|
|
94
|
+
_skill_cache[name] = FetchCryptoNews(skill_store=store)
|
|
95
|
+
elif name == "fetch_crypto_sentiment":
|
|
96
|
+
from .fetch_crypto_sentiment import FetchCryptoSentiment
|
|
97
|
+
|
|
98
|
+
_skill_cache[name] = FetchCryptoSentiment(skill_store=store)
|
|
99
|
+
else:
|
|
100
|
+
logger.warning("Unknown CryptoPanic skill: %s", name)
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
logger.debug("Cached new skill instance: %s", name)
|
|
104
|
+
return _skill_cache[name]
|
|
105
|
+
|
|
106
|
+
except ImportError as e:
|
|
107
|
+
logger.error("Failed to import CryptoPanic skill %s: %s", name, e)
|
|
108
|
+
return None
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Base module for CryptoPanic skills.
|
|
2
|
+
|
|
3
|
+
Defines the base class and shared utilities for CryptoPanic skills.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Type
|
|
7
|
+
|
|
8
|
+
from langchain.tools.base import ToolException
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
|
|
11
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
12
|
+
from intentkit.skills.base import IntentKitSkill, SkillContext
|
|
13
|
+
|
|
14
|
+
base_url = "https://cryptopanic.com/api/v1/posts/"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CryptopanicBaseTool(IntentKitSkill):
|
|
18
|
+
"""Base class for CryptoPanic skills.
|
|
19
|
+
|
|
20
|
+
Provides common functionality for interacting with the CryptoPanic API,
|
|
21
|
+
including API key retrieval and skill store access.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
name: str = Field(description="Tool name")
|
|
25
|
+
description: str = Field(description="Tool description")
|
|
26
|
+
args_schema: Type[BaseModel]
|
|
27
|
+
skill_store: SkillStoreABC = Field(description="Skill store for data persistence")
|
|
28
|
+
|
|
29
|
+
def get_api_key(self, context: SkillContext) -> str:
|
|
30
|
+
"""Retrieve the CryptoPanic API key from context.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
context: Skill context containing configuration.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
API key string.
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
ToolException: If the API key is not found.
|
|
40
|
+
"""
|
|
41
|
+
api_key = context.config.get("api_key")
|
|
42
|
+
if not api_key:
|
|
43
|
+
raise ToolException(
|
|
44
|
+
"CryptoPanic API key not found in context.config['api_key']"
|
|
45
|
+
)
|
|
46
|
+
return api_key
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def category(self) -> str:
|
|
50
|
+
"""Category of the skill."""
|
|
51
|
+
return "cryptopanic"
|
|
Binary file
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Skill to fetch the latest crypto market news from CryptoPanic API.
|
|
2
|
+
|
|
3
|
+
Fetches all news posts for BTC or ETH, sorted by publication date (newest first).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import List, Type
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
from langchain_core.runnables import RunnableConfig
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
13
|
+
from intentkit.skills.cryptopanic.base import CryptopanicBaseTool
|
|
14
|
+
|
|
15
|
+
SUPPORTED_CURRENCIES = ["BTC", "ETH"]
|
|
16
|
+
BASE_URL = "https://cryptopanic.com/api/v1/posts/"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CryptopanicNewsInput(BaseModel):
|
|
20
|
+
"""Input schema for fetching crypto news."""
|
|
21
|
+
|
|
22
|
+
query: str = Field(description="Query to specify currency (e.g., 'btc news')")
|
|
23
|
+
currency: str = Field(
|
|
24
|
+
default="BTC", description="Currency to fetch news for (BTC or ETH)"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class NewsItem(BaseModel):
|
|
29
|
+
"""Data model for a single news item."""
|
|
30
|
+
|
|
31
|
+
title: str = Field(description="News headline")
|
|
32
|
+
published_at: str = Field(description="Publication timestamp")
|
|
33
|
+
source: str = Field(description="News source domain")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CryptopanicNewsOutput(BaseModel):
|
|
37
|
+
"""Output schema for fetching crypto news."""
|
|
38
|
+
|
|
39
|
+
currency: str = Field(description="Currency news was fetched for")
|
|
40
|
+
news_items: List[NewsItem] = Field(description="List of news items")
|
|
41
|
+
summary: str = Field(description="Summary of fetched news")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FetchCryptoNews(CryptopanicBaseTool):
|
|
45
|
+
"""Skill to fetch the latest crypto market news from CryptoPanic API."""
|
|
46
|
+
|
|
47
|
+
name: str = "fetch_crypto_news"
|
|
48
|
+
description: str = (
|
|
49
|
+
"Fetches all crypto market news posts from CryptoPanic for BTC or ETH, "
|
|
50
|
+
"sorted by publication date (newest first). Defaults to BTC."
|
|
51
|
+
)
|
|
52
|
+
args_schema: Type[BaseModel] = CryptopanicNewsInput
|
|
53
|
+
skill_store: SkillStoreABC = Field(description="Skill store for data persistence")
|
|
54
|
+
|
|
55
|
+
async def fetch_news(
|
|
56
|
+
self,
|
|
57
|
+
currency: str,
|
|
58
|
+
api_key: str,
|
|
59
|
+
) -> List[NewsItem]:
|
|
60
|
+
"""Fetch the latest news for a specific currency from CryptoPanic API.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
currency: Currency to fetch news for (BTC or ETH).
|
|
64
|
+
api_key: CryptoPanic API key.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
List of NewsItem objects, sorted by publication date (newest first).
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
ToolException: If the API request fails or data is invalid.
|
|
71
|
+
"""
|
|
72
|
+
from langchain.tools.base import ToolException
|
|
73
|
+
|
|
74
|
+
if currency not in SUPPORTED_CURRENCIES:
|
|
75
|
+
raise ToolException(f"Unsupported currency: {currency}")
|
|
76
|
+
|
|
77
|
+
params = {
|
|
78
|
+
"auth_token": api_key,
|
|
79
|
+
"public": "true",
|
|
80
|
+
"currencies": currency.upper(),
|
|
81
|
+
"sort": "-published_at", # Sort by newest first
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async with httpx.AsyncClient() as client:
|
|
85
|
+
try:
|
|
86
|
+
response = await client.get(BASE_URL, params=params, timeout=10)
|
|
87
|
+
response.raise_for_status()
|
|
88
|
+
data = response.json().get("results", [])
|
|
89
|
+
return [
|
|
90
|
+
NewsItem(
|
|
91
|
+
title=post["title"],
|
|
92
|
+
published_at=post.get("published_at", "Unknown"),
|
|
93
|
+
source=post.get("source", {}).get("domain", "CryptoPanic"),
|
|
94
|
+
)
|
|
95
|
+
for post in data
|
|
96
|
+
]
|
|
97
|
+
except (httpx.RequestError, httpx.HTTPStatusError) as e:
|
|
98
|
+
raise ToolException(f"Error fetching news from CryptoPanic: {e}")
|
|
99
|
+
|
|
100
|
+
async def _arun(
|
|
101
|
+
self,
|
|
102
|
+
query: str = "",
|
|
103
|
+
currency: str = "BTC",
|
|
104
|
+
config: RunnableConfig = None,
|
|
105
|
+
**kwargs,
|
|
106
|
+
) -> CryptopanicNewsOutput:
|
|
107
|
+
"""Fetch the latest crypto news asynchronously.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
query: Query to specify currency (e.g., 'btc news').
|
|
111
|
+
currency: Currency to fetch news for (defaults to BTC).
|
|
112
|
+
config: Runnable configuration.
|
|
113
|
+
**kwargs: Additional keyword arguments.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
CryptopanicNewsOutput with news items and summary.
|
|
117
|
+
|
|
118
|
+
Raises:
|
|
119
|
+
ToolException: If the API key is missing or request fails.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
currency = currency.upper() if currency else "BTC"
|
|
123
|
+
if currency not in SUPPORTED_CURRENCIES:
|
|
124
|
+
currency = "BTC"
|
|
125
|
+
|
|
126
|
+
context = self.context_from_config(config)
|
|
127
|
+
api_key = self.get_api_key(context)
|
|
128
|
+
|
|
129
|
+
news_items = await self.fetch_news(currency, api_key)
|
|
130
|
+
|
|
131
|
+
# Deduplicate news items by title
|
|
132
|
+
seen_titles = set()
|
|
133
|
+
unique_news_items = [
|
|
134
|
+
item
|
|
135
|
+
for item in news_items
|
|
136
|
+
if item.title not in seen_titles and not seen_titles.add(item.title)
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
total_items = len(unique_news_items)
|
|
140
|
+
summary = (
|
|
141
|
+
f"Fetched {total_items} unique news posts for {currency}, sorted by recency."
|
|
142
|
+
if unique_news_items
|
|
143
|
+
else f"No news posts found for {currency}."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
return CryptopanicNewsOutput(
|
|
147
|
+
currency=currency,
|
|
148
|
+
news_items=unique_news_items,
|
|
149
|
+
summary=summary,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def _run(self, question: str):
|
|
153
|
+
raise NotImplementedError("Use _arun for async execution")
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Skill to provide AI-driven insights on crypto market conditions using CryptoPanic news."""
|
|
2
|
+
|
|
3
|
+
from typing import ClassVar, List, Type
|
|
4
|
+
|
|
5
|
+
from langchain_core.runnables import RunnableConfig
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
9
|
+
from intentkit.skills.cryptopanic.base import CryptopanicBaseTool
|
|
10
|
+
|
|
11
|
+
SUPPORTED_CURRENCIES = ["BTC", "ETH"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CryptopanicSentimentInput(BaseModel):
|
|
15
|
+
"""Input schema for fetching crypto market insights."""
|
|
16
|
+
|
|
17
|
+
currency: str = Field(default="BTC", description="Currency to analyze (BTC or ETH)")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CryptopanicSentimentOutput(BaseModel):
|
|
21
|
+
"""Output schema for crypto market insights."""
|
|
22
|
+
|
|
23
|
+
currency: str = Field(description="Currency analyzed")
|
|
24
|
+
total_posts: int = Field(description="Number of news items analyzed")
|
|
25
|
+
headlines: list[str] = Field(description="List of news headlines")
|
|
26
|
+
prompt: str = Field(description="Formatted prompt for LLM insights")
|
|
27
|
+
summary: str = Field(description="Summary of analysis process")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CryptopanicNewsOutput(BaseModel):
|
|
31
|
+
"""Output schema for fetching crypto news (used internally)."""
|
|
32
|
+
|
|
33
|
+
currency: str = Field(description="Currency news was fetched for")
|
|
34
|
+
news_items: List[BaseModel] = Field(description="List of news items")
|
|
35
|
+
summary: str = Field(description="Summary of fetched news")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class FetchCryptoSentiment(CryptopanicBaseTool):
|
|
39
|
+
"""Skill to provide AI-driven insights on crypto market conditions using CryptoPanic news."""
|
|
40
|
+
|
|
41
|
+
name: str = "fetch_crypto_sentiment"
|
|
42
|
+
description: str = (
|
|
43
|
+
"Provides AI-driven insights on market conditions for BTC or ETH, including trends, "
|
|
44
|
+
"opportunities, risks, and outlook, based on news fetched from fetch_crypto_news "
|
|
45
|
+
"with all posts sorted by recency. Triggered by 'sentiment' or 'market state' queries. "
|
|
46
|
+
"Defaults to BTC."
|
|
47
|
+
)
|
|
48
|
+
args_schema: Type[BaseModel] = CryptopanicSentimentInput
|
|
49
|
+
skill_store: SkillStoreABC = Field(description="Skill store for data persistence")
|
|
50
|
+
|
|
51
|
+
INSIGHTS_PROMPT: ClassVar[str] = """
|
|
52
|
+
CryptoPanic Headlines for {currency}:
|
|
53
|
+
{headlines}
|
|
54
|
+
|
|
55
|
+
Total Posts: {total_posts}
|
|
56
|
+
Currency: {currency}
|
|
57
|
+
|
|
58
|
+
Based on these headlines, provide AI-driven insights into the market conditions for {currency}.
|
|
59
|
+
Summarize key trends (e.g., price movements, adoption, network developments) inferred from the news.
|
|
60
|
+
Identify significant opportunities (e.g., growth potential) and risks (e.g., negative sentiment, competition).
|
|
61
|
+
Classify the overall market outlook as Bullish, Bearish and provide opinion on wether to buy, sell or hold.
|
|
62
|
+
Conclude with a short-term outlook for {currency}. Provide a concise, professional analysis without headings.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
async def _arun(
|
|
66
|
+
self,
|
|
67
|
+
currency: str = "BTC",
|
|
68
|
+
config: RunnableConfig = None,
|
|
69
|
+
**kwargs,
|
|
70
|
+
) -> CryptopanicSentimentOutput:
|
|
71
|
+
"""Generate AI-driven market insights asynchronously.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
currency: Currency to analyze (defaults to BTC).
|
|
75
|
+
config: Runnable configuration.
|
|
76
|
+
**kwargs: Additional keyword arguments.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
CryptopanicSentimentOutput with market insights.
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
ToolException: If news fetching fails.
|
|
83
|
+
"""
|
|
84
|
+
from langchain.tools.base import ToolException
|
|
85
|
+
|
|
86
|
+
from intentkit.skills.cryptopanic.fetch_crypto_news import (
|
|
87
|
+
FetchCryptoNews,
|
|
88
|
+
) # Import here to avoid circular import
|
|
89
|
+
|
|
90
|
+
currency = currency.upper() if currency else "BTC"
|
|
91
|
+
if currency not in SUPPORTED_CURRENCIES:
|
|
92
|
+
currency = "BTC"
|
|
93
|
+
|
|
94
|
+
# Instantiate FetchCryptoNews
|
|
95
|
+
news_skill = FetchCryptoNews(skill_store=self.skill_store)
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
news_output: CryptopanicNewsOutput = await news_skill._arun(
|
|
99
|
+
query=f"insights for {currency}",
|
|
100
|
+
currency=currency,
|
|
101
|
+
config=config,
|
|
102
|
+
)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
raise ToolException(f"Failed to fetch news for analysis: {e}")
|
|
105
|
+
|
|
106
|
+
news_items = news_output.news_items
|
|
107
|
+
total_posts = len(news_items)
|
|
108
|
+
|
|
109
|
+
if total_posts == 0:
|
|
110
|
+
headlines = ["No recent news available"]
|
|
111
|
+
summary = f"No news found for {currency} to analyze."
|
|
112
|
+
else:
|
|
113
|
+
headlines = [item.title for item in news_items[:5]] # Limit to 5
|
|
114
|
+
summary = f"Generated insights for {currency} based on {total_posts} news items sorted by recency."
|
|
115
|
+
|
|
116
|
+
# Format headlines as numbered list
|
|
117
|
+
formatted_headlines = "\n".join(
|
|
118
|
+
f"{i + 1}. {headline}" for i, headline in enumerate(headlines)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
prompt = self.INSIGHTS_PROMPT.format(
|
|
122
|
+
total_posts=total_posts,
|
|
123
|
+
currency=currency,
|
|
124
|
+
headlines=formatted_headlines,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return CryptopanicSentimentOutput(
|
|
128
|
+
currency=currency,
|
|
129
|
+
total_posts=total_posts,
|
|
130
|
+
headlines=headlines,
|
|
131
|
+
prompt=prompt,
|
|
132
|
+
summary=summary,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def _run(self, question: str):
|
|
136
|
+
raise NotImplementedError("Use _arun for async execution")
|