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
intentkit/skills/base.py CHANGED
@@ -1,23 +1,38 @@
1
- import asyncio
2
1
  import logging
3
- from typing import Any, Callable, Dict, Literal, NotRequired, Optional, TypedDict, Union
2
+ from collections.abc import Callable, Sequence
3
+ from typing import (
4
+ Any,
5
+ Literal,
6
+ NotRequired,
7
+ TypedDict,
8
+ )
4
9
 
5
- from langchain_core.runnables import RunnableConfig
6
- from langchain_core.tools import BaseTool
10
+ from coinbase_agentkit import (
11
+ Action,
12
+ AgentKit,
13
+ AgentKitConfig,
14
+ CdpEvmWalletProvider,
15
+ )
16
+ from langchain_core.tools import BaseTool, StructuredTool
7
17
  from langchain_core.tools.base import ToolException
8
18
  from langgraph.runtime import get_runtime
9
19
  from pydantic import (
10
- BaseModel,
11
20
  ValidationError,
12
21
  )
13
22
  from pydantic.v1 import ValidationError as ValidationErrorV1
14
23
  from redis.exceptions import RedisError
15
24
 
16
- from intentkit.abstracts.exception import RateLimitExceeded
17
25
  from intentkit.abstracts.graph import AgentContext
18
- from intentkit.abstracts.skill import SkillStoreABC
26
+ from intentkit.clients import get_wallet_provider
19
27
  from intentkit.models.agent import Agent
20
28
  from intentkit.models.redis import get_redis
29
+ from intentkit.models.skill import (
30
+ AgentSkillData,
31
+ AgentSkillDataCreate,
32
+ ChatSkillData,
33
+ ChatSkillDataCreate,
34
+ )
35
+ from intentkit.utils.error import IntentKitAPIError, RateLimitExceeded
21
36
 
22
37
  SkillState = Literal["disabled", "public", "private"]
23
38
  SkillOwnerState = Literal["disabled", "private"]
@@ -28,39 +43,9 @@ class SkillConfig(TypedDict):
28
43
  """Abstract base class for skill configuration."""
29
44
 
30
45
  enabled: bool
31
- states: Dict[str, SkillState | SkillOwnerState]
46
+ states: dict[str, SkillState | SkillOwnerState]
32
47
  api_key_provider: NotRequired[APIKeyProviderValue]
33
- __extra__: NotRequired[Dict[str, Any]]
34
-
35
-
36
- class SkillContext(BaseModel):
37
- skill_category: str
38
- agent_id: str
39
- user_id: Optional[str] = None
40
- chat_id: Optional[str] = None
41
- app_id: Optional[str] = None
42
- entrypoint: Literal["web", "twitter", "telegram", "trigger", "api"]
43
- is_private: bool
44
- payer: Optional[str] = None
45
- _agent: Optional[Agent] = None
46
-
47
- @property
48
- def agent(self) -> Agent:
49
- if self._agent is None:
50
- self._agent = asyncio.run(Agent.get(self.agent_id))
51
- return self._agent
52
-
53
- @property
54
- def config(self) -> Dict[str, Any]:
55
- agent = self.agent
56
- config = None
57
- if agent.skills:
58
- config = agent.skills.get(self.skill_category)
59
- if not config:
60
- raise ValueError(
61
- f"Skill {self.skill_category} not found in agent {self.agent_id}"
62
- )
63
- return config
48
+ __extra__: NotRequired[dict[str, Any]]
64
49
 
65
50
 
66
51
  class IntentKitSkill(BaseTool):
@@ -68,17 +53,16 @@ class IntentKitSkill(BaseTool):
68
53
  Will have predefined abilities.
69
54
  """
70
55
 
71
- skill_store: SkillStoreABC
72
56
  # overwrite the value of BaseTool
73
- handle_tool_error: Optional[Union[bool, str, Callable[[ToolException], str]]] = (
57
+ handle_tool_error: bool | str | Callable[[ToolException], str] | None = (
74
58
  lambda e: f"tool error: {e}"
75
59
  )
76
60
  """Handle the content of the ToolException thrown."""
77
61
 
78
62
  # overwrite the value of BaseTool
79
- handle_validation_error: Optional[
80
- Union[bool, str, Callable[[Union[ValidationError, ValidationErrorV1]], str]]
81
- ] = lambda e: f"validation error: {e}"
63
+ handle_validation_error: (
64
+ bool | str | Callable[[ValidationError | ValidationErrorV1], str] | None
65
+ ) = lambda e: f"validation error: {e}"
82
66
  """Handle the content of the ValidationError thrown."""
83
67
 
84
68
  # Logger for the class
@@ -89,15 +73,12 @@ class IntentKitSkill(BaseTool):
89
73
  """Get the category of the skill."""
90
74
  raise NotImplementedError
91
75
 
92
- async def user_rate_limit(
93
- self, user_id: str, limit: int, minutes: int, key: str
94
- ) -> None:
76
+ async def user_rate_limit(self, limit: int, seconds: int, key: str) -> None:
95
77
  """Check if a user has exceeded the rate limit for this skill.
96
78
 
97
79
  Args:
98
- user_id: The ID of the user to check
99
80
  limit: Maximum number of requests allowed
100
- minutes: Time window in minutes
81
+ seconds: Time window in seconds
101
82
  key: The key to use for rate limiting (e.g., skill name or category)
102
83
 
103
84
  Raises:
@@ -106,25 +87,48 @@ class IntentKitSkill(BaseTool):
106
87
  Returns:
107
88
  None: Always returns None if no exception is raised
108
89
  """
109
- if not user_id:
110
- return None # No rate limiting for users without ID
90
+ try:
91
+ context = self.get_context()
92
+ except ValueError:
93
+ self.logger.info(
94
+ "AgentContext not available, skipping rate limit for %s",
95
+ key,
96
+ )
97
+ return None
98
+
99
+ user_identifier = context.user_id or context.agent_id
100
+ if not user_identifier:
101
+ return None # No rate limiting when no identifier is available
102
+
103
+ try:
104
+ max_requests = int(limit)
105
+ window_seconds = int(seconds)
106
+ except (TypeError, ValueError):
107
+ self.logger.info(
108
+ "Invalid user rate limit parameters for %s: limit=%r, seconds=%r",
109
+ key,
110
+ limit,
111
+ seconds,
112
+ )
113
+ return None
114
+
115
+ if window_seconds <= 0 or max_requests <= 0:
116
+ return None
111
117
 
112
118
  try:
113
119
  redis = get_redis()
114
120
  # Create a unique key for this rate limit and user
115
- rate_limit_key = f"rate_limit:{key}:{user_id}"
121
+ rate_limit_key = f"rate_limit:{key}:{user_identifier}"
116
122
 
117
123
  # Get the current count
118
124
  count = await redis.incr(rate_limit_key)
119
125
 
120
126
  # Set expiration if this is the first request
121
127
  if count == 1:
122
- await redis.expire(
123
- rate_limit_key, minutes * 60
124
- ) # Convert minutes to seconds
128
+ await redis.expire(rate_limit_key, window_seconds)
125
129
 
126
130
  # Check if user has exceeded the limit
127
- if count > limit:
131
+ if count > max_requests:
128
132
  raise RateLimitExceeded(f"Rate limit exceeded for {key}")
129
133
 
130
134
  return None
@@ -140,62 +144,221 @@ class IntentKitSkill(BaseTool):
140
144
  )
141
145
  return None
142
146
 
143
- async def user_rate_limit_by_skill(
144
- self, user_id: str, limit: int, minutes: int
145
- ) -> None:
147
+ async def user_rate_limit_by_skill(self, limit: int, seconds: int) -> None:
146
148
  """Check if a user has exceeded the rate limit for this specific skill.
147
149
 
148
150
  This uses the skill name as the rate limit key.
149
151
 
150
152
  Args:
151
- user_id: The ID of the user to check
152
153
  limit: Maximum number of requests allowed
153
- minutes: Time window in minutes
154
+ seconds: Time window in seconds
154
155
 
155
156
  Raises:
156
157
  RateLimitExceeded: If the user has exceeded the rate limit
157
158
  """
158
- return await self.user_rate_limit(user_id, limit, minutes, self.name)
159
+ return await self.user_rate_limit(limit, seconds, self.name)
159
160
 
160
- async def user_rate_limit_by_category(
161
- self, user_id: str, limit: int, minutes: int
162
- ) -> None:
161
+ async def user_rate_limit_by_category(self, limit: int, seconds: int) -> None:
163
162
  """Check if a user has exceeded the rate limit for this skill category.
164
163
 
165
164
  This uses the skill category as the rate limit key, which means the limit
166
165
  is shared across all skills in the same category.
167
166
 
168
167
  Args:
169
- user_id: The ID of the user to check
170
168
  limit: Maximum number of requests allowed
171
- minutes: Time window in minutes
169
+ seconds: Time window in seconds
172
170
 
173
171
  Raises:
174
172
  RateLimitExceeded: If the user has exceeded the rate limit
175
173
  """
176
- return await self.user_rate_limit(user_id, limit, minutes, self.category)
174
+ return await self.user_rate_limit(limit, seconds, self.category)
175
+
176
+ async def global_rate_limit(self, limit: int, seconds: int, key: str) -> None:
177
+ """Check if a global rate limit has been exceeded for a given key.
178
+
179
+ Args:
180
+ limit: Maximum number of requests allowed
181
+ seconds: Time window in seconds
182
+ key: The key to use for rate limiting (e.g., skill name or category)
183
+
184
+ Raises:
185
+ RateLimitExceeded: If the global limit has been exceeded
186
+
187
+ Returns:
188
+ None: Always returns None if no exception is raised
189
+ """
190
+ try:
191
+ max_requests = int(limit)
192
+ window_seconds = int(seconds)
193
+ except (TypeError, ValueError):
194
+ self.logger.info(
195
+ "Invalid global rate limit parameters for %s: limit=%r, seconds=%r",
196
+ key,
197
+ limit,
198
+ seconds,
199
+ )
200
+ return None
201
+
202
+ if window_seconds <= 0 or max_requests <= 0:
203
+ return None
204
+
205
+ try:
206
+ redis = get_redis()
207
+ rate_limit_key = f"rate_limit:{key}"
208
+
209
+ count = await redis.incr(rate_limit_key)
210
+
211
+ if count == 1:
212
+ await redis.expire(rate_limit_key, window_seconds)
213
+
214
+ if count > max_requests:
215
+ raise RateLimitExceeded(f"Global rate limit exceeded for {key}")
216
+
217
+ return None
218
+
219
+ except RuntimeError:
220
+ self.logger.info(
221
+ "Redis not initialized, skipping global rate limit for %s",
222
+ key,
223
+ )
224
+ return None
225
+ except RedisError as e:
226
+ self.logger.info(
227
+ f"Redis error in global rate limiting: {e}, skipping rate limit for {key}"
228
+ )
229
+ return None
230
+
231
+ async def global_rate_limit_by_skill(self, limit: int, seconds: int) -> None:
232
+ """Apply a global rate limit scoped to this specific skill."""
233
+ return await self.global_rate_limit(limit, seconds, self.name)
234
+
235
+ async def global_rate_limit_by_category(self, limit: int, seconds: int) -> None:
236
+ """Apply a global rate limit scoped to this skill category."""
237
+ return await self.global_rate_limit(limit, seconds, self.category)
177
238
 
178
239
  def _run(self, *args: Any, **kwargs: Any) -> Any:
179
240
  raise NotImplementedError(
180
241
  "Use _arun instead, IntentKit only supports synchronous skill calls"
181
242
  )
182
243
 
183
- def context_from_config(self, runner_config: RunnableConfig) -> SkillContext:
184
- if "configurable" not in runner_config:
185
- raise ValueError("configurable not in runner_config")
186
- configurable = runner_config["configurable"]
187
- if not configurable:
188
- raise ValueError("configurable in runnable config is empty")
189
- return SkillContext(
190
- skill_category=self.category,
191
- agent_id=configurable.get("agent_id"),
192
- user_id=configurable.get("user_id"),
193
- app_id=configurable.get("app_id"),
194
- chat_id=configurable.get("chat_id"),
195
- entrypoint=configurable.get("entrypoint"),
196
- is_private=configurable.get("is_private"),
197
- )
198
-
199
- def get_context(self) -> AgentContext:
244
+ @staticmethod
245
+ def get_context() -> AgentContext:
200
246
  runtime = get_runtime(AgentContext)
247
+ if runtime.context is None or not isinstance(runtime.context, AgentContext):
248
+ raise ValueError("No AgentContext found")
201
249
  return runtime.context
250
+
251
+ async def get_agent_skill_data(
252
+ self,
253
+ key: str,
254
+ ) -> dict[str, Any] | None:
255
+ """Retrieve persisted data for this skill scoped to the active agent."""
256
+ return await self.get_agent_skill_data_raw(self.name, key)
257
+
258
+ async def get_agent_skill_data_raw(
259
+ self,
260
+ skill_name: str,
261
+ key: str,
262
+ ) -> dict[str, Any] | None:
263
+ """Retrieve persisted data for a specific skill scoped to the active agent."""
264
+ context = self.get_context()
265
+ return await AgentSkillData.get(context.agent_id, skill_name, key)
266
+
267
+ async def save_agent_skill_data(self, key: str, data: dict[str, Any]) -> None:
268
+ """Persist data for this skill scoped to the active agent."""
269
+ await self.save_agent_skill_data_raw(self.name, key, data)
270
+
271
+ async def save_agent_skill_data_raw(
272
+ self,
273
+ skill_name: str,
274
+ key: str,
275
+ data: dict[str, Any],
276
+ ) -> None:
277
+ """Persist data for a specific skill scoped to the active agent."""
278
+ context = self.get_context()
279
+ skill_data = AgentSkillDataCreate(
280
+ agent_id=context.agent_id,
281
+ skill=skill_name,
282
+ key=key,
283
+ data=data,
284
+ )
285
+ await skill_data.save()
286
+
287
+ async def delete_agent_skill_data(self, key: str) -> None:
288
+ """Remove persisted data for this skill scoped to the active agent."""
289
+ context = self.get_context()
290
+ await AgentSkillData.delete(context.agent_id, self.name, key)
291
+
292
+ async def get_thread_skill_data(
293
+ self,
294
+ key: str,
295
+ ) -> dict[str, Any] | None:
296
+ """Retrieve persisted data for this skill scoped to the active chat."""
297
+ context = self.get_context()
298
+ return await ChatSkillData.get(context.chat_id, self.name, key)
299
+
300
+ async def save_thread_skill_data(self, key: str, data: dict[str, Any]) -> None:
301
+ """Persist data for this skill scoped to the active chat."""
302
+ context = self.get_context()
303
+ skill_data = ChatSkillDataCreate(
304
+ chat_id=context.chat_id,
305
+ agent_id=context.agent_id,
306
+ skill=self.name,
307
+ key=key,
308
+ data=data,
309
+ )
310
+ await skill_data.save()
311
+
312
+
313
+ async def get_agentkit_actions(
314
+ agent_id: str,
315
+ provider_factories: Sequence[Callable[[], object]],
316
+ *,
317
+ agent: Agent | None = None,
318
+ ) -> list[Action]:
319
+ """Build an AgentKit instance and return its actions."""
320
+
321
+ if agent is None:
322
+ try:
323
+ context = IntentKitSkill.get_context()
324
+ except ValueError as exc: # pragma: no cover - defensive guard
325
+ raise IntentKitAPIError(
326
+ 500,
327
+ "AgentContextMissing",
328
+ "Agent context is required to initialize AgentKit actions.",
329
+ ) from exc
330
+ agent = context.agent
331
+
332
+ if agent.id != agent_id:
333
+ raise IntentKitAPIError(
334
+ 400,
335
+ "AgentMismatch",
336
+ "The requested agent does not match the active context agent.",
337
+ )
338
+
339
+ wallet_provider: CdpEvmWalletProvider = await get_wallet_provider(agent)
340
+
341
+ agent_kit = AgentKit(
342
+ AgentKitConfig(
343
+ wallet_provider=wallet_provider,
344
+ action_providers=[factory() for factory in provider_factories],
345
+ )
346
+ )
347
+ return agent_kit.get_actions()
348
+
349
+
350
+ def action_to_structured_tool(action: Action) -> StructuredTool:
351
+ """Convert an AgentKit action to a LangChain StructuredTool."""
352
+
353
+ def _tool_fn(**kwargs: object) -> str:
354
+ return action.invoke(kwargs)
355
+
356
+ tool = StructuredTool(
357
+ name=action.name,
358
+ description=action.description,
359
+ func=_tool_fn,
360
+ args_schema=action.args_schema,
361
+ )
362
+ tool.handle_tool_error = lambda e: f"tool error: {e}"
363
+ tool.handle_validation_error = lambda e: f"validation error: {e}"
364
+ return tool
@@ -0,0 +1,51 @@
1
+ """Basename AgentKit skills."""
2
+
3
+ from typing import TypedDict
4
+
5
+ from coinbase_agentkit import basename_action_provider
6
+
7
+ from intentkit.models.agent import Agent
8
+ from intentkit.skills.base import (
9
+ SkillConfig,
10
+ SkillState,
11
+ action_to_structured_tool,
12
+ get_agentkit_actions,
13
+ )
14
+ from intentkit.skills.basename.base import BasenameBaseTool
15
+
16
+
17
+ class SkillStates(TypedDict):
18
+ BasenameActionProvider_register_basename: SkillState
19
+
20
+
21
+ class Config(SkillConfig):
22
+ """Configuration for Basename skills."""
23
+
24
+ states: SkillStates
25
+
26
+
27
+ async def get_skills(
28
+ config: "Config",
29
+ is_private: bool,
30
+ agent_id: str,
31
+ agent: Agent | None = None,
32
+ **_,
33
+ ) -> list[BasenameBaseTool]:
34
+ """Get all Basename skills."""
35
+
36
+ available_skills: list[str] = []
37
+ for skill_name, state in config["states"].items():
38
+ if state == "disabled":
39
+ continue
40
+ if state == "public" or (state == "private" and is_private):
41
+ available_skills.append(skill_name)
42
+
43
+ actions = await get_agentkit_actions(
44
+ agent_id, [basename_action_provider], agent=agent
45
+ )
46
+ tools: list[BasenameBaseTool] = []
47
+ for skill in available_skills:
48
+ for action in actions:
49
+ if action.name.endswith(skill):
50
+ tools.append(action_to_structured_tool(action))
51
+ return tools
@@ -0,0 +1,11 @@
1
+ """Basename AgentKit skills base class."""
2
+
3
+ from intentkit.skills.cdp.base import CDPBaseTool
4
+
5
+
6
+ class BasenameBaseTool(CDPBaseTool):
7
+ """Base class for Basename tools."""
8
+
9
+ @property
10
+ def category(self) -> str:
11
+ return "basename"
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#4c7dff" />
5
+ <stop offset="100%" stop-color="#0b2f80" />
6
+ </linearGradient>
7
+ </defs>
8
+ <rect width="128" height="128" fill="url(#bg)" rx="16" />
9
+ <text x="50%" y="52%" font-family="Arial,Helvetica,sans-serif" font-size="60" fill="#ffffff" font-weight="700" text-anchor="middle">B</text>
10
+ <text x="50%" y="86%" font-family="Arial,Helvetica,sans-serif" font-size="20" fill="#dbe4ff" text-anchor="middle">Base</text>
11
+ </svg>
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "Basename",
5
+ "description": "Basename ENS-style name registration via Coinbase AgentKit",
6
+ "x-icon": "https://ai.service.crestal.dev/skills/basename/basename.svg",
7
+ "x-tags": [
8
+ "Crypto",
9
+ "Identity"
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
+ "BasenameActionProvider_register_basename": {
22
+ "type": "string",
23
+ "title": "Register Basename",
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": "State for BasenameActionProvider_register_basename",
35
+ "default": "disabled"
36
+ }
37
+ },
38
+ "description": "States for each Basename skill (disabled, public, or private)"
39
+ },
40
+ "api_key_provider": {
41
+ "type": "string",
42
+ "title": "API Key Provider",
43
+ "description": "Who provides the API key",
44
+ "enum": [
45
+ "platform"
46
+ ],
47
+ "x-enum-title": [
48
+ "Nation Hosted"
49
+ ],
50
+ "default": "platform"
51
+ }
52
+ },
53
+ "required": [
54
+ "states",
55
+ "enabled"
56
+ ],
57
+ "additionalProperties": true
58
+ }