intentkit 0.6.13.dev2__py3-none-any.whl → 0.8.17__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.

Files changed (385) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/agent.py +4 -5
  3. intentkit/abstracts/engine.py +5 -5
  4. intentkit/abstracts/graph.py +14 -7
  5. intentkit/abstracts/skill.py +6 -144
  6. intentkit/abstracts/twitter.py +4 -5
  7. intentkit/clients/__init__.py +5 -2
  8. intentkit/clients/cdp.py +101 -141
  9. intentkit/clients/twitter.py +83 -62
  10. intentkit/clients/web3.py +29 -0
  11. intentkit/config/config.py +8 -5
  12. intentkit/core/agent.py +472 -195
  13. intentkit/core/asset.py +253 -0
  14. intentkit/core/chat.py +51 -0
  15. intentkit/core/client.py +1 -1
  16. intentkit/core/credit.py +460 -130
  17. intentkit/core/engine.py +262 -233
  18. intentkit/core/node.py +15 -16
  19. intentkit/core/prompt.py +62 -28
  20. intentkit/core/scheduler.py +92 -0
  21. intentkit/core/statistics.py +168 -0
  22. intentkit/models/agent.py +1096 -949
  23. intentkit/models/agent_data.py +68 -38
  24. intentkit/models/agent_public.json +98 -0
  25. intentkit/models/agent_schema.json +54 -439
  26. intentkit/models/app_setting.py +96 -33
  27. intentkit/models/chat.py +74 -27
  28. intentkit/models/conversation.py +8 -8
  29. intentkit/models/credit.py +362 -74
  30. intentkit/models/db.py +26 -8
  31. intentkit/models/db_mig.py +2 -2
  32. intentkit/models/llm.csv +28 -0
  33. intentkit/models/llm.py +185 -350
  34. intentkit/models/redis.py +6 -4
  35. intentkit/models/skill.py +186 -72
  36. intentkit/models/skills.csv +174 -0
  37. intentkit/models/user.py +82 -24
  38. intentkit/skills/acolyt/__init__.py +2 -9
  39. intentkit/skills/acolyt/ask.py +3 -4
  40. intentkit/skills/acolyt/base.py +4 -9
  41. intentkit/skills/acolyt/schema.json +4 -3
  42. intentkit/skills/aixbt/__init__.py +2 -13
  43. intentkit/skills/aixbt/base.py +1 -7
  44. intentkit/skills/aixbt/projects.py +14 -15
  45. intentkit/skills/aixbt/schema.json +4 -4
  46. intentkit/skills/allora/__init__.py +2 -9
  47. intentkit/skills/allora/base.py +4 -9
  48. intentkit/skills/allora/price.py +3 -4
  49. intentkit/skills/allora/schema.json +3 -2
  50. intentkit/skills/base.py +248 -85
  51. intentkit/skills/basename/__init__.py +51 -0
  52. intentkit/skills/basename/base.py +11 -0
  53. intentkit/skills/basename/basename.svg +11 -0
  54. intentkit/skills/basename/schema.json +58 -0
  55. intentkit/skills/carv/__init__.py +115 -121
  56. intentkit/skills/carv/base.py +184 -185
  57. intentkit/skills/carv/fetch_news.py +3 -3
  58. intentkit/skills/carv/onchain_query.py +4 -4
  59. intentkit/skills/carv/schema.json +134 -137
  60. intentkit/skills/carv/token_info_and_price.py +5 -5
  61. intentkit/skills/casino/README.md +254 -0
  62. intentkit/skills/casino/__init__.py +86 -0
  63. intentkit/skills/casino/base.py +17 -0
  64. intentkit/skills/casino/casino.png +0 -0
  65. intentkit/skills/casino/deck_draw.py +127 -0
  66. intentkit/skills/casino/deck_shuffle.py +118 -0
  67. intentkit/skills/casino/dice_roll.py +100 -0
  68. intentkit/skills/casino/schema.json +77 -0
  69. intentkit/skills/casino/utils.py +107 -0
  70. intentkit/skills/cdp/__init__.py +22 -84
  71. intentkit/skills/cdp/base.py +1 -7
  72. intentkit/skills/cdp/schema.json +11 -314
  73. intentkit/skills/chainlist/__init__.py +2 -7
  74. intentkit/skills/chainlist/base.py +1 -7
  75. intentkit/skills/chainlist/chain_lookup.py +18 -18
  76. intentkit/skills/chainlist/schema.json +3 -5
  77. intentkit/skills/common/__init__.py +2 -9
  78. intentkit/skills/common/base.py +1 -7
  79. intentkit/skills/common/current_time.py +1 -2
  80. intentkit/skills/common/schema.json +2 -2
  81. intentkit/skills/cookiefun/__init__.py +6 -9
  82. intentkit/skills/cookiefun/base.py +2 -7
  83. intentkit/skills/cookiefun/get_account_details.py +7 -7
  84. intentkit/skills/cookiefun/get_account_feed.py +19 -19
  85. intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
  86. intentkit/skills/cookiefun/get_sectors.py +3 -3
  87. intentkit/skills/cookiefun/schema.json +1 -3
  88. intentkit/skills/cookiefun/search_accounts.py +9 -9
  89. intentkit/skills/cryptocompare/__init__.py +7 -24
  90. intentkit/skills/cryptocompare/api.py +2 -3
  91. intentkit/skills/cryptocompare/base.py +11 -25
  92. intentkit/skills/cryptocompare/fetch_news.py +4 -5
  93. intentkit/skills/cryptocompare/fetch_price.py +6 -7
  94. intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
  95. intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
  96. intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
  97. intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
  98. intentkit/skills/cryptocompare/schema.json +3 -3
  99. intentkit/skills/cryptopanic/__init__.py +7 -10
  100. intentkit/skills/cryptopanic/base.py +51 -55
  101. intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
  102. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
  103. intentkit/skills/cryptopanic/schema.json +105 -103
  104. intentkit/skills/dapplooker/__init__.py +2 -9
  105. intentkit/skills/dapplooker/base.py +4 -9
  106. intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
  107. intentkit/skills/dapplooker/schema.json +3 -5
  108. intentkit/skills/defillama/__init__.py +24 -74
  109. intentkit/skills/defillama/api.py +6 -9
  110. intentkit/skills/defillama/base.py +11 -21
  111. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
  112. intentkit/skills/defillama/coins/fetch_block.py +6 -8
  113. intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
  114. intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
  115. intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
  116. intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
  117. intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
  118. intentkit/skills/defillama/config/chains.py +1 -3
  119. intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
  120. intentkit/skills/defillama/schema.json +5 -1
  121. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
  122. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
  123. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
  124. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
  125. intentkit/skills/defillama/tests/api_integration.test.py +1 -1
  126. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
  127. intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
  128. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
  129. intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
  130. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
  131. intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
  132. intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
  133. intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
  134. intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
  135. intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
  136. intentkit/skills/defillama/yields/fetch_pools.py +26 -30
  137. intentkit/skills/dexscreener/README.md +154 -0
  138. intentkit/skills/dexscreener/__init__.py +97 -93
  139. intentkit/skills/dexscreener/base.py +125 -133
  140. intentkit/skills/dexscreener/get_pair_info.py +158 -0
  141. intentkit/skills/dexscreener/get_token_pairs.py +165 -0
  142. intentkit/skills/dexscreener/get_tokens_info.py +212 -0
  143. intentkit/skills/dexscreener/model/search_token_response.py +80 -82
  144. intentkit/skills/dexscreener/schema.json +91 -48
  145. intentkit/skills/dexscreener/search_token.py +182 -321
  146. intentkit/skills/dexscreener/utils.py +420 -0
  147. intentkit/skills/dune_analytics/__init__.py +7 -9
  148. intentkit/skills/dune_analytics/base.py +48 -52
  149. intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
  150. intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
  151. intentkit/skills/dune_analytics/schema.json +104 -99
  152. intentkit/skills/elfa/__init__.py +5 -18
  153. intentkit/skills/elfa/base.py +10 -14
  154. intentkit/skills/elfa/mention.py +19 -21
  155. intentkit/skills/elfa/schema.json +3 -2
  156. intentkit/skills/elfa/stats.py +4 -4
  157. intentkit/skills/elfa/tokens.py +12 -12
  158. intentkit/skills/elfa/utils.py +26 -28
  159. intentkit/skills/enso/__init__.py +11 -31
  160. intentkit/skills/enso/base.py +50 -35
  161. intentkit/skills/enso/best_yield.py +16 -24
  162. intentkit/skills/enso/networks.py +6 -11
  163. intentkit/skills/enso/prices.py +11 -13
  164. intentkit/skills/enso/route.py +34 -38
  165. intentkit/skills/enso/schema.json +3 -2
  166. intentkit/skills/enso/tokens.py +29 -38
  167. intentkit/skills/enso/wallet.py +76 -191
  168. intentkit/skills/erc20/__init__.py +50 -0
  169. intentkit/skills/erc20/base.py +11 -0
  170. intentkit/skills/erc20/erc20.svg +5 -0
  171. intentkit/skills/erc20/schema.json +74 -0
  172. intentkit/skills/erc721/__init__.py +53 -0
  173. intentkit/skills/erc721/base.py +11 -0
  174. intentkit/skills/erc721/erc721.svg +5 -0
  175. intentkit/skills/erc721/schema.json +90 -0
  176. intentkit/skills/firecrawl/README.md +11 -5
  177. intentkit/skills/firecrawl/__init__.py +5 -18
  178. intentkit/skills/firecrawl/base.py +4 -11
  179. intentkit/skills/firecrawl/clear.py +4 -8
  180. intentkit/skills/firecrawl/crawl.py +19 -19
  181. intentkit/skills/firecrawl/query.py +4 -3
  182. intentkit/skills/firecrawl/schema.json +6 -8
  183. intentkit/skills/firecrawl/scrape.py +150 -40
  184. intentkit/skills/firecrawl/utils.py +50 -42
  185. intentkit/skills/github/__init__.py +2 -7
  186. intentkit/skills/github/base.py +1 -7
  187. intentkit/skills/github/github_search.py +1 -2
  188. intentkit/skills/github/schema.json +3 -4
  189. intentkit/skills/heurist/__init__.py +8 -27
  190. intentkit/skills/heurist/base.py +4 -9
  191. intentkit/skills/heurist/image_generation_animagine_xl.py +12 -13
  192. intentkit/skills/heurist/image_generation_arthemy_comics.py +12 -13
  193. intentkit/skills/heurist/image_generation_arthemy_real.py +12 -13
  194. intentkit/skills/heurist/image_generation_braindance.py +12 -13
  195. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +12 -13
  196. intentkit/skills/heurist/image_generation_flux_1_dev.py +12 -13
  197. intentkit/skills/heurist/image_generation_sdxl.py +12 -13
  198. intentkit/skills/heurist/schema.json +2 -2
  199. intentkit/skills/http/__init__.py +4 -15
  200. intentkit/skills/http/base.py +1 -7
  201. intentkit/skills/http/get.py +21 -16
  202. intentkit/skills/http/post.py +23 -18
  203. intentkit/skills/http/put.py +23 -18
  204. intentkit/skills/http/schema.json +4 -5
  205. intentkit/skills/lifi/__init__.py +8 -13
  206. intentkit/skills/lifi/base.py +1 -7
  207. intentkit/skills/lifi/schema.json +17 -8
  208. intentkit/skills/lifi/token_execute.py +36 -30
  209. intentkit/skills/lifi/token_quote.py +8 -10
  210. intentkit/skills/lifi/utils.py +104 -51
  211. intentkit/skills/moralis/__init__.py +6 -10
  212. intentkit/skills/moralis/api.py +6 -7
  213. intentkit/skills/moralis/base.py +5 -10
  214. intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
  215. intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
  216. intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
  217. intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
  218. intentkit/skills/moralis/schema.json +7 -2
  219. intentkit/skills/morpho/__init__.py +52 -0
  220. intentkit/skills/morpho/base.py +11 -0
  221. intentkit/skills/morpho/morpho.svg +12 -0
  222. intentkit/skills/morpho/schema.json +73 -0
  223. intentkit/skills/nation/__init__.py +4 -9
  224. intentkit/skills/nation/base.py +5 -10
  225. intentkit/skills/nation/nft_check.py +3 -4
  226. intentkit/skills/nation/schema.json +4 -3
  227. intentkit/skills/onchain.py +23 -0
  228. intentkit/skills/openai/__init__.py +17 -18
  229. intentkit/skills/openai/base.py +10 -14
  230. intentkit/skills/openai/dalle_image_generation.py +3 -8
  231. intentkit/skills/openai/gpt_avatar_generator.py +102 -0
  232. intentkit/skills/openai/gpt_image_generation.py +4 -8
  233. intentkit/skills/openai/gpt_image_mini_generator.py +91 -0
  234. intentkit/skills/openai/gpt_image_to_image.py +4 -8
  235. intentkit/skills/openai/image_to_text.py +3 -7
  236. intentkit/skills/openai/schema.json +34 -3
  237. intentkit/skills/portfolio/__init__.py +11 -35
  238. intentkit/skills/portfolio/base.py +33 -19
  239. intentkit/skills/portfolio/schema.json +3 -5
  240. intentkit/skills/portfolio/token_balances.py +21 -21
  241. intentkit/skills/portfolio/wallet_approvals.py +17 -18
  242. intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
  243. intentkit/skills/portfolio/wallet_history.py +31 -31
  244. intentkit/skills/portfolio/wallet_net_worth.py +13 -13
  245. intentkit/skills/portfolio/wallet_nfts.py +19 -19
  246. intentkit/skills/portfolio/wallet_profitability.py +18 -18
  247. intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
  248. intentkit/skills/portfolio/wallet_stats.py +3 -3
  249. intentkit/skills/portfolio/wallet_swaps.py +19 -19
  250. intentkit/skills/pyth/__init__.py +50 -0
  251. intentkit/skills/pyth/base.py +11 -0
  252. intentkit/skills/pyth/pyth.svg +6 -0
  253. intentkit/skills/pyth/schema.json +75 -0
  254. intentkit/skills/skills.toml +40 -0
  255. intentkit/skills/slack/__init__.py +5 -17
  256. intentkit/skills/slack/base.py +3 -9
  257. intentkit/skills/slack/get_channel.py +8 -8
  258. intentkit/skills/slack/get_message.py +9 -9
  259. intentkit/skills/slack/schedule_message.py +5 -5
  260. intentkit/skills/slack/schema.json +2 -2
  261. intentkit/skills/slack/send_message.py +3 -5
  262. intentkit/skills/supabase/__init__.py +7 -23
  263. intentkit/skills/supabase/base.py +9 -13
  264. intentkit/skills/supabase/delete_data.py +5 -6
  265. intentkit/skills/supabase/fetch_data.py +13 -14
  266. intentkit/skills/supabase/insert_data.py +5 -6
  267. intentkit/skills/supabase/invoke_function.py +7 -8
  268. intentkit/skills/supabase/schema.json +2 -3
  269. intentkit/skills/supabase/update_data.py +7 -8
  270. intentkit/skills/supabase/upsert_data.py +5 -6
  271. intentkit/skills/superfluid/__init__.py +53 -0
  272. intentkit/skills/superfluid/base.py +11 -0
  273. intentkit/skills/superfluid/schema.json +89 -0
  274. intentkit/skills/superfluid/superfluid.svg +6 -0
  275. intentkit/skills/system/__init__.py +7 -24
  276. intentkit/skills/system/add_autonomous_task.py +10 -12
  277. intentkit/skills/system/delete_autonomous_task.py +2 -2
  278. intentkit/skills/system/edit_autonomous_task.py +14 -18
  279. intentkit/skills/system/list_autonomous_tasks.py +3 -5
  280. intentkit/skills/system/read_agent_api_key.py +6 -4
  281. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  282. intentkit/skills/system/schema.json +6 -8
  283. intentkit/skills/tavily/__init__.py +3 -12
  284. intentkit/skills/tavily/base.py +4 -9
  285. intentkit/skills/tavily/schema.json +3 -5
  286. intentkit/skills/tavily/tavily_extract.py +2 -4
  287. intentkit/skills/tavily/tavily_search.py +4 -6
  288. intentkit/skills/token/__init__.py +5 -10
  289. intentkit/skills/token/base.py +7 -11
  290. intentkit/skills/token/erc20_transfers.py +19 -19
  291. intentkit/skills/token/schema.json +3 -6
  292. intentkit/skills/token/token_analytics.py +3 -3
  293. intentkit/skills/token/token_price.py +13 -13
  294. intentkit/skills/token/token_search.py +9 -9
  295. intentkit/skills/twitter/__init__.py +11 -35
  296. intentkit/skills/twitter/base.py +23 -35
  297. intentkit/skills/twitter/follow_user.py +3 -7
  298. intentkit/skills/twitter/get_mentions.py +6 -13
  299. intentkit/skills/twitter/get_timeline.py +5 -13
  300. intentkit/skills/twitter/get_user_by_username.py +3 -7
  301. intentkit/skills/twitter/get_user_tweets.py +6 -14
  302. intentkit/skills/twitter/like_tweet.py +3 -7
  303. intentkit/skills/twitter/post_tweet.py +23 -12
  304. intentkit/skills/twitter/reply_tweet.py +21 -12
  305. intentkit/skills/twitter/retweet.py +3 -7
  306. intentkit/skills/twitter/schema.json +1 -0
  307. intentkit/skills/twitter/search_tweets.py +5 -13
  308. intentkit/skills/unrealspeech/__init__.py +2 -7
  309. intentkit/skills/unrealspeech/base.py +2 -8
  310. intentkit/skills/unrealspeech/schema.json +2 -5
  311. intentkit/skills/unrealspeech/text_to_speech.py +8 -8
  312. intentkit/skills/venice_audio/__init__.py +98 -106
  313. intentkit/skills/venice_audio/base.py +117 -121
  314. intentkit/skills/venice_audio/input.py +41 -41
  315. intentkit/skills/venice_audio/schema.json +151 -152
  316. intentkit/skills/venice_audio/venice_audio.py +38 -21
  317. intentkit/skills/venice_image/__init__.py +147 -154
  318. intentkit/skills/venice_image/api.py +138 -138
  319. intentkit/skills/venice_image/base.py +185 -192
  320. intentkit/skills/venice_image/config.py +33 -35
  321. intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
  322. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
  323. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
  324. intentkit/skills/venice_image/image_generation/image_generation_base.py +9 -9
  325. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
  326. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
  327. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
  328. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
  329. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
  330. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
  331. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
  332. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
  333. intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
  334. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
  335. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
  336. intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
  337. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
  338. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
  339. intentkit/skills/venice_image/schema.json +267 -267
  340. intentkit/skills/venice_image/utils.py +77 -78
  341. intentkit/skills/web_scraper/__init__.py +5 -18
  342. intentkit/skills/web_scraper/base.py +21 -7
  343. intentkit/skills/web_scraper/document_indexer.py +7 -6
  344. intentkit/skills/web_scraper/schema.json +2 -6
  345. intentkit/skills/web_scraper/scrape_and_index.py +15 -15
  346. intentkit/skills/web_scraper/utils.py +62 -63
  347. intentkit/skills/web_scraper/website_indexer.py +17 -19
  348. intentkit/skills/weth/__init__.py +49 -0
  349. intentkit/skills/weth/base.py +11 -0
  350. intentkit/skills/weth/schema.json +58 -0
  351. intentkit/skills/weth/weth.svg +6 -0
  352. intentkit/skills/wow/__init__.py +51 -0
  353. intentkit/skills/wow/base.py +11 -0
  354. intentkit/skills/wow/schema.json +89 -0
  355. intentkit/skills/wow/wow.svg +7 -0
  356. intentkit/skills/x402/__init__.py +61 -0
  357. intentkit/skills/x402/ask_agent.py +98 -0
  358. intentkit/skills/x402/base.py +99 -0
  359. intentkit/skills/x402/http_request.py +117 -0
  360. intentkit/skills/x402/schema.json +45 -0
  361. intentkit/skills/x402/x402.webp +0 -0
  362. intentkit/skills/xmtp/__init__.py +4 -15
  363. intentkit/skills/xmtp/base.py +61 -2
  364. intentkit/skills/xmtp/price.py +18 -13
  365. intentkit/skills/xmtp/schema.json +69 -71
  366. intentkit/skills/xmtp/swap.py +22 -25
  367. intentkit/skills/xmtp/transfer.py +71 -32
  368. intentkit/utils/chain.py +3 -3
  369. intentkit/utils/error.py +14 -1
  370. intentkit/utils/logging.py +2 -4
  371. intentkit/utils/s3.py +59 -7
  372. intentkit/utils/schema.py +100 -0
  373. intentkit/utils/slack_alert.py +7 -8
  374. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/METADATA +14 -16
  375. intentkit-0.8.17.dist-info/RECORD +466 -0
  376. intentkit/abstracts/exception.py +0 -9
  377. intentkit/core/skill.py +0 -200
  378. intentkit/models/generator.py +0 -347
  379. intentkit/skills/cdp/get_balance.py +0 -110
  380. intentkit/skills/cdp/swap.py +0 -121
  381. intentkit/skills/moralis/tests/__init__.py +0 -0
  382. intentkit/skills/moralis/tests/test_wallet.py +0 -511
  383. intentkit-0.6.13.dev2.dist-info/RECORD +0 -409
  384. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/WHEEL +0 -0
  385. {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/licenses/LICENSE +0 -0
@@ -1,133 +1,125 @@
1
- import json
2
- import logging
3
- from typing import Any, Dict, Optional, Tuple
4
-
5
- import httpx
6
- from pydantic import Field
7
-
8
- from intentkit.abstracts.skill import SkillStoreABC
9
- from intentkit.skills.base import IntentKitSkill
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
- DEXSCREENER_BASE_URL = "https://api.dexscreener.com"
14
-
15
- # Removed DexScreenerApiError as it won't be raised by _get anymore
16
-
17
- # ApiResult still represents (success_data, error_data)
18
- ApiResult = Tuple[Optional[Dict[str, Any]], Optional[Dict[str, Any]]]
19
-
20
-
21
- class DexScreenerBaseTool(IntentKitSkill):
22
- """
23
- Generic base class for tools interacting with the Dex Screener API.
24
- Handles shared logic like API calls and error reporting via return values.
25
- """
26
-
27
- skill_store: SkillStoreABC = Field(
28
- description="The skill store for persisting data and configs."
29
- )
30
- base_url: str = DEXSCREENER_BASE_URL
31
-
32
- @property
33
- def category(self) -> str:
34
- return "dexscreener"
35
-
36
- async def _get(
37
- self,
38
- path: str,
39
- params: Optional[Dict[str, Any]] = None,
40
- ) -> ApiResult:
41
- """
42
- Makes an asynchronous GET request to the DexScreener API.
43
-
44
- Args:
45
- path: The API endpoint path (e.g., "/dex/search").
46
- params: Optional dictionary of query parameters.
47
-
48
- Returns:
49
- A tuple (data, error_details):
50
- - (dict, None): On HTTP 2xx success with valid JSON response.
51
- - (None, dict): On any error (API error, connection error,
52
- JSON parsing error, unexpected error). The dict
53
- contains details including an 'error_type'.
54
- """
55
- if not path.startswith("/"):
56
- path = "/" + path
57
-
58
- url = f"{self.base_url}{path}"
59
- headers = {"Accept": "application/json"}
60
- method = "GET"
61
-
62
- logger.debug(f"Calling DexScreener API: {method} {url} with params: {params}")
63
- response = None # Define response outside try block for access in except
64
-
65
- try:
66
- async with httpx.AsyncClient() as client:
67
- response = await client.request(
68
- method, url, params=params, headers=headers
69
- )
70
-
71
- # Attempt to parse JSON response text
72
- try:
73
- response_data = response.json()
74
- except json.JSONDecodeError as json_err:
75
- logger.error(
76
- f"Failed to parse JSON response from {url}. Status: {response.status_code}. Response text: {response.text}",
77
- exc_info=True,
78
- )
79
- error_details = {
80
- "error": "Failed to parse DexScreener API response",
81
- "error_type": "parsing_error",
82
- "status_code": response.status_code,
83
- "details": response.text, # Raw text causing the error
84
- "original_exception": str(json_err),
85
- "url": url,
86
- }
87
- return None, error_details # Return parsing error
88
-
89
- # Check HTTP status *after* attempting JSON parse
90
- if response.is_success: # 2xx
91
- logger.debug(
92
- f"DexScreener API success response status: {response.status_code}"
93
- )
94
- return response_data, None # Success
95
- else: # 4xx/5xx
96
- logger.warning(
97
- f"DexScreener API returned error status: {response.status_code} - {response.text}"
98
- )
99
- error_details = {
100
- "error": "DexScreener API request failed",
101
- "error_type": "api_error",
102
- "status_code": response.status_code,
103
- "response_body": response_data, # Parsed error body if available
104
- "url": url,
105
- }
106
- return None, error_details # Return API error
107
-
108
- except httpx.RequestError as req_err:
109
- logger.error(
110
- f"Request error connecting to DexScreener API: {req_err}", exc_info=True
111
- )
112
- error_details = {
113
- "error": "Failed to connect to DexScreener API",
114
- "error_type": "connection_error",
115
- "details": str(req_err),
116
- "url": url,
117
- }
118
- return None, error_details # Return connection error
119
-
120
- except Exception as e:
121
- # Catch any other unexpected errors during the process
122
- logger.exception(
123
- f"An unexpected error occurred during DexScreener API GET call: {e}"
124
- )
125
- status_code = response.status_code if response else None
126
- error_details = {
127
- "error": "An unexpected error occurred during API call",
128
- "error_type": "unexpected_error",
129
- "status_code": status_code, # Include if available
130
- "details": str(e),
131
- "url": url,
132
- }
133
- return None, error_details # Return unexpected error
1
+ import json
2
+ import logging
3
+ from typing import Any
4
+
5
+ import httpx
6
+
7
+ from intentkit.skills.base import IntentKitSkill
8
+ from intentkit.skills.dexscreener.utils import DEXSCREENER_BASE_URL
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ # ApiResult still represents (success_data, error_data)
13
+ ApiResult = tuple[dict[str, Any] | None, dict[str, Any] | None]
14
+
15
+
16
+ class DexScreenerBaseTool(IntentKitSkill):
17
+ """
18
+ Generic base class for tools interacting with the Dex Screener API.
19
+ Handles shared logic like API calls and error reporting via return values.
20
+ """
21
+
22
+ base_url: str = DEXSCREENER_BASE_URL
23
+
24
+ @property
25
+ def category(self) -> str:
26
+ return "dexscreener"
27
+
28
+ async def _get(
29
+ self,
30
+ path: str,
31
+ params: dict[str, Any] | None = None,
32
+ ) -> ApiResult:
33
+ """
34
+ Makes an asynchronous GET request to the DexScreener API.
35
+
36
+ Args:
37
+ path: The API endpoint path (e.g., "/dex/search").
38
+ params: Optional dictionary of query parameters.
39
+
40
+ Returns:
41
+ A tuple (data, error_details):
42
+ - (dict, None): On HTTP 2xx success with valid JSON response.
43
+ - (None, dict): On any error (API error, connection error,
44
+ JSON parsing error, unexpected error). The dict
45
+ contains details including an 'error_type'.
46
+ """
47
+ if not path.startswith("/"):
48
+ path = "/" + path
49
+
50
+ url = f"{self.base_url}{path}"
51
+ headers = {"Accept": "application/json"}
52
+ method = "GET"
53
+
54
+ logger.debug(f"Calling DexScreener API: {method} {url} with params: {params}")
55
+ response = None # Define response outside try block for access in except
56
+
57
+ try:
58
+ async with httpx.AsyncClient() as client:
59
+ response = await client.request(
60
+ method, url, params=params, headers=headers
61
+ )
62
+
63
+ # Attempt to parse JSON response text
64
+ try:
65
+ response_data = response.json()
66
+ except json.JSONDecodeError as json_err:
67
+ logger.error(
68
+ f"Failed to parse JSON response from {url}. Status: {response.status_code}. Response text: {response.text}",
69
+ exc_info=True,
70
+ )
71
+ error_details = {
72
+ "error": "Failed to parse DexScreener API response",
73
+ "error_type": "parsing_error",
74
+ "status_code": response.status_code,
75
+ "details": response.text, # Raw text causing the error
76
+ "original_exception": str(json_err),
77
+ "url": url,
78
+ }
79
+ return None, error_details # Return parsing error
80
+
81
+ # Check HTTP status *after* attempting JSON parse
82
+ if response.is_success: # 2xx
83
+ logger.debug(
84
+ f"DexScreener API success response status: {response.status_code}"
85
+ )
86
+ return response_data, None # Success
87
+ else: # 4xx/5xx
88
+ logger.warning(
89
+ f"DexScreener API returned error status: {response.status_code} - {response.text}"
90
+ )
91
+ error_details = {
92
+ "error": "DexScreener API request failed",
93
+ "error_type": "api_error",
94
+ "status_code": response.status_code,
95
+ "response_body": response_data, # Parsed error body if available
96
+ "url": url,
97
+ }
98
+ return None, error_details # Return API error
99
+
100
+ except httpx.RequestError as req_err:
101
+ logger.error(
102
+ f"Request error connecting to DexScreener API: {req_err}", exc_info=True
103
+ )
104
+ error_details = {
105
+ "error": "Failed to connect to DexScreener API",
106
+ "error_type": "connection_error",
107
+ "details": str(req_err),
108
+ "url": url,
109
+ }
110
+ return None, error_details # Return connection error
111
+
112
+ except Exception as e:
113
+ # Catch any other unexpected errors during the process
114
+ logger.exception(
115
+ f"An unexpected error occurred during DexScreener API GET call: {e}"
116
+ )
117
+ status_code = response.status_code if response else None
118
+ error_details = {
119
+ "error": "An unexpected error occurred during API call",
120
+ "error_type": "unexpected_error",
121
+ "status_code": status_code, # Include if available
122
+ "details": str(e),
123
+ "url": url,
124
+ }
125
+ return None, error_details # Return unexpected error
@@ -0,0 +1,158 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+ from intentkit.skills.dexscreener.base import DexScreenerBaseTool
7
+ from intentkit.skills.dexscreener.model.search_token_response import PairModel
8
+ from intentkit.skills.dexscreener.utils import (
9
+ API_ENDPOINTS,
10
+ RATE_LIMITS,
11
+ create_error_response,
12
+ format_success_response,
13
+ truncate_large_fields,
14
+ )
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class GetPairInfoInput(BaseModel):
20
+ """Input schema for the DexScreener get_pair_info tool."""
21
+
22
+ chain_id: str = Field(
23
+ description="The blockchain chain ID (e.g., 'ethereum', 'solana', 'bsc', 'polygon', 'arbitrum', 'base', 'avalanche')"
24
+ )
25
+ pair_address: str = Field(
26
+ description="The trading pair contract address (e.g., '0x1234...abcd' for Ethereum-based chains)"
27
+ )
28
+
29
+
30
+ class GetPairInfo(DexScreenerBaseTool):
31
+ """
32
+ Tool to get detailed information about a specific trading pair on DexScreener.
33
+ """
34
+
35
+ name: str = "dexscreener_get_pair_info"
36
+ description: str = (
37
+ "Retrieves detailed information about a specific trading pair using chain ID and pair address. "
38
+ "Returns comprehensive data including current price, volume, liquidity, price changes, "
39
+ "market cap, FDV, transaction counts, and social links. "
40
+ "Use this tool when you have a specific pair address and need detailed trading metrics."
41
+ )
42
+ args_schema: type[BaseModel] = GetPairInfoInput
43
+
44
+ async def _arun(
45
+ self,
46
+ chain_id: str,
47
+ pair_address: str,
48
+ **kwargs: Any,
49
+ ) -> str:
50
+ """Implementation to get specific pair information."""
51
+
52
+ # Apply rate limiting
53
+ await self.global_rate_limit_by_skill(
54
+ limit=RATE_LIMITS["pairs"],
55
+ seconds=60,
56
+ )
57
+
58
+ logger.info(
59
+ f"Executing DexScreener get_pair_info tool with chain_id: '{chain_id}', "
60
+ f"pair_address: '{pair_address}'"
61
+ )
62
+
63
+ try:
64
+ # Construct API path
65
+ api_path = f"{API_ENDPOINTS['pairs']}/{chain_id}/{pair_address}"
66
+
67
+ data, error_details = await self._get(path=api_path)
68
+
69
+ if error_details:
70
+ return await self._handle_error_response(error_details)
71
+
72
+ if not data:
73
+ logger.error(f"No data returned for pair {pair_address} on {chain_id}")
74
+ return create_error_response(
75
+ error_type="empty_success",
76
+ message="API call returned empty success response.",
77
+ additional_data={
78
+ "chain_id": chain_id,
79
+ "pair_address": pair_address,
80
+ },
81
+ )
82
+
83
+ # The API returns a single pair object, not wrapped in a pairs array
84
+ if not isinstance(data, dict):
85
+ return create_error_response(
86
+ error_type="format_error",
87
+ message="Unexpected response format - expected object",
88
+ additional_data={
89
+ "chain_id": chain_id,
90
+ "pair_address": pair_address,
91
+ },
92
+ )
93
+
94
+ try:
95
+ # Validate the response using our existing PairModel
96
+ pair_data = PairModel.model_validate(data)
97
+ logger.info(
98
+ f"Successfully retrieved pair info for {pair_address} on {chain_id}"
99
+ )
100
+
101
+ return format_success_response(
102
+ {
103
+ "pair": pair_data.model_dump(),
104
+ "chain_id": chain_id,
105
+ "pair_address": pair_address,
106
+ }
107
+ )
108
+
109
+ except Exception as validation_error:
110
+ logger.error(
111
+ f"Failed to validate pair response for {pair_address} on {chain_id}: {validation_error}",
112
+ exc_info=True,
113
+ )
114
+ # Return raw data if validation fails
115
+ return format_success_response(
116
+ {
117
+ "pair": data,
118
+ "chain_id": chain_id,
119
+ "pair_address": pair_address,
120
+ "validation_warning": "Response structure may have changed",
121
+ }
122
+ )
123
+
124
+ except Exception as e:
125
+ return await self._handle_unexpected_runtime_error(
126
+ e, f"{chain_id}/{pair_address}"
127
+ )
128
+
129
+ async def _handle_error_response(self, error_details: dict) -> str:
130
+ """Formats error details (from _get) into a JSON string."""
131
+ if error_details.get("error_type") in [
132
+ "connection_error",
133
+ "parsing_error",
134
+ "unexpected_error",
135
+ ]:
136
+ logger.error(
137
+ f"DexScreener get_pair_info tool encountered an error: {error_details}"
138
+ )
139
+ else: # api_error
140
+ logger.warning(f"DexScreener API returned an error: {error_details}")
141
+
142
+ # Truncate potentially large fields before returning to user/LLM
143
+ truncated_details = truncate_large_fields(error_details)
144
+ return format_success_response(truncated_details)
145
+
146
+ async def _handle_unexpected_runtime_error(
147
+ self, e: Exception, query_info: str
148
+ ) -> str:
149
+ """Formats unexpected runtime exception details into a JSON string."""
150
+ logger.exception(
151
+ f"An unexpected runtime error occurred in get_pair_info tool _arun method for {query_info}: {e}"
152
+ )
153
+ return create_error_response(
154
+ error_type="runtime_error",
155
+ message="An unexpected internal error occurred processing the pair info request",
156
+ details=str(e),
157
+ additional_data={"query_info": query_info},
158
+ )
@@ -0,0 +1,165 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, Field, ValidationError
5
+
6
+ from intentkit.skills.dexscreener.base import DexScreenerBaseTool
7
+ from intentkit.skills.dexscreener.model.search_token_response import (
8
+ SearchTokenResponseModel,
9
+ )
10
+ from intentkit.skills.dexscreener.utils import (
11
+ API_ENDPOINTS,
12
+ RATE_LIMITS,
13
+ create_error_response,
14
+ create_no_results_response,
15
+ format_success_response,
16
+ get_liquidity_value,
17
+ handle_validation_error,
18
+ truncate_large_fields,
19
+ )
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class GetTokenPairsInput(BaseModel):
25
+ """Input schema for the DexScreener get_token_pairs tool."""
26
+
27
+ chain_id: str = Field(
28
+ description="The blockchain chain ID (e.g., 'ethereum', 'solana', 'bsc', 'polygon', 'arbitrum', 'base', 'avalanche')"
29
+ )
30
+ token_address: str = Field(
31
+ description="The token contract address (e.g., '0x1234...abcd' for Ethereum-based chains)"
32
+ )
33
+
34
+
35
+ class GetTokenPairs(DexScreenerBaseTool):
36
+ """
37
+ Tool to get all trading pairs for a specific token on DexScreener.
38
+ """
39
+
40
+ name: str = "dexscreener_get_token_pairs"
41
+ description: str = (
42
+ "Finds all trading pairs for a specific token using chain ID and token address. "
43
+ "Returns a list of all pools/pairs where this token is traded, including pair addresses, "
44
+ "DEX information, liquidity, volume, and pricing data for each pair. "
45
+ "Use this tool to analyze all available trading venues and liquidity sources for a specific token."
46
+ )
47
+ args_schema: type[BaseModel] = GetTokenPairsInput
48
+
49
+ async def _arun(
50
+ self,
51
+ chain_id: str,
52
+ token_address: str,
53
+ **kwargs: Any,
54
+ ) -> str:
55
+ """Implementation to get all pairs for a specific token."""
56
+
57
+ # Apply rate limiting
58
+ await self.global_rate_limit_by_skill(
59
+ limit=RATE_LIMITS["token_pairs"],
60
+ seconds=60,
61
+ )
62
+
63
+ logger.info(
64
+ f"Executing DexScreener get_token_pairs tool with chain_id: '{chain_id}', "
65
+ f"token_address: '{token_address}'"
66
+ )
67
+
68
+ try:
69
+ # Construct API path
70
+ api_path = f"{API_ENDPOINTS['token_pairs']}/{chain_id}/{token_address}"
71
+
72
+ data, error_details = await self._get(path=api_path)
73
+
74
+ if error_details:
75
+ return await self._handle_error_response(error_details)
76
+
77
+ if not data:
78
+ logger.error(
79
+ f"No data returned for token {token_address} on {chain_id}"
80
+ )
81
+ return create_error_response(
82
+ error_type="empty_success",
83
+ message="API call returned empty success response.",
84
+ additional_data={
85
+ "chain_id": chain_id,
86
+ "token_address": token_address,
87
+ },
88
+ )
89
+
90
+ try:
91
+ # Validate response using SearchTokenResponseModel since API returns similar structure
92
+ result = SearchTokenResponseModel.model_validate(data)
93
+ except ValidationError as e:
94
+ return handle_validation_error(
95
+ e, f"{chain_id}/{token_address}", len(str(data))
96
+ )
97
+
98
+ if not result.pairs:
99
+ return create_no_results_response(
100
+ f"{chain_id}/{token_address}",
101
+ reason="no trading pairs found for this token",
102
+ )
103
+
104
+ pairs_list = [p for p in result.pairs if p is not None]
105
+
106
+ if not pairs_list:
107
+ return create_no_results_response(
108
+ f"{chain_id}/{token_address}",
109
+ reason="all pairs were null or invalid",
110
+ )
111
+
112
+ # Sort pairs by liquidity (highest first) for better UX
113
+ try:
114
+ pairs_list.sort(key=get_liquidity_value, reverse=True)
115
+ except Exception as sort_err:
116
+ logger.warning(f"Failed to sort pairs by liquidity: {sort_err}")
117
+
118
+ logger.info(
119
+ f"Found {len(pairs_list)} pairs for token {token_address} on {chain_id}"
120
+ )
121
+
122
+ return format_success_response(
123
+ {
124
+ "pairs": [p.model_dump() for p in pairs_list],
125
+ "chain_id": chain_id,
126
+ "token_address": token_address,
127
+ "total_pairs": len(pairs_list),
128
+ }
129
+ )
130
+
131
+ except Exception as e:
132
+ return await self._handle_unexpected_runtime_error(
133
+ e, f"{chain_id}/{token_address}"
134
+ )
135
+
136
+ async def _handle_error_response(self, error_details: dict) -> str:
137
+ """Formats error details (from _get) into a JSON string."""
138
+ if error_details.get("error_type") in [
139
+ "connection_error",
140
+ "parsing_error",
141
+ "unexpected_error",
142
+ ]:
143
+ logger.error(
144
+ f"DexScreener get_token_pairs tool encountered an error: {error_details}"
145
+ )
146
+ else: # api_error
147
+ logger.warning(f"DexScreener API returned an error: {error_details}")
148
+
149
+ # Truncate potentially large fields before returning to user/LLM
150
+ truncated_details = truncate_large_fields(error_details)
151
+ return format_success_response(truncated_details)
152
+
153
+ async def _handle_unexpected_runtime_error(
154
+ self, e: Exception, query_info: str
155
+ ) -> str:
156
+ """Formats unexpected runtime exception details into a JSON string."""
157
+ logger.exception(
158
+ f"An unexpected runtime error occurred in get_token_pairs tool _arun method for {query_info}: {e}"
159
+ )
160
+ return create_error_response(
161
+ error_type="runtime_error",
162
+ message="An unexpected internal error occurred processing the token pairs request",
163
+ details=str(e),
164
+ additional_data={"query_info": query_info},
165
+ )