intentkit 0.7.5.dev3__py3-none-any.whl → 0.8.34.dev7__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.
Files changed (393) hide show
  1. intentkit/MANIFEST.in +14 -0
  2. intentkit/README.md +88 -0
  3. intentkit/__init__.py +6 -4
  4. intentkit/abstracts/agent.py +4 -5
  5. intentkit/abstracts/engine.py +5 -5
  6. intentkit/abstracts/graph.py +15 -8
  7. intentkit/abstracts/skill.py +6 -144
  8. intentkit/abstracts/twitter.py +4 -5
  9. intentkit/clients/__init__.py +9 -2
  10. intentkit/clients/cdp.py +129 -153
  11. intentkit/{utils → clients}/s3.py +109 -34
  12. intentkit/clients/twitter.py +83 -62
  13. intentkit/clients/web3.py +4 -7
  14. intentkit/config/config.py +123 -90
  15. intentkit/core/account_checking.py +802 -0
  16. intentkit/core/agent.py +313 -498
  17. intentkit/core/asset.py +267 -0
  18. intentkit/core/chat.py +5 -3
  19. intentkit/core/client.py +1 -1
  20. intentkit/core/credit.py +49 -41
  21. intentkit/core/draft.py +201 -0
  22. intentkit/core/draft_chat.py +118 -0
  23. intentkit/core/engine.py +378 -287
  24. intentkit/core/manager/__init__.py +25 -0
  25. intentkit/core/manager/engine.py +220 -0
  26. intentkit/core/manager/service.py +172 -0
  27. intentkit/core/manager/skills.py +178 -0
  28. intentkit/core/middleware.py +231 -0
  29. intentkit/core/prompt.py +74 -114
  30. intentkit/core/scheduler.py +143 -0
  31. intentkit/core/statistics.py +168 -0
  32. intentkit/models/agent.py +931 -518
  33. intentkit/models/agent_data.py +165 -106
  34. intentkit/models/agent_schema.json +38 -251
  35. intentkit/models/app_setting.py +15 -13
  36. intentkit/models/chat.py +86 -140
  37. intentkit/models/credit.py +182 -162
  38. intentkit/models/db.py +42 -23
  39. intentkit/models/db_mig.py +120 -3
  40. intentkit/models/draft.py +222 -0
  41. intentkit/models/llm.csv +31 -0
  42. intentkit/models/llm.py +262 -370
  43. intentkit/models/redis.py +6 -4
  44. intentkit/models/skill.py +222 -101
  45. intentkit/models/skills.csv +173 -0
  46. intentkit/models/team.py +189 -0
  47. intentkit/models/user.py +103 -31
  48. intentkit/skills/acolyt/__init__.py +2 -9
  49. intentkit/skills/acolyt/ask.py +3 -4
  50. intentkit/skills/acolyt/base.py +4 -9
  51. intentkit/skills/acolyt/schema.json +4 -3
  52. intentkit/skills/aixbt/__init__.py +2 -13
  53. intentkit/skills/aixbt/base.py +1 -7
  54. intentkit/skills/aixbt/projects.py +14 -15
  55. intentkit/skills/aixbt/schema.json +4 -4
  56. intentkit/skills/allora/__init__.py +2 -9
  57. intentkit/skills/allora/base.py +4 -9
  58. intentkit/skills/allora/price.py +3 -4
  59. intentkit/skills/allora/schema.json +3 -2
  60. intentkit/skills/base.py +241 -41
  61. intentkit/skills/basename/__init__.py +51 -0
  62. intentkit/skills/basename/base.py +11 -0
  63. intentkit/skills/basename/basename.svg +11 -0
  64. intentkit/skills/basename/schema.json +58 -0
  65. intentkit/skills/carv/__init__.py +115 -121
  66. intentkit/skills/carv/base.py +184 -185
  67. intentkit/skills/carv/fetch_news.py +3 -3
  68. intentkit/skills/carv/onchain_query.py +4 -4
  69. intentkit/skills/carv/schema.json +134 -137
  70. intentkit/skills/carv/token_info_and_price.py +6 -6
  71. intentkit/skills/casino/__init__.py +4 -15
  72. intentkit/skills/casino/base.py +1 -7
  73. intentkit/skills/casino/deck_draw.py +5 -8
  74. intentkit/skills/casino/deck_shuffle.py +6 -6
  75. intentkit/skills/casino/dice_roll.py +2 -4
  76. intentkit/skills/casino/schema.json +0 -1
  77. intentkit/skills/cdp/__init__.py +22 -84
  78. intentkit/skills/cdp/base.py +1 -7
  79. intentkit/skills/cdp/schema.json +11 -314
  80. intentkit/skills/chainlist/__init__.py +2 -7
  81. intentkit/skills/chainlist/base.py +1 -7
  82. intentkit/skills/chainlist/chain_lookup.py +18 -18
  83. intentkit/skills/chainlist/schema.json +3 -5
  84. intentkit/skills/common/__init__.py +2 -9
  85. intentkit/skills/common/base.py +1 -7
  86. intentkit/skills/common/current_time.py +1 -2
  87. intentkit/skills/common/schema.json +2 -2
  88. intentkit/skills/cookiefun/__init__.py +6 -9
  89. intentkit/skills/cookiefun/base.py +2 -7
  90. intentkit/skills/cookiefun/get_account_details.py +7 -7
  91. intentkit/skills/cookiefun/get_account_feed.py +19 -19
  92. intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
  93. intentkit/skills/cookiefun/get_sectors.py +3 -3
  94. intentkit/skills/cookiefun/schema.json +1 -3
  95. intentkit/skills/cookiefun/search_accounts.py +9 -9
  96. intentkit/skills/cryptocompare/__init__.py +7 -24
  97. intentkit/skills/cryptocompare/api.py +2 -3
  98. intentkit/skills/cryptocompare/base.py +10 -24
  99. intentkit/skills/cryptocompare/fetch_news.py +4 -5
  100. intentkit/skills/cryptocompare/fetch_price.py +6 -7
  101. intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
  102. intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
  103. intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
  104. intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
  105. intentkit/skills/cryptocompare/schema.json +3 -3
  106. intentkit/skills/cryptopanic/__init__.py +7 -10
  107. intentkit/skills/cryptopanic/base.py +51 -55
  108. intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
  109. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
  110. intentkit/skills/cryptopanic/schema.json +105 -103
  111. intentkit/skills/dapplooker/__init__.py +2 -9
  112. intentkit/skills/dapplooker/base.py +4 -9
  113. intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
  114. intentkit/skills/dapplooker/schema.json +3 -5
  115. intentkit/skills/defillama/__init__.py +24 -74
  116. intentkit/skills/defillama/api.py +6 -9
  117. intentkit/skills/defillama/base.py +8 -19
  118. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
  119. intentkit/skills/defillama/coins/fetch_block.py +6 -8
  120. intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
  121. intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
  122. intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
  123. intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
  124. intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
  125. intentkit/skills/defillama/config/chains.py +1 -3
  126. intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
  127. intentkit/skills/defillama/schema.json +5 -1
  128. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
  129. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
  130. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
  131. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
  132. intentkit/skills/defillama/tests/api_integration.test.py +1 -1
  133. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
  134. intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
  135. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
  136. intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
  137. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
  138. intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
  139. intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
  140. intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
  141. intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
  142. intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
  143. intentkit/skills/defillama/yields/fetch_pools.py +26 -30
  144. intentkit/skills/dexscreener/__init__.py +97 -102
  145. intentkit/skills/dexscreener/base.py +125 -130
  146. intentkit/skills/dexscreener/get_pair_info.py +4 -5
  147. intentkit/skills/dexscreener/get_token_pairs.py +4 -5
  148. intentkit/skills/dexscreener/get_tokens_info.py +7 -8
  149. intentkit/skills/dexscreener/model/search_token_response.py +80 -82
  150. intentkit/skills/dexscreener/schema.json +91 -93
  151. intentkit/skills/dexscreener/search_token.py +182 -184
  152. intentkit/skills/dexscreener/utils.py +15 -14
  153. intentkit/skills/dune_analytics/__init__.py +7 -9
  154. intentkit/skills/dune_analytics/base.py +48 -52
  155. intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
  156. intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
  157. intentkit/skills/dune_analytics/schema.json +104 -99
  158. intentkit/skills/elfa/__init__.py +5 -18
  159. intentkit/skills/elfa/base.py +10 -14
  160. intentkit/skills/elfa/mention.py +19 -21
  161. intentkit/skills/elfa/schema.json +3 -2
  162. intentkit/skills/elfa/stats.py +4 -4
  163. intentkit/skills/elfa/tokens.py +12 -12
  164. intentkit/skills/elfa/utils.py +26 -28
  165. intentkit/skills/enso/__init__.py +11 -31
  166. intentkit/skills/enso/base.py +54 -35
  167. intentkit/skills/enso/best_yield.py +16 -24
  168. intentkit/skills/enso/networks.py +6 -11
  169. intentkit/skills/enso/prices.py +11 -13
  170. intentkit/skills/enso/route.py +34 -38
  171. intentkit/skills/enso/schema.json +3 -2
  172. intentkit/skills/enso/tokens.py +29 -38
  173. intentkit/skills/enso/wallet.py +76 -191
  174. intentkit/skills/erc20/__init__.py +50 -0
  175. intentkit/skills/erc20/base.py +11 -0
  176. intentkit/skills/erc20/erc20.svg +5 -0
  177. intentkit/skills/erc20/schema.json +74 -0
  178. intentkit/skills/erc721/__init__.py +53 -0
  179. intentkit/skills/erc721/base.py +11 -0
  180. intentkit/skills/erc721/erc721.svg +5 -0
  181. intentkit/skills/erc721/schema.json +90 -0
  182. intentkit/skills/firecrawl/__init__.py +5 -18
  183. intentkit/skills/firecrawl/base.py +4 -9
  184. intentkit/skills/firecrawl/clear.py +4 -8
  185. intentkit/skills/firecrawl/crawl.py +19 -19
  186. intentkit/skills/firecrawl/query.py +4 -3
  187. intentkit/skills/firecrawl/schema.json +2 -6
  188. intentkit/skills/firecrawl/scrape.py +17 -22
  189. intentkit/skills/firecrawl/utils.py +50 -42
  190. intentkit/skills/github/__init__.py +2 -7
  191. intentkit/skills/github/base.py +1 -7
  192. intentkit/skills/github/github_search.py +1 -2
  193. intentkit/skills/github/schema.json +3 -4
  194. intentkit/skills/heurist/__init__.py +8 -27
  195. intentkit/skills/heurist/base.py +4 -9
  196. intentkit/skills/heurist/image_generation_animagine_xl.py +13 -15
  197. intentkit/skills/heurist/image_generation_arthemy_comics.py +13 -15
  198. intentkit/skills/heurist/image_generation_arthemy_real.py +13 -15
  199. intentkit/skills/heurist/image_generation_braindance.py +13 -15
  200. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +13 -15
  201. intentkit/skills/heurist/image_generation_flux_1_dev.py +13 -15
  202. intentkit/skills/heurist/image_generation_sdxl.py +13 -15
  203. intentkit/skills/heurist/schema.json +2 -2
  204. intentkit/skills/http/__init__.py +4 -15
  205. intentkit/skills/http/base.py +1 -7
  206. intentkit/skills/http/get.py +21 -16
  207. intentkit/skills/http/post.py +23 -18
  208. intentkit/skills/http/put.py +23 -18
  209. intentkit/skills/http/schema.json +4 -5
  210. intentkit/skills/lifi/__init__.py +8 -13
  211. intentkit/skills/lifi/base.py +3 -9
  212. intentkit/skills/lifi/schema.json +17 -8
  213. intentkit/skills/lifi/token_execute.py +150 -60
  214. intentkit/skills/lifi/token_quote.py +8 -10
  215. intentkit/skills/lifi/utils.py +104 -51
  216. intentkit/skills/moralis/__init__.py +6 -10
  217. intentkit/skills/moralis/api.py +6 -7
  218. intentkit/skills/moralis/base.py +5 -10
  219. intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
  220. intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
  221. intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
  222. intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
  223. intentkit/skills/moralis/schema.json +7 -2
  224. intentkit/skills/morpho/__init__.py +52 -0
  225. intentkit/skills/morpho/base.py +11 -0
  226. intentkit/skills/morpho/morpho.svg +12 -0
  227. intentkit/skills/morpho/schema.json +73 -0
  228. intentkit/skills/nation/__init__.py +4 -9
  229. intentkit/skills/nation/base.py +5 -10
  230. intentkit/skills/nation/nft_check.py +3 -4
  231. intentkit/skills/nation/schema.json +4 -3
  232. intentkit/skills/onchain.py +30 -0
  233. intentkit/skills/openai/__init__.py +17 -18
  234. intentkit/skills/openai/base.py +10 -14
  235. intentkit/skills/openai/dalle_image_generation.py +4 -9
  236. intentkit/skills/openai/gpt_avatar_generator.py +102 -0
  237. intentkit/skills/openai/gpt_image_generation.py +5 -9
  238. intentkit/skills/openai/gpt_image_mini_generator.py +92 -0
  239. intentkit/skills/openai/gpt_image_to_image.py +5 -9
  240. intentkit/skills/openai/image_to_text.py +3 -7
  241. intentkit/skills/openai/schema.json +34 -3
  242. intentkit/skills/portfolio/__init__.py +11 -35
  243. intentkit/skills/portfolio/base.py +33 -19
  244. intentkit/skills/portfolio/schema.json +3 -5
  245. intentkit/skills/portfolio/token_balances.py +21 -21
  246. intentkit/skills/portfolio/wallet_approvals.py +17 -18
  247. intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
  248. intentkit/skills/portfolio/wallet_history.py +31 -31
  249. intentkit/skills/portfolio/wallet_net_worth.py +13 -13
  250. intentkit/skills/portfolio/wallet_nfts.py +19 -19
  251. intentkit/skills/portfolio/wallet_profitability.py +18 -18
  252. intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
  253. intentkit/skills/portfolio/wallet_stats.py +3 -3
  254. intentkit/skills/portfolio/wallet_swaps.py +19 -19
  255. intentkit/skills/pyth/__init__.py +50 -0
  256. intentkit/skills/pyth/base.py +11 -0
  257. intentkit/skills/pyth/pyth.svg +6 -0
  258. intentkit/skills/pyth/schema.json +75 -0
  259. intentkit/skills/skills.toml +36 -0
  260. intentkit/skills/slack/__init__.py +5 -17
  261. intentkit/skills/slack/base.py +3 -9
  262. intentkit/skills/slack/get_channel.py +8 -8
  263. intentkit/skills/slack/get_message.py +9 -9
  264. intentkit/skills/slack/schedule_message.py +5 -5
  265. intentkit/skills/slack/schema.json +2 -2
  266. intentkit/skills/slack/send_message.py +3 -5
  267. intentkit/skills/supabase/__init__.py +7 -23
  268. intentkit/skills/supabase/base.py +1 -7
  269. intentkit/skills/supabase/delete_data.py +4 -4
  270. intentkit/skills/supabase/fetch_data.py +12 -12
  271. intentkit/skills/supabase/insert_data.py +4 -4
  272. intentkit/skills/supabase/invoke_function.py +6 -6
  273. intentkit/skills/supabase/schema.json +2 -3
  274. intentkit/skills/supabase/update_data.py +6 -6
  275. intentkit/skills/supabase/upsert_data.py +4 -4
  276. intentkit/skills/superfluid/__init__.py +53 -0
  277. intentkit/skills/superfluid/base.py +11 -0
  278. intentkit/skills/superfluid/schema.json +89 -0
  279. intentkit/skills/superfluid/superfluid.svg +6 -0
  280. intentkit/skills/system/__init__.py +7 -24
  281. intentkit/skills/system/add_autonomous_task.py +10 -12
  282. intentkit/skills/system/delete_autonomous_task.py +2 -2
  283. intentkit/skills/system/edit_autonomous_task.py +14 -18
  284. intentkit/skills/system/list_autonomous_tasks.py +3 -5
  285. intentkit/skills/system/read_agent_api_key.py +6 -4
  286. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  287. intentkit/skills/system/schema.json +6 -8
  288. intentkit/skills/tavily/__init__.py +3 -12
  289. intentkit/skills/tavily/base.py +4 -9
  290. intentkit/skills/tavily/schema.json +3 -5
  291. intentkit/skills/tavily/tavily_extract.py +2 -4
  292. intentkit/skills/tavily/tavily_search.py +4 -6
  293. intentkit/skills/token/__init__.py +5 -10
  294. intentkit/skills/token/base.py +7 -11
  295. intentkit/skills/token/erc20_transfers.py +19 -19
  296. intentkit/skills/token/schema.json +3 -6
  297. intentkit/skills/token/token_analytics.py +3 -3
  298. intentkit/skills/token/token_price.py +13 -13
  299. intentkit/skills/token/token_search.py +9 -9
  300. intentkit/skills/twitter/__init__.py +11 -35
  301. intentkit/skills/twitter/base.py +22 -34
  302. intentkit/skills/twitter/follow_user.py +2 -6
  303. intentkit/skills/twitter/get_mentions.py +5 -12
  304. intentkit/skills/twitter/get_timeline.py +4 -12
  305. intentkit/skills/twitter/get_user_by_username.py +2 -6
  306. intentkit/skills/twitter/get_user_tweets.py +5 -13
  307. intentkit/skills/twitter/like_tweet.py +2 -6
  308. intentkit/skills/twitter/post_tweet.py +6 -9
  309. intentkit/skills/twitter/reply_tweet.py +6 -9
  310. intentkit/skills/twitter/retweet.py +2 -6
  311. intentkit/skills/twitter/schema.json +1 -0
  312. intentkit/skills/twitter/search_tweets.py +4 -12
  313. intentkit/skills/unrealspeech/__init__.py +2 -7
  314. intentkit/skills/unrealspeech/base.py +2 -8
  315. intentkit/skills/unrealspeech/schema.json +2 -5
  316. intentkit/skills/unrealspeech/text_to_speech.py +8 -8
  317. intentkit/skills/venice_audio/__init__.py +98 -106
  318. intentkit/skills/venice_audio/base.py +117 -121
  319. intentkit/skills/venice_audio/input.py +41 -41
  320. intentkit/skills/venice_audio/schema.json +151 -152
  321. intentkit/skills/venice_audio/venice_audio.py +38 -21
  322. intentkit/skills/venice_image/__init__.py +147 -154
  323. intentkit/skills/venice_image/api.py +138 -138
  324. intentkit/skills/venice_image/base.py +185 -192
  325. intentkit/skills/venice_image/config.py +33 -35
  326. intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
  327. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
  328. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
  329. intentkit/skills/venice_image/image_generation/image_generation_base.py +11 -10
  330. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
  331. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
  332. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
  333. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
  334. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
  335. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
  336. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
  337. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
  338. intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
  339. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
  340. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
  341. intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
  342. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
  343. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
  344. intentkit/skills/venice_image/schema.json +267 -267
  345. intentkit/skills/venice_image/utils.py +77 -78
  346. intentkit/skills/web_scraper/__init__.py +5 -18
  347. intentkit/skills/web_scraper/base.py +21 -7
  348. intentkit/skills/web_scraper/document_indexer.py +7 -6
  349. intentkit/skills/web_scraper/schema.json +2 -6
  350. intentkit/skills/web_scraper/scrape_and_index.py +15 -15
  351. intentkit/skills/web_scraper/utils.py +62 -63
  352. intentkit/skills/web_scraper/website_indexer.py +17 -19
  353. intentkit/skills/weth/__init__.py +49 -0
  354. intentkit/skills/weth/base.py +11 -0
  355. intentkit/skills/weth/schema.json +58 -0
  356. intentkit/skills/weth/weth.svg +6 -0
  357. intentkit/skills/wow/__init__.py +51 -0
  358. intentkit/skills/wow/base.py +11 -0
  359. intentkit/skills/wow/schema.json +89 -0
  360. intentkit/skills/wow/wow.svg +7 -0
  361. intentkit/skills/x402/__init__.py +58 -0
  362. intentkit/skills/x402/base.py +99 -0
  363. intentkit/skills/x402/http_request.py +117 -0
  364. intentkit/skills/x402/schema.json +40 -0
  365. intentkit/skills/x402/x402.webp +0 -0
  366. intentkit/skills/xmtp/__init__.py +4 -15
  367. intentkit/skills/xmtp/base.py +5 -5
  368. intentkit/skills/xmtp/price.py +7 -6
  369. intentkit/skills/xmtp/schema.json +69 -71
  370. intentkit/skills/xmtp/swap.py +6 -8
  371. intentkit/skills/xmtp/transfer.py +4 -6
  372. intentkit/utils/__init__.py +4 -0
  373. intentkit/utils/chain.py +198 -96
  374. intentkit/utils/ens.py +135 -0
  375. intentkit/utils/error.py +5 -2
  376. intentkit/utils/logging.py +9 -11
  377. intentkit/utils/schema.py +100 -0
  378. intentkit/utils/slack_alert.py +8 -8
  379. intentkit/utils/tx.py +16 -8
  380. intentkit/uv.lock +3377 -0
  381. {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/METADATA +13 -15
  382. intentkit-0.8.34.dev7.dist-info/RECORD +478 -0
  383. intentkit-0.8.34.dev7.dist-info/licenses/LICENSE +21 -0
  384. intentkit/core/node.py +0 -215
  385. intentkit/models/conversation.py +0 -286
  386. intentkit/models/generator.py +0 -347
  387. intentkit/skills/cdp/get_balance.py +0 -110
  388. intentkit/skills/cdp/swap.py +0 -121
  389. intentkit/skills/moralis/tests/__init__.py +0 -0
  390. intentkit/skills/moralis/tests/test_wallet.py +0 -511
  391. intentkit-0.7.5.dev3.dist-info/RECORD +0 -424
  392. {intentkit-0.7.5.dev3.dist-info/licenses → intentkit}/LICENSE +0 -0
  393. {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/WHEEL +0 -0
@@ -0,0 +1,267 @@
1
+ """Shared asset retrieval utilities for agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ from decimal import Decimal
8
+
9
+ import httpx
10
+ from pydantic import BaseModel, Field
11
+ from sqlalchemy import update
12
+ from web3 import Web3
13
+
14
+ from intentkit.clients.web3 import get_web3_client
15
+ from intentkit.config.config import config
16
+ from intentkit.models.agent import Agent, AgentTable
17
+ from intentkit.models.agent_data import AgentData
18
+ from intentkit.models.db import get_session
19
+ from intentkit.models.redis import get_redis
20
+ from intentkit.utils.error import IntentKitAPIError
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # USDC contract addresses for different networks
25
+ USDC_ADDRESSES = {
26
+ "base-mainnet": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
27
+ "ethereum-mainnet": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
28
+ "arbitrum-mainnet": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
29
+ "optimism-mainnet": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
30
+ "polygon-mainnet": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31
+ }
32
+
33
+ # NATION token address for base-mainnet
34
+ NATION_ADDRESS = "0x2f74f818e81685c8086dd783837a4605a90474b8"
35
+
36
+ MORALIS_CHAIN_BY_NETWORK = {
37
+ "ethereum-mainnet": "eth",
38
+ "base-mainnet": "base",
39
+ "polygon-mainnet": "polygon",
40
+ "arbitrum-mainnet": "arbitrum",
41
+ "optimism-mainnet": "optimism",
42
+ }
43
+
44
+
45
+ class Asset(BaseModel):
46
+ """Model for individual asset with symbol and balance."""
47
+
48
+ symbol: str = Field(description="Asset symbol (e.g., ETH, USDC, NATION)")
49
+ balance: Decimal = Field(description="Asset balance as decimal")
50
+
51
+
52
+ class AgentAssets(BaseModel):
53
+ """Simplified agent asset response with wallet net worth and tokens."""
54
+
55
+ net_worth: str = Field(description="Total wallet net worth in USD")
56
+ tokens: list[Asset] = Field(description="List of assets with symbol and balance")
57
+
58
+
59
+ async def _get_token_balance(
60
+ web3_client: Web3, wallet_address: str, token_address: str
61
+ ) -> Decimal:
62
+ """Get ERC-20 token balance for a wallet address."""
63
+ try:
64
+ # ERC-20 standard ABI for balanceOf and decimals
65
+ erc20_abi = [
66
+ {
67
+ "constant": True,
68
+ "inputs": [{"name": "_owner", "type": "address"}],
69
+ "name": "balanceOf",
70
+ "outputs": [{"name": "balance", "type": "uint256"}],
71
+ "type": "function",
72
+ },
73
+ {
74
+ "constant": True,
75
+ "inputs": [],
76
+ "name": "decimals",
77
+ "outputs": [{"name": "", "type": "uint8"}],
78
+ "type": "function",
79
+ },
80
+ ]
81
+
82
+ contract = web3_client.eth.contract(
83
+ address=web3_client.to_checksum_address(token_address), abi=erc20_abi
84
+ )
85
+
86
+ balance_wei = contract.functions.balanceOf(
87
+ web3_client.to_checksum_address(wallet_address)
88
+ ).call()
89
+ decimals = contract.functions.decimals().call()
90
+
91
+ # Convert from wei to token units using actual decimals
92
+ balance = Decimal(balance_wei) / Decimal(10**decimals)
93
+ return balance
94
+ except Exception as exc: # pragma: no cover - log path only
95
+ logger.error("Error getting token balance: %s", exc)
96
+ return Decimal("0")
97
+
98
+
99
+ async def _get_eth_balance(web3_client: Web3, wallet_address: str) -> Decimal:
100
+ """Get ETH balance for a wallet address."""
101
+ try:
102
+ balance_wei = web3_client.eth.get_balance(
103
+ web3_client.to_checksum_address(wallet_address)
104
+ )
105
+ balance = Decimal(balance_wei) / Decimal(10**18)
106
+ return balance
107
+ except Exception as exc: # pragma: no cover - log path only
108
+ logger.error("Error getting ETH balance: %s", exc)
109
+ return Decimal("0")
110
+
111
+
112
+ async def _get_wallet_net_worth(wallet_address: str, network_id: str | None) -> str:
113
+ """Get wallet net worth using Moralis API."""
114
+ moralis_chain = MORALIS_CHAIN_BY_NETWORK.get(network_id or "")
115
+ if not moralis_chain:
116
+ return "0"
117
+
118
+ try:
119
+ async with httpx.AsyncClient() as client:
120
+ url = (
121
+ "https://deep-index.moralis.io/api/v2.2/wallets/"
122
+ f"{wallet_address}/net-worth"
123
+ )
124
+ headers = {
125
+ "accept": "application/json",
126
+ "X-API-Key": config.moralis_api_key,
127
+ }
128
+ params = {
129
+ "exclude_spam": "true",
130
+ "exclude_unverified_contracts": "true",
131
+ "chains": [moralis_chain],
132
+ }
133
+
134
+ response = await client.get(url, headers=headers, params=params)
135
+ response.raise_for_status()
136
+ data = response.json()
137
+ return data.get("total_networth_usd", "0")
138
+ except Exception as exc: # pragma: no cover - log path only
139
+ logger.error("Error getting wallet net worth for %s: %s", wallet_address, exc)
140
+ return "0"
141
+
142
+
143
+ async def _build_assets_list(
144
+ agent: Agent, agent_data: AgentData, web3_client: Web3
145
+ ) -> list[Asset]:
146
+ """Build the assets list based on network conditions and agent configuration."""
147
+ assets: list[Asset] = []
148
+
149
+ if not agent_data or not agent_data.evm_wallet_address:
150
+ return assets
151
+
152
+ wallet_address = agent_data.evm_wallet_address
153
+ network_id: str | None = agent.network_id
154
+
155
+ # ETH is always included
156
+ eth_balance = await _get_eth_balance(web3_client, wallet_address)
157
+ assets.append(Asset(symbol="ETH", balance=eth_balance))
158
+
159
+ if network_id and network_id.endswith("-mainnet"):
160
+ usdc_address = USDC_ADDRESSES.get(str(network_id))
161
+ if usdc_address:
162
+ usdc_balance = await _get_token_balance(
163
+ web3_client, wallet_address, usdc_address
164
+ )
165
+ assets.append(Asset(symbol="USDC", balance=usdc_balance))
166
+
167
+ if network_id == "base-mainnet":
168
+ nation_balance = await _get_token_balance(
169
+ web3_client, wallet_address, NATION_ADDRESS
170
+ )
171
+ assets.append(Asset(symbol="NATION", balance=nation_balance))
172
+
173
+ if agent.ticker and agent.token_address:
174
+ lower_addresses = [addr.lower() for addr in USDC_ADDRESSES.values()]
175
+ is_usdc = agent.token_address.lower() in lower_addresses
176
+ is_nation = agent.token_address.lower() == NATION_ADDRESS.lower()
177
+
178
+ if not is_usdc and not is_nation:
179
+ custom_balance = await _get_token_balance(
180
+ web3_client, wallet_address, agent.token_address
181
+ )
182
+ assets.append(Asset(symbol=agent.ticker, balance=custom_balance))
183
+
184
+ return assets
185
+
186
+
187
+ async def agent_asset(agent_id: str) -> AgentAssets:
188
+ """Fetch wallet net worth and token balances for an agent."""
189
+
190
+ cache_key = f"intentkit:agent_assets:{agent_id}"
191
+ redis_client = None
192
+
193
+ try:
194
+ redis_client = get_redis()
195
+ except Exception as exc: # pragma: no cover - best effort fallback
196
+ logger.debug("Redis unavailable for agent assets: %s", exc)
197
+
198
+ agent = await Agent.get(agent_id)
199
+ if not agent:
200
+ raise IntentKitAPIError(404, "AgentNotFound", "Agent not found")
201
+
202
+ if redis_client:
203
+ try:
204
+ cached_raw = await redis_client.get(cache_key)
205
+ if cached_raw:
206
+ cached_data = json.loads(cached_raw)
207
+ cached_assets = AgentAssets.model_validate(cached_data)
208
+ return cached_assets
209
+ except Exception as exc: # pragma: no cover - cache read path only
210
+ logger.debug("Failed to read agent asset cache for %s: %s", agent_id, exc)
211
+
212
+ agent_data = await AgentData.get(agent_id)
213
+ if not agent_data or not agent_data.evm_wallet_address:
214
+ assets_result = AgentAssets(net_worth="0", tokens=[])
215
+ elif not agent.network_id:
216
+ assets_result = AgentAssets(net_worth="0", tokens=[])
217
+ else:
218
+ try:
219
+ web3_client = get_web3_client(str(agent.network_id))
220
+ tokens = await _build_assets_list(agent, agent_data, web3_client)
221
+ net_worth = await _get_wallet_net_worth(
222
+ agent_data.evm_wallet_address, str(agent.network_id)
223
+ )
224
+ assets_result = AgentAssets(net_worth=net_worth, tokens=tokens)
225
+ except IntentKitAPIError:
226
+ raise
227
+ except Exception as exc:
228
+ logger.error("Error getting agent assets for %s: %s", agent_id, exc)
229
+ raise IntentKitAPIError(
230
+ 500, "AgentAssetError", "Failed to retrieve agent assets"
231
+ ) from exc
232
+
233
+ assets_payload = assets_result.model_dump(mode="json")
234
+
235
+ if redis_client:
236
+ try:
237
+ await redis_client.set(
238
+ cache_key,
239
+ json.dumps(assets_payload),
240
+ ex=3600,
241
+ )
242
+ except Exception as exc: # pragma: no cover - cache write path only
243
+ logger.debug("Failed to write agent asset cache for %s: %s", agent_id, exc)
244
+
245
+ try:
246
+ async with get_session() as session:
247
+ await session.execute(
248
+ update(AgentTable)
249
+ .where(AgentTable.id == agent_id)
250
+ .values(assets=assets_payload)
251
+ )
252
+ await session.commit()
253
+ except Exception as exc: # pragma: no cover - db persistence path only
254
+ logger.error("Error updating agent assets cache for %s: %s", agent_id, exc)
255
+
256
+ return assets_result
257
+
258
+
259
+ __all__ = [
260
+ "Asset",
261
+ "AgentAssets",
262
+ "USDC_ADDRESSES",
263
+ "NATION_ADDRESS",
264
+ "agent_asset",
265
+ "_build_assets_list",
266
+ "_get_wallet_net_worth",
267
+ ]
intentkit/core/chat.py CHANGED
@@ -6,7 +6,7 @@ including clearing thread history using LangGraph's checkpointer.
6
6
 
7
7
  import logging
8
8
 
9
- from intentkit.models.db import get_langgraph_checkpointer
9
+ from intentkit.models.db import get_checkpointer
10
10
  from intentkit.utils.error import IntentKitAPIError
11
11
 
12
12
  logger = logging.getLogger(__name__)
@@ -34,7 +34,7 @@ async def clear_thread_memory(agent_id: str, chat_id: str) -> bool:
34
34
  thread_id = f"{agent_id}-{chat_id}"
35
35
 
36
36
  # Get the LangGraph checkpointer instance
37
- checkpointer = get_langgraph_checkpointer()
37
+ checkpointer = get_checkpointer()
38
38
 
39
39
  # Use the official LangGraph method to delete all thread content
40
40
  await checkpointer.adelete_thread(thread_id)
@@ -46,4 +46,6 @@ async def clear_thread_memory(agent_id: str, chat_id: str) -> bool:
46
46
  logger.error(
47
47
  f"Failed to clear thread memory for agent_id: {agent_id}, chat_id: {chat_id}. Error: {str(e)}"
48
48
  )
49
- raise IntentKitAPIError(500, "ServerError", "Failed to clear thread memory")
49
+ raise IntentKitAPIError(
50
+ status_code=500, key="ServerError", message="Failed to clear thread memory"
51
+ )
intentkit/core/client.py CHANGED
@@ -3,7 +3,7 @@
3
3
  This module provides client functions for core API endpoints with environment-aware routing.
4
4
  """
5
5
 
6
- from typing import AsyncIterator
6
+ from collections.abc import AsyncIterator
7
7
 
8
8
  import httpx
9
9
 
intentkit/core/credit.py CHANGED
@@ -1,10 +1,8 @@
1
1
  import logging
2
2
  from datetime import datetime
3
3
  from decimal import ROUND_HALF_UP, Decimal
4
- from typing import List, Optional, Tuple
5
4
 
6
5
  from epyxid import XID
7
- from fastapi import HTTPException
8
6
  from pydantic import BaseModel
9
7
  from sqlalchemy import desc, select
10
8
  from sqlalchemy.ext.asyncio import AsyncSession
@@ -39,6 +37,7 @@ from intentkit.models.credit import (
39
37
  )
40
38
  from intentkit.models.db import get_session
41
39
  from intentkit.models.skill import Skill
40
+ from intentkit.utils.error import IntentKitAPIError
42
41
  from intentkit.utils.slack_alert import send_slack_message
43
42
 
44
43
  logger = logging.getLogger(__name__)
@@ -50,7 +49,7 @@ FOURPLACES = Decimal("0.0001")
50
49
  async def update_credit_event_note(
51
50
  session: AsyncSession,
52
51
  event_id: str,
53
- note: Optional[str] = None,
52
+ note: str | None = None,
54
53
  ) -> CreditEvent:
55
54
  """
56
55
  Update the note of a credit event.
@@ -72,7 +71,9 @@ async def update_credit_event_note(
72
71
  event = result.scalar_one_or_none()
73
72
 
74
73
  if not event:
75
- raise HTTPException(status_code=404, detail="Credit event not found")
74
+ raise IntentKitAPIError(
75
+ status_code=404, key="CreditEventNotFound", message="Credit event not found"
76
+ )
76
77
 
77
78
  # Update the note
78
79
  event.note = note
@@ -87,7 +88,7 @@ async def recharge(
87
88
  user_id: str,
88
89
  amount: Decimal,
89
90
  upstream_tx_id: str,
90
- note: Optional[str] = None,
91
+ note: str | None = None,
91
92
  ) -> CreditAccount:
92
93
  """
93
94
  Recharge credits to a user account.
@@ -218,7 +219,7 @@ async def withdraw(
218
219
  agent_id: str,
219
220
  amount: Decimal,
220
221
  upstream_tx_id: str,
221
- note: Optional[str] = None,
222
+ note: str | None = None,
222
223
  ) -> CreditAccount:
223
224
  """
224
225
  Withdraw credits from an agent account to platform account.
@@ -244,10 +245,14 @@ async def withdraw(
244
245
  # Get agent to retrieve user_id from agent.owner
245
246
  agent = await Agent.get(agent_id)
246
247
  if not agent:
247
- raise HTTPException(status_code=404, detail="Agent not found")
248
+ raise IntentKitAPIError(
249
+ status_code=404, key="AgentNotFound", message="Agent not found"
250
+ )
248
251
 
249
252
  if not agent.owner:
250
- raise HTTPException(status_code=400, detail="Agent has no owner")
253
+ raise IntentKitAPIError(
254
+ status_code=400, key="AgentNoOwner", message="Agent has no owner"
255
+ )
251
256
 
252
257
  # Get agent wallet address
253
258
  agent_data = await AgentData.get(agent.id)
@@ -264,9 +269,10 @@ async def withdraw(
264
269
 
265
270
  # Check if agent has sufficient permanent credits
266
271
  if agent_account.credits < amount:
267
- raise HTTPException(
272
+ raise IntentKitAPIError(
268
273
  status_code=400,
269
- detail=f"Insufficient balance. Available: {agent_account.credits}, Required: {amount}",
274
+ key="InsufficientBalance",
275
+ message=f"Insufficient balance. Available: {agent_account.credits}, Required: {amount}",
270
276
  )
271
277
 
272
278
  # 1. Create credit event record first to get event_id
@@ -378,8 +384,8 @@ async def reward(
378
384
  user_id: str,
379
385
  amount: Decimal,
380
386
  upstream_tx_id: str,
381
- note: Optional[str] = None,
382
- reward_type: Optional[RewardType] = RewardType.REWARD,
387
+ note: str | None = None,
388
+ reward_type: RewardType | None = RewardType.REWARD,
383
389
  ) -> CreditAccount:
384
390
  """
385
391
  Reward a user account with reward credits.
@@ -672,8 +678,8 @@ async def adjustment(
672
678
  async def update_daily_quota(
673
679
  session: AsyncSession,
674
680
  user_id: str,
675
- free_quota: Optional[Decimal] = None,
676
- refill_amount: Optional[Decimal] = None,
681
+ free_quota: Decimal | None = None,
682
+ refill_amount: Decimal | None = None,
677
683
  upstream_tx_id: str = "",
678
684
  note: str = "",
679
685
  ) -> CreditAccount:
@@ -699,11 +705,11 @@ async def update_daily_quota(
699
705
  async def list_credit_events_by_user(
700
706
  session: AsyncSession,
701
707
  user_id: str,
702
- direction: Optional[Direction] = None,
703
- cursor: Optional[str] = None,
708
+ direction: Direction | None = None,
709
+ cursor: str | None = None,
704
710
  limit: int = 20,
705
- event_type: Optional[EventType] = None,
706
- ) -> Tuple[List[CreditEvent], Optional[str], bool]:
711
+ event_type: EventType | None = None,
712
+ ) -> tuple[list[CreditEvent], str | None, bool]:
707
713
  """
708
714
  List credit events for a user account with cursor pagination.
709
715
 
@@ -764,13 +770,13 @@ async def list_credit_events_by_user(
764
770
 
765
771
  async def list_credit_events(
766
772
  session: AsyncSession,
767
- direction: Optional[Direction] = Direction.EXPENSE,
768
- cursor: Optional[str] = None,
773
+ direction: Direction | None = Direction.EXPENSE,
774
+ cursor: str | None = None,
769
775
  limit: int = 20,
770
- event_type: Optional[EventType] = None,
771
- start_at: Optional[datetime] = None,
772
- end_at: Optional[datetime] = None,
773
- ) -> Tuple[List[CreditEvent], Optional[str], bool]:
776
+ event_type: EventType | None = None,
777
+ start_at: datetime | None = None,
778
+ end_at: datetime | None = None,
779
+ ) -> tuple[list[CreditEvent], str | None, bool]:
774
780
  """
775
781
  List all credit events with cursor pagination.
776
782
 
@@ -834,9 +840,9 @@ async def list_credit_events(
834
840
  async def list_fee_events_by_agent(
835
841
  session: AsyncSession,
836
842
  agent_id: str,
837
- cursor: Optional[str] = None,
843
+ cursor: str | None = None,
838
844
  limit: int = 20,
839
- ) -> Tuple[List[CreditEvent], Optional[str], bool]:
845
+ ) -> tuple[list[CreditEvent], str | None, bool]:
840
846
  """
841
847
  List fee events for an agent with cursor pagination.
842
848
  These events represent income for the agent from users' expenses.
@@ -916,9 +922,10 @@ async def fetch_credit_event_by_upstream_tx_id(
916
922
 
917
923
  # Raise 404 if not found
918
924
  if not result:
919
- raise HTTPException(
925
+ raise IntentKitAPIError(
920
926
  status_code=404,
921
- detail=f"Credit event with upstream_tx_id '{upstream_tx_id}' not found",
927
+ key="CreditEventNotFound",
928
+ message=f"Credit event with upstream_tx_id '{upstream_tx_id}' not found",
922
929
  )
923
930
 
924
931
  # Convert to Pydantic model and return
@@ -940,7 +947,7 @@ async def fetch_credit_event_by_id(
940
947
  The credit event if found.
941
948
 
942
949
  Raises:
943
- HTTPException: If the credit event is not found.
950
+ IntentKitAPIError: If the credit event is not found.
944
951
  """
945
952
  # Build the query to find the event by ID
946
953
  stmt = select(CreditEventTable).where(CreditEventTable.id == event_id)
@@ -950,9 +957,10 @@ async def fetch_credit_event_by_id(
950
957
 
951
958
  # Raise 404 if not found
952
959
  if not result:
953
- raise HTTPException(
960
+ raise IntentKitAPIError(
954
961
  status_code=404,
955
- detail=f"Credit event with ID '{event_id}' not found",
962
+ key="CreditEventNotFound",
963
+ message=f"Credit event with ID '{event_id}' not found",
956
964
  )
957
965
 
958
966
  # Convert to Pydantic model and return
@@ -1277,16 +1285,16 @@ async def skill_cost(
1277
1285
  skill = await Skill.get(skill_name)
1278
1286
  if not skill:
1279
1287
  raise ValueError(f"The price of {skill_name} not set yet")
1280
- agent_skill_config = agent.skills.get(skill.category)
1281
- if (
1282
- agent_skill_config
1283
- and agent_skill_config.get("api_key_provider") == "agent_owner"
1284
- ):
1285
- base_skill_amount = skill.price_self_key.quantize(
1286
- FOURPLACES, rounding=ROUND_HALF_UP
1287
- )
1288
- else:
1289
- base_skill_amount = skill.price.quantize(FOURPLACES, rounding=ROUND_HALF_UP)
1288
+ base_skill_amount = skill.price.quantize(FOURPLACES, rounding=ROUND_HALF_UP)
1289
+ if agent.skills:
1290
+ agent_skill_config = agent.skills.get(skill.category)
1291
+ if (
1292
+ agent_skill_config
1293
+ and agent_skill_config.get("api_key_provider") == "agent_owner"
1294
+ ):
1295
+ base_skill_amount = skill.price_self_key.quantize(
1296
+ FOURPLACES, rounding=ROUND_HALF_UP
1297
+ )
1290
1298
  # Get payment settings
1291
1299
  payment_settings = await AppSetting.payment()
1292
1300