intentkit 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of intentkit might be problematic. Click here for more details.

Files changed (366) hide show
  1. intentkit/__init__.py +17 -0
  2. intentkit/abstracts/__init__.py +0 -0
  3. intentkit/abstracts/agent.py +60 -0
  4. intentkit/abstracts/api.py +4 -0
  5. intentkit/abstracts/engine.py +38 -0
  6. intentkit/abstracts/exception.py +9 -0
  7. intentkit/abstracts/graph.py +25 -0
  8. intentkit/abstracts/skill.py +129 -0
  9. intentkit/abstracts/twitter.py +54 -0
  10. intentkit/clients/__init__.py +14 -0
  11. intentkit/clients/cdp.py +53 -0
  12. intentkit/clients/twitter.py +445 -0
  13. intentkit/config/__init__.py +0 -0
  14. intentkit/config/config.py +164 -0
  15. intentkit/core/__init__.py +0 -0
  16. intentkit/core/agent.py +191 -0
  17. intentkit/core/api.py +40 -0
  18. intentkit/core/client.py +45 -0
  19. intentkit/core/credit.py +1767 -0
  20. intentkit/core/engine.py +1018 -0
  21. intentkit/core/node.py +223 -0
  22. intentkit/core/prompt.py +58 -0
  23. intentkit/core/skill.py +124 -0
  24. intentkit/models/agent.py +1689 -0
  25. intentkit/models/agent_data.py +810 -0
  26. intentkit/models/agent_schema.json +733 -0
  27. intentkit/models/app_setting.py +156 -0
  28. intentkit/models/base.py +9 -0
  29. intentkit/models/chat.py +581 -0
  30. intentkit/models/conversation.py +286 -0
  31. intentkit/models/credit.py +1406 -0
  32. intentkit/models/db.py +120 -0
  33. intentkit/models/db_mig.py +102 -0
  34. intentkit/models/generator.py +347 -0
  35. intentkit/models/llm.py +746 -0
  36. intentkit/models/redis.py +132 -0
  37. intentkit/models/skill.py +466 -0
  38. intentkit/models/user.py +243 -0
  39. intentkit/skills/__init__.py +12 -0
  40. intentkit/skills/acolyt/__init__.py +83 -0
  41. intentkit/skills/acolyt/acolyt.jpg +0 -0
  42. intentkit/skills/acolyt/ask.py +128 -0
  43. intentkit/skills/acolyt/base.py +28 -0
  44. intentkit/skills/acolyt/schema.json +89 -0
  45. intentkit/skills/aixbt/README.md +71 -0
  46. intentkit/skills/aixbt/__init__.py +73 -0
  47. intentkit/skills/aixbt/aixbt.jpg +0 -0
  48. intentkit/skills/aixbt/base.py +21 -0
  49. intentkit/skills/aixbt/projects.py +153 -0
  50. intentkit/skills/aixbt/schema.json +99 -0
  51. intentkit/skills/allora/__init__.py +83 -0
  52. intentkit/skills/allora/allora.jpeg +0 -0
  53. intentkit/skills/allora/base.py +28 -0
  54. intentkit/skills/allora/price.py +130 -0
  55. intentkit/skills/allora/schema.json +89 -0
  56. intentkit/skills/base.py +174 -0
  57. intentkit/skills/carv/README.md +95 -0
  58. intentkit/skills/carv/__init__.py +121 -0
  59. intentkit/skills/carv/base.py +183 -0
  60. intentkit/skills/carv/carv.webp +0 -0
  61. intentkit/skills/carv/fetch_news.py +92 -0
  62. intentkit/skills/carv/onchain_query.py +164 -0
  63. intentkit/skills/carv/schema.json +137 -0
  64. intentkit/skills/carv/token_info_and_price.py +110 -0
  65. intentkit/skills/cdp/__init__.py +137 -0
  66. intentkit/skills/cdp/base.py +21 -0
  67. intentkit/skills/cdp/cdp.png +0 -0
  68. intentkit/skills/cdp/get_balance.py +81 -0
  69. intentkit/skills/cdp/schema.json +473 -0
  70. intentkit/skills/chainlist/README.md +38 -0
  71. intentkit/skills/chainlist/__init__.py +54 -0
  72. intentkit/skills/chainlist/base.py +21 -0
  73. intentkit/skills/chainlist/chain_lookup.py +208 -0
  74. intentkit/skills/chainlist/chainlist.png +0 -0
  75. intentkit/skills/chainlist/schema.json +47 -0
  76. intentkit/skills/common/__init__.py +82 -0
  77. intentkit/skills/common/base.py +21 -0
  78. intentkit/skills/common/common.jpg +0 -0
  79. intentkit/skills/common/current_time.py +84 -0
  80. intentkit/skills/common/schema.json +57 -0
  81. intentkit/skills/cookiefun/README.md +121 -0
  82. intentkit/skills/cookiefun/__init__.py +78 -0
  83. intentkit/skills/cookiefun/base.py +41 -0
  84. intentkit/skills/cookiefun/constants.py +18 -0
  85. intentkit/skills/cookiefun/cookiefun.png +0 -0
  86. intentkit/skills/cookiefun/get_account_details.py +171 -0
  87. intentkit/skills/cookiefun/get_account_feed.py +282 -0
  88. intentkit/skills/cookiefun/get_account_smart_followers.py +181 -0
  89. intentkit/skills/cookiefun/get_sectors.py +128 -0
  90. intentkit/skills/cookiefun/schema.json +155 -0
  91. intentkit/skills/cookiefun/search_accounts.py +225 -0
  92. intentkit/skills/cryptocompare/__init__.py +130 -0
  93. intentkit/skills/cryptocompare/api.py +159 -0
  94. intentkit/skills/cryptocompare/base.py +303 -0
  95. intentkit/skills/cryptocompare/cryptocompare.png +0 -0
  96. intentkit/skills/cryptocompare/fetch_news.py +96 -0
  97. intentkit/skills/cryptocompare/fetch_price.py +99 -0
  98. intentkit/skills/cryptocompare/fetch_top_exchanges.py +113 -0
  99. intentkit/skills/cryptocompare/fetch_top_market_cap.py +109 -0
  100. intentkit/skills/cryptocompare/fetch_top_volume.py +108 -0
  101. intentkit/skills/cryptocompare/fetch_trading_signals.py +107 -0
  102. intentkit/skills/cryptocompare/schema.json +168 -0
  103. intentkit/skills/cryptopanic/__init__.py +108 -0
  104. intentkit/skills/cryptopanic/base.py +51 -0
  105. intentkit/skills/cryptopanic/cryptopanic.png +0 -0
  106. intentkit/skills/cryptopanic/fetch_crypto_news.py +153 -0
  107. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +136 -0
  108. intentkit/skills/cryptopanic/schema.json +103 -0
  109. intentkit/skills/dapplooker/README.md +92 -0
  110. intentkit/skills/dapplooker/__init__.py +83 -0
  111. intentkit/skills/dapplooker/base.py +26 -0
  112. intentkit/skills/dapplooker/dapplooker.jpg +0 -0
  113. intentkit/skills/dapplooker/dapplooker_token_data.py +476 -0
  114. intentkit/skills/dapplooker/schema.json +91 -0
  115. intentkit/skills/defillama/__init__.py +323 -0
  116. intentkit/skills/defillama/api.py +315 -0
  117. intentkit/skills/defillama/base.py +135 -0
  118. intentkit/skills/defillama/coins/__init__.py +0 -0
  119. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +116 -0
  120. intentkit/skills/defillama/coins/fetch_block.py +98 -0
  121. intentkit/skills/defillama/coins/fetch_current_prices.py +105 -0
  122. intentkit/skills/defillama/coins/fetch_first_price.py +100 -0
  123. intentkit/skills/defillama/coins/fetch_historical_prices.py +110 -0
  124. intentkit/skills/defillama/coins/fetch_price_chart.py +109 -0
  125. intentkit/skills/defillama/coins/fetch_price_percentage.py +93 -0
  126. intentkit/skills/defillama/config/__init__.py +0 -0
  127. intentkit/skills/defillama/config/chains.py +433 -0
  128. intentkit/skills/defillama/defillama.jpeg +0 -0
  129. intentkit/skills/defillama/fees/__init__.py +0 -0
  130. intentkit/skills/defillama/fees/fetch_fees_overview.py +130 -0
  131. intentkit/skills/defillama/schema.json +383 -0
  132. intentkit/skills/defillama/stablecoins/__init__.py +0 -0
  133. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +100 -0
  134. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +129 -0
  135. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +83 -0
  136. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +126 -0
  137. intentkit/skills/defillama/tests/__init__.py +0 -0
  138. intentkit/skills/defillama/tests/api_integration.test.py +192 -0
  139. intentkit/skills/defillama/tests/api_unit.test.py +583 -0
  140. intentkit/skills/defillama/tvl/__init__.py +0 -0
  141. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +106 -0
  142. intentkit/skills/defillama/tvl/fetch_chains.py +107 -0
  143. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +91 -0
  144. intentkit/skills/defillama/tvl/fetch_protocol.py +207 -0
  145. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +93 -0
  146. intentkit/skills/defillama/tvl/fetch_protocols.py +196 -0
  147. intentkit/skills/defillama/volumes/__init__.py +0 -0
  148. intentkit/skills/defillama/volumes/fetch_dex_overview.py +157 -0
  149. intentkit/skills/defillama/volumes/fetch_dex_summary.py +123 -0
  150. intentkit/skills/defillama/volumes/fetch_options_overview.py +131 -0
  151. intentkit/skills/defillama/yields/__init__.py +0 -0
  152. intentkit/skills/defillama/yields/fetch_pool_chart.py +100 -0
  153. intentkit/skills/defillama/yields/fetch_pools.py +126 -0
  154. intentkit/skills/dexscreener/__init__.py +93 -0
  155. intentkit/skills/dexscreener/base.py +133 -0
  156. intentkit/skills/dexscreener/dexscreener.png +0 -0
  157. intentkit/skills/dexscreener/model/__init__.py +0 -0
  158. intentkit/skills/dexscreener/model/search_token_response.py +82 -0
  159. intentkit/skills/dexscreener/schema.json +48 -0
  160. intentkit/skills/dexscreener/search_token.py +321 -0
  161. intentkit/skills/dune_analytics/__init__.py +103 -0
  162. intentkit/skills/dune_analytics/base.py +46 -0
  163. intentkit/skills/dune_analytics/dune.png +0 -0
  164. intentkit/skills/dune_analytics/fetch_kol_buys.py +128 -0
  165. intentkit/skills/dune_analytics/fetch_nation_metrics.py +237 -0
  166. intentkit/skills/dune_analytics/schema.json +99 -0
  167. intentkit/skills/elfa/README.md +100 -0
  168. intentkit/skills/elfa/__init__.py +123 -0
  169. intentkit/skills/elfa/base.py +28 -0
  170. intentkit/skills/elfa/elfa.jpg +0 -0
  171. intentkit/skills/elfa/mention.py +504 -0
  172. intentkit/skills/elfa/schema.json +153 -0
  173. intentkit/skills/elfa/stats.py +118 -0
  174. intentkit/skills/elfa/tokens.py +126 -0
  175. intentkit/skills/enso/README.md +75 -0
  176. intentkit/skills/enso/__init__.py +114 -0
  177. intentkit/skills/enso/abi/__init__.py +0 -0
  178. intentkit/skills/enso/abi/approval.py +279 -0
  179. intentkit/skills/enso/abi/erc20.py +14 -0
  180. intentkit/skills/enso/abi/route.py +129 -0
  181. intentkit/skills/enso/base.py +44 -0
  182. intentkit/skills/enso/best_yield.py +286 -0
  183. intentkit/skills/enso/enso.jpg +0 -0
  184. intentkit/skills/enso/networks.py +105 -0
  185. intentkit/skills/enso/prices.py +93 -0
  186. intentkit/skills/enso/route.py +300 -0
  187. intentkit/skills/enso/schema.json +212 -0
  188. intentkit/skills/enso/tokens.py +223 -0
  189. intentkit/skills/enso/wallet.py +381 -0
  190. intentkit/skills/github/README.md +63 -0
  191. intentkit/skills/github/__init__.py +54 -0
  192. intentkit/skills/github/base.py +21 -0
  193. intentkit/skills/github/github.jpg +0 -0
  194. intentkit/skills/github/github_search.py +183 -0
  195. intentkit/skills/github/schema.json +59 -0
  196. intentkit/skills/heurist/__init__.py +143 -0
  197. intentkit/skills/heurist/base.py +26 -0
  198. intentkit/skills/heurist/heurist.png +0 -0
  199. intentkit/skills/heurist/image_generation_animagine_xl.py +162 -0
  200. intentkit/skills/heurist/image_generation_arthemy_comics.py +162 -0
  201. intentkit/skills/heurist/image_generation_arthemy_real.py +162 -0
  202. intentkit/skills/heurist/image_generation_braindance.py +162 -0
  203. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +162 -0
  204. intentkit/skills/heurist/image_generation_flux_1_dev.py +162 -0
  205. intentkit/skills/heurist/image_generation_sdxl.py +161 -0
  206. intentkit/skills/heurist/schema.json +196 -0
  207. intentkit/skills/lifi/README.md +294 -0
  208. intentkit/skills/lifi/__init__.py +141 -0
  209. intentkit/skills/lifi/base.py +21 -0
  210. intentkit/skills/lifi/lifi.png +0 -0
  211. intentkit/skills/lifi/schema.json +89 -0
  212. intentkit/skills/lifi/token_execute.py +472 -0
  213. intentkit/skills/lifi/token_quote.py +190 -0
  214. intentkit/skills/lifi/utils.py +656 -0
  215. intentkit/skills/moralis/README.md +490 -0
  216. intentkit/skills/moralis/__init__.py +110 -0
  217. intentkit/skills/moralis/api.py +281 -0
  218. intentkit/skills/moralis/base.py +55 -0
  219. intentkit/skills/moralis/fetch_chain_portfolio.py +191 -0
  220. intentkit/skills/moralis/fetch_nft_portfolio.py +284 -0
  221. intentkit/skills/moralis/fetch_solana_portfolio.py +331 -0
  222. intentkit/skills/moralis/fetch_wallet_portfolio.py +301 -0
  223. intentkit/skills/moralis/moralis.png +0 -0
  224. intentkit/skills/moralis/schema.json +156 -0
  225. intentkit/skills/moralis/tests/__init__.py +0 -0
  226. intentkit/skills/moralis/tests/test_wallet.py +511 -0
  227. intentkit/skills/nation/__init__.py +62 -0
  228. intentkit/skills/nation/base.py +31 -0
  229. intentkit/skills/nation/nation.png +0 -0
  230. intentkit/skills/nation/nft_check.py +106 -0
  231. intentkit/skills/nation/schema.json +58 -0
  232. intentkit/skills/openai/__init__.py +107 -0
  233. intentkit/skills/openai/base.py +32 -0
  234. intentkit/skills/openai/dalle_image_generation.py +128 -0
  235. intentkit/skills/openai/gpt_image_generation.py +152 -0
  236. intentkit/skills/openai/gpt_image_to_image.py +186 -0
  237. intentkit/skills/openai/image_to_text.py +126 -0
  238. intentkit/skills/openai/openai.png +0 -0
  239. intentkit/skills/openai/schema.json +139 -0
  240. intentkit/skills/portfolio/README.md +55 -0
  241. intentkit/skills/portfolio/__init__.py +151 -0
  242. intentkit/skills/portfolio/base.py +107 -0
  243. intentkit/skills/portfolio/constants.py +9 -0
  244. intentkit/skills/portfolio/moralis.png +0 -0
  245. intentkit/skills/portfolio/schema.json +237 -0
  246. intentkit/skills/portfolio/token_balances.py +155 -0
  247. intentkit/skills/portfolio/wallet_approvals.py +102 -0
  248. intentkit/skills/portfolio/wallet_defi_positions.py +80 -0
  249. intentkit/skills/portfolio/wallet_history.py +155 -0
  250. intentkit/skills/portfolio/wallet_net_worth.py +112 -0
  251. intentkit/skills/portfolio/wallet_nfts.py +139 -0
  252. intentkit/skills/portfolio/wallet_profitability.py +101 -0
  253. intentkit/skills/portfolio/wallet_profitability_summary.py +91 -0
  254. intentkit/skills/portfolio/wallet_stats.py +79 -0
  255. intentkit/skills/portfolio/wallet_swaps.py +147 -0
  256. intentkit/skills/skills.toml +103 -0
  257. intentkit/skills/slack/__init__.py +98 -0
  258. intentkit/skills/slack/base.py +55 -0
  259. intentkit/skills/slack/get_channel.py +109 -0
  260. intentkit/skills/slack/get_message.py +136 -0
  261. intentkit/skills/slack/schedule_message.py +92 -0
  262. intentkit/skills/slack/schema.json +135 -0
  263. intentkit/skills/slack/send_message.py +81 -0
  264. intentkit/skills/slack/slack.jpg +0 -0
  265. intentkit/skills/system/__init__.py +90 -0
  266. intentkit/skills/system/base.py +22 -0
  267. intentkit/skills/system/read_agent_api_key.py +87 -0
  268. intentkit/skills/system/regenerate_agent_api_key.py +77 -0
  269. intentkit/skills/system/schema.json +53 -0
  270. intentkit/skills/system/system.svg +76 -0
  271. intentkit/skills/tavily/README.md +86 -0
  272. intentkit/skills/tavily/__init__.py +91 -0
  273. intentkit/skills/tavily/base.py +27 -0
  274. intentkit/skills/tavily/schema.json +119 -0
  275. intentkit/skills/tavily/tavily.jpg +0 -0
  276. intentkit/skills/tavily/tavily_extract.py +147 -0
  277. intentkit/skills/tavily/tavily_search.py +139 -0
  278. intentkit/skills/token/README.md +89 -0
  279. intentkit/skills/token/__init__.py +107 -0
  280. intentkit/skills/token/base.py +154 -0
  281. intentkit/skills/token/constants.py +9 -0
  282. intentkit/skills/token/erc20_transfers.py +145 -0
  283. intentkit/skills/token/moralis.png +0 -0
  284. intentkit/skills/token/schema.json +141 -0
  285. intentkit/skills/token/token_analytics.py +81 -0
  286. intentkit/skills/token/token_price.py +132 -0
  287. intentkit/skills/token/token_search.py +121 -0
  288. intentkit/skills/twitter/__init__.py +146 -0
  289. intentkit/skills/twitter/base.py +68 -0
  290. intentkit/skills/twitter/follow_user.py +69 -0
  291. intentkit/skills/twitter/get_mentions.py +124 -0
  292. intentkit/skills/twitter/get_timeline.py +111 -0
  293. intentkit/skills/twitter/get_user_by_username.py +84 -0
  294. intentkit/skills/twitter/get_user_tweets.py +123 -0
  295. intentkit/skills/twitter/like_tweet.py +65 -0
  296. intentkit/skills/twitter/post_tweet.py +90 -0
  297. intentkit/skills/twitter/reply_tweet.py +98 -0
  298. intentkit/skills/twitter/retweet.py +76 -0
  299. intentkit/skills/twitter/schema.json +258 -0
  300. intentkit/skills/twitter/search_tweets.py +115 -0
  301. intentkit/skills/twitter/twitter.png +0 -0
  302. intentkit/skills/unrealspeech/__init__.py +55 -0
  303. intentkit/skills/unrealspeech/base.py +21 -0
  304. intentkit/skills/unrealspeech/schema.json +100 -0
  305. intentkit/skills/unrealspeech/text_to_speech.py +177 -0
  306. intentkit/skills/unrealspeech/unrealspeech.jpg +0 -0
  307. intentkit/skills/venice_audio/__init__.py +106 -0
  308. intentkit/skills/venice_audio/base.py +119 -0
  309. intentkit/skills/venice_audio/input.py +41 -0
  310. intentkit/skills/venice_audio/schema.json +152 -0
  311. intentkit/skills/venice_audio/venice_audio.py +240 -0
  312. intentkit/skills/venice_audio/venice_logo.jpg +0 -0
  313. intentkit/skills/venice_image/README.md +119 -0
  314. intentkit/skills/venice_image/__init__.py +154 -0
  315. intentkit/skills/venice_image/api.py +138 -0
  316. intentkit/skills/venice_image/base.py +188 -0
  317. intentkit/skills/venice_image/config.py +35 -0
  318. intentkit/skills/venice_image/image_enhance/README.md +119 -0
  319. intentkit/skills/venice_image/image_enhance/__init__.py +0 -0
  320. intentkit/skills/venice_image/image_enhance/image_enhance.py +80 -0
  321. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +23 -0
  322. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +40 -0
  323. intentkit/skills/venice_image/image_generation/README.md +144 -0
  324. intentkit/skills/venice_image/image_generation/__init__.py +0 -0
  325. intentkit/skills/venice_image/image_generation/image_generation_base.py +117 -0
  326. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -0
  327. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -0
  328. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -0
  329. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -0
  330. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -0
  331. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -0
  332. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -0
  333. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -0
  334. intentkit/skills/venice_image/image_upscale/README.md +111 -0
  335. intentkit/skills/venice_image/image_upscale/__init__.py +0 -0
  336. intentkit/skills/venice_image/image_upscale/image_upscale.py +90 -0
  337. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +23 -0
  338. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -0
  339. intentkit/skills/venice_image/image_vision/README.md +112 -0
  340. intentkit/skills/venice_image/image_vision/__init__.py +0 -0
  341. intentkit/skills/venice_image/image_vision/image_vision.py +100 -0
  342. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -0
  343. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -0
  344. intentkit/skills/venice_image/schema.json +267 -0
  345. intentkit/skills/venice_image/utils.py +78 -0
  346. intentkit/skills/venice_image/venice_image.jpg +0 -0
  347. intentkit/skills/web_scraper/README.md +82 -0
  348. intentkit/skills/web_scraper/__init__.py +92 -0
  349. intentkit/skills/web_scraper/base.py +21 -0
  350. intentkit/skills/web_scraper/langchain.png +0 -0
  351. intentkit/skills/web_scraper/schema.json +115 -0
  352. intentkit/skills/web_scraper/scrape_and_index.py +327 -0
  353. intentkit/utils/__init__.py +1 -0
  354. intentkit/utils/chain.py +436 -0
  355. intentkit/utils/error.py +134 -0
  356. intentkit/utils/logging.py +70 -0
  357. intentkit/utils/middleware.py +61 -0
  358. intentkit/utils/random.py +16 -0
  359. intentkit/utils/s3.py +267 -0
  360. intentkit/utils/slack_alert.py +79 -0
  361. intentkit/utils/tx.py +37 -0
  362. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/METADATA +1 -1
  363. intentkit-0.5.2.dist-info/RECORD +365 -0
  364. intentkit-0.5.0.dist-info/RECORD +0 -4
  365. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/WHEEL +0 -0
  366. {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,186 @@
1
+ """GPT image-to-image generation skill for OpenAI."""
2
+
3
+ import base64
4
+ import logging
5
+ from io import BytesIO
6
+ from typing import Literal, Type
7
+
8
+ import httpx
9
+ import openai
10
+ from epyxid import XID
11
+ from langchain_core.runnables import RunnableConfig
12
+ from pydantic import BaseModel, Field
13
+
14
+ from intentkit.skills.openai.base import OpenAIBaseTool
15
+ from intentkit.utils.s3 import store_image_bytes
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class GPTImageToImageInput(BaseModel):
21
+ """Input for GPTImageToImage tool."""
22
+
23
+ image_url: str = Field(
24
+ description="URL of the source image to edit.",
25
+ )
26
+ prompt: str = Field(
27
+ description="Text prompt describing the desired edits to the image.",
28
+ )
29
+ size: Literal["1024x1024", "1536x1024", "1024x1536", "auto"] = Field(
30
+ default="auto",
31
+ description="Size of the generated image. Options: 1024x1024, 1536x1024, 1024x1536, auto",
32
+ )
33
+ quality: Literal["high", "medium", "low", "auto"] = Field(
34
+ default="auto",
35
+ description="Quality of the generated image. Options: high, medium, low, auto",
36
+ )
37
+
38
+
39
+ class GPTImageToImage(OpenAIBaseTool):
40
+ """Tool for editing images using OpenAI's GPT-Image-1 model.
41
+
42
+ This tool takes a source image URL and a text prompt, then uses OpenAI's API to
43
+ generate an edited version of the image based on the description.
44
+
45
+ Attributes:
46
+ name: The name of the tool.
47
+ description: A description of what the tool does.
48
+ args_schema: The schema for the tool's input arguments.
49
+ """
50
+
51
+ name: str = "gpt_image_to_image"
52
+ description: str = (
53
+ "Edit images using OpenAI's GPT-Image-1 model.\n"
54
+ "Provide a source image URL and a text prompt describing the desired edits.\n"
55
+ "GPT-Image-1 is a powerful image editing model capable of transforming images "
56
+ "based on text descriptions.\n"
57
+ "You can specify size and quality parameters for more control.\n"
58
+ )
59
+ args_schema: Type[BaseModel] = GPTImageToImageInput
60
+
61
+ async def _arun(
62
+ self,
63
+ image_url: str,
64
+ prompt: str,
65
+ size: Literal["1024x1024", "1536x1024", "1024x1536", "auto"] = "auto",
66
+ quality: Literal["high", "medium", "low", "auto"] = "auto",
67
+ config: RunnableConfig = None,
68
+ **kwargs,
69
+ ) -> str:
70
+ """Implementation of the tool to edit images using OpenAI's GPT-Image-1 model.
71
+
72
+ Args:
73
+ image_url: URL of the source image to edit.
74
+ prompt: Text prompt describing the desired edits to the image.
75
+ size: Size of the generated image. Options: 1024x1024, 1536x1024, 1024x1536, auto
76
+ quality: Quality of the generated image. Options: high, medium, low, auto
77
+ config: Configuration for the runnable.
78
+
79
+ Returns:
80
+ str: URL of the edited image.
81
+
82
+ Raises:
83
+ Exception: If the image editing fails.
84
+ """
85
+ context = self.context_from_config(config)
86
+
87
+ # Get the OpenAI API key from the skill store
88
+ api_key = self.get_api_key(context)
89
+
90
+ # Generate a unique job ID
91
+ job_id = str(XID())
92
+
93
+ try:
94
+ # Download the image from the URL asynchronously
95
+ async with httpx.AsyncClient() as client:
96
+ response = await client.get(image_url, follow_redirects=True)
97
+ response.raise_for_status()
98
+ image_data = response.content
99
+
100
+ # Initialize the OpenAI client
101
+ client = openai.OpenAI(api_key=api_key)
102
+
103
+ # Import required modules for file handling
104
+ import os
105
+ import tempfile
106
+
107
+ from PIL import Image
108
+
109
+ # Create a temporary file with .png extension
110
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_file:
111
+ temp_path = temp_file.name
112
+
113
+ # Open the image, convert to RGB if needed, and save as PNG
114
+ img = Image.open(BytesIO(image_data))
115
+ if img.mode != "RGB":
116
+ img = img.convert("RGB")
117
+ img.save(temp_path, format="PNG")
118
+
119
+ # Open the temporary file in binary read mode
120
+ # This provides both .read() method and .name attribute that OpenAI SDK needs
121
+ image_file = open(temp_path, "rb")
122
+
123
+ # Make the API request to edit the image
124
+ try:
125
+ response = client.images.edit(
126
+ model="gpt-image-1",
127
+ image=image_file, # Use the file object with .read() method and .name attribute
128
+ prompt=prompt,
129
+ size=size,
130
+ quality=quality,
131
+ n=1,
132
+ )
133
+
134
+ # GPT-Image-1 always returns base64-encoded images
135
+ # Get the base64 image data from the response
136
+ base64_image = response.data[0].b64_json
137
+
138
+ # Log the usage information if available
139
+ if hasattr(response, "usage") and response.usage:
140
+ usage = response.usage
141
+ logger.info(
142
+ f"GPT-Image-1 edit usage: "
143
+ f"input_tokens={usage.input_tokens}, "
144
+ f"output_tokens={usage.output_tokens}, "
145
+ f"total_tokens={usage.total_tokens}"
146
+ )
147
+
148
+ # Log detailed input tokens information if available
149
+ if (
150
+ hasattr(usage, "input_tokens_details")
151
+ and usage.input_tokens_details
152
+ ):
153
+ details = usage.input_tokens_details
154
+ logger.info(f"Input tokens details: {details}")
155
+
156
+ # Decode the base64 string to bytes
157
+ image_bytes = base64.b64decode(base64_image)
158
+
159
+ # Generate a key with agent ID as prefix
160
+ image_key = f"{context.agent.id}/gpt-image-edit/{job_id}"
161
+
162
+ # Store the image bytes and get the CDN URL
163
+ stored_url = await store_image_bytes(image_bytes, image_key)
164
+ finally:
165
+ # Close and remove the temporary file
166
+ image_file.close()
167
+ if os.path.exists(temp_path):
168
+ os.unlink(temp_path)
169
+
170
+ # Return the stored image URL
171
+ return stored_url
172
+
173
+ except httpx.HTTPError as e:
174
+ error_message = f"Failed to download image from URL {image_url}: {str(e)}"
175
+ logger.error(error_message)
176
+ raise Exception(error_message)
177
+
178
+ except openai.OpenAIError as e:
179
+ error_message = f"OpenAI API error: {str(e)}"
180
+ logger.error(error_message)
181
+ raise Exception(error_message)
182
+
183
+ except Exception as e:
184
+ error_message = f"Error editing image with GPT-Image-1: {str(e)}"
185
+ logger.error(error_message)
186
+ raise Exception(error_message)
@@ -0,0 +1,126 @@
1
+ import io
2
+ import logging
3
+ from typing import Type
4
+
5
+ import aiohttp
6
+ import openai
7
+ from langchain_core.runnables import RunnableConfig
8
+ from PIL import Image
9
+ from pydantic import BaseModel, Field
10
+
11
+ from intentkit.skills.openai.base import OpenAIBaseTool
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ImageToTextInput(BaseModel):
17
+ """Input for ImageToText tool."""
18
+
19
+ image: str = Field(
20
+ description="URL of the image to convert to text.",
21
+ )
22
+
23
+
24
+ class ImageToTextOutput(BaseModel):
25
+ """Output for ImageToText tool."""
26
+
27
+ description: str = Field(description="Detailed text description of the image.")
28
+ width: int = Field(description="Width of the processed image.")
29
+ height: int = Field(description="Height of the processed image.")
30
+
31
+
32
+ class ImageToText(OpenAIBaseTool):
33
+ """Tool for converting images to text using OpenAI's GPT-4o model.
34
+
35
+ This tool takes an image URL and uses OpenAI's vision capabilities
36
+ to generate a detailed text description of the image content.
37
+
38
+ Attributes:
39
+ name: The name of the tool.
40
+ description: A description of what the tool does.
41
+ args_schema: The schema for the tool's input arguments.
42
+ """
43
+
44
+ name: str = "image_to_text"
45
+ description: str = (
46
+ "Convert an image to detailed text description.\n"
47
+ "Provide a URL to the image to analyze and get a comprehensive textual description.\n"
48
+ "Optimized for DALL-E generated images and preserves as many details as possible."
49
+ )
50
+ args_schema: Type[BaseModel] = ImageToTextInput
51
+
52
+ async def _arun(
53
+ self, image: str, config: RunnableConfig, **kwargs
54
+ ) -> ImageToTextOutput:
55
+ """Implementation of the tool to convert images to text.
56
+
57
+ Args:
58
+ image (str): URL of the image to convert to text.
59
+
60
+ Returns:
61
+ ImageToTextOutput: Object containing the text description and image dimensions.
62
+ """
63
+ context = self.context_from_config(config)
64
+ logger.debug(f"context: {context}")
65
+
66
+ # Get the OpenAI client from the skill store
67
+ api_key = self.get_api_key(context)
68
+ client = openai.AsyncOpenAI(api_key=api_key)
69
+
70
+ try:
71
+ # Download the image from the URL
72
+ async with aiohttp.ClientSession() as session:
73
+ async with session.get(image) as response:
74
+ if response.status != 200:
75
+ raise Exception(
76
+ f"Failed to download image from URL: {response.status}"
77
+ )
78
+
79
+ # Get image data
80
+ image_data = await response.read()
81
+ img = Image.open(io.BytesIO(image_data))
82
+
83
+ # Get original dimensions
84
+ orig_width, orig_height = img.size
85
+
86
+ # Calculate new dimensions with longest side as 1024 (for reference only)
87
+ max_size = 1024
88
+ if orig_width >= orig_height:
89
+ scaled_width = max_size
90
+ scaled_height = int(orig_height * (max_size / orig_width))
91
+ else:
92
+ scaled_height = max_size
93
+ scaled_width = int(orig_width * (max_size / orig_height))
94
+
95
+ # Use OpenAI API to analyze the image (using original image)
96
+ response = await client.chat.completions.create(
97
+ model="gpt-4o",
98
+ messages=[
99
+ {
100
+ "role": "system",
101
+ "content": "You are an expert image analyzer. Describe the image in great detail, capturing all visual elements, colors, composition, subjects, and context. If there are people in the picture, be sure to clearly describe the person's skin color, hair color, expression, direction, etc. For DALL-E generated images, pay special attention to artistic style, lighting effects, and fantastical elements. Preserve as many details as possible in your description.",
102
+ },
103
+ {
104
+ "role": "user",
105
+ "content": [
106
+ {"type": "text", "text": "Describe this image in detail:"},
107
+ {
108
+ "type": "image_url",
109
+ "image_url": {"url": image, "detail": "high"},
110
+ },
111
+ ],
112
+ },
113
+ ],
114
+ max_tokens=1000,
115
+ )
116
+
117
+ # Return the text description and scaled image dimensions
118
+ return ImageToTextOutput(
119
+ description=response.choices[0].message.content,
120
+ width=scaled_width,
121
+ height=scaled_height,
122
+ )
123
+
124
+ except Exception as e:
125
+ logger.error(f"Error converting image to text: {e}")
126
+ raise Exception(f"Error converting image to text: {str(e)}")
Binary file
@@ -0,0 +1,139 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "OpenAI",
5
+ "description": "Skills for interacting with OpenAI services, including image generation, image-to-text conversion, and other AI capabilities",
6
+ "x-icon": "https://ai.service.crestal.dev/skills/openai/openai.png",
7
+ "x-tags": [
8
+ "AI",
9
+ "Image Generation",
10
+ "Image Analysis"
11
+ ],
12
+ "properties": {
13
+ "enabled": {
14
+ "type": "boolean",
15
+ "title": "Enabled",
16
+ "description": "Whether this skill is enabled",
17
+ "default": true
18
+ },
19
+ "states": {
20
+ "type": "object",
21
+ "properties": {
22
+ "image_to_text": {
23
+ "type": "string",
24
+ "title": "Image to Text",
25
+ "enum": [
26
+ "disabled",
27
+ "public",
28
+ "private"
29
+ ],
30
+ "x-enum-title": [
31
+ "Disabled",
32
+ "Agent Owner + All Users",
33
+ "Agent Owner Only"
34
+ ],
35
+ "description": "Convert images to detailed text descriptions using OpenAI's GPT-4o model",
36
+ "default": "private"
37
+ },
38
+ "dalle_image_generation": {
39
+ "type": "string",
40
+ "title": "Image Generation by DALL-E",
41
+ "enum": [
42
+ "disabled",
43
+ "public",
44
+ "private"
45
+ ],
46
+ "x-enum-title": [
47
+ "Disabled",
48
+ "Agent Owner + All Users",
49
+ "Agent Owner Only"
50
+ ],
51
+ "description": "Generate images using OpenAI's DALL-E model based on text prompts",
52
+ "default": "disabled"
53
+ },
54
+ "gpt_image_generation": {
55
+ "type": "string",
56
+ "title": "Image Generation by GPT",
57
+ "enum": [
58
+ "disabled",
59
+ "public",
60
+ "private"
61
+ ],
62
+ "x-enum-title": [
63
+ "Disabled",
64
+ "Agent Owner + All Users",
65
+ "Agent Owner Only"
66
+ ],
67
+ "description": "Generate images using OpenAI's GPT-Image-1 model based on text prompts",
68
+ "default": "private"
69
+ },
70
+ "gpt_image_to_image": {
71
+ "type": "string",
72
+ "title": "Image Editing by GPT",
73
+ "enum": [
74
+ "disabled",
75
+ "public",
76
+ "private"
77
+ ],
78
+ "x-enum-title": [
79
+ "Disabled",
80
+ "Agent Owner + All Users",
81
+ "Agent Owner Only"
82
+ ],
83
+ "description": "Edit images using OpenAI's GPT-Image-1 model based on text prompts",
84
+ "default": "private"
85
+ }
86
+ },
87
+ "description": "States for each OpenAI skill (disabled, public, or private)"
88
+ },
89
+ "api_key_provider": {
90
+ "type": "string",
91
+ "title": "API Key Provider",
92
+ "description": "Provider of the API key",
93
+ "enum": [
94
+ "platform",
95
+ "agent_owner"
96
+ ],
97
+ "x-enum-title": [
98
+ "Nation Hosted",
99
+ "Owner Provided"
100
+ ],
101
+ "default": "platform"
102
+ }
103
+ },
104
+ "required": [
105
+ "states",
106
+ "enabled"
107
+ ],
108
+ "if": {
109
+ "properties": {
110
+ "api_key_provider": {
111
+ "const": "agent_owner"
112
+ }
113
+ }
114
+ },
115
+ "then": {
116
+ "properties": {
117
+ "api_key": {
118
+ "type": "string",
119
+ "title": "API Key",
120
+ "x-link": "[Get your API key](https://platform.openai.com/)",
121
+ "x-sensitive": true,
122
+ "description": "OpenAI API key for authentication"
123
+ }
124
+ },
125
+ "if": {
126
+ "properties": {
127
+ "enabled": {
128
+ "const": true
129
+ }
130
+ }
131
+ },
132
+ "then": {
133
+ "required": [
134
+ "api_key"
135
+ ]
136
+ }
137
+ },
138
+ "additionalProperties": true
139
+ }
@@ -0,0 +1,55 @@
1
+ # Blockchain Portfolio Analysis Skills
2
+
3
+ A set of skills for analyzing blockchain wallets and portfolios through the Moralis API, allowing agents to retrieve wallet data, token balances, and investment performance across various blockchain networks.
4
+
5
+ ## Available Skills
6
+
7
+ | Skill | Description | Endpoint | Example Prompts |
8
+ |-------|-------------|----------|----------------|
9
+ | `wallet_history` | Gets transaction history including sends, receives, token transfers | `GET /wallets/{address}/history` | "Show me all transactions for wallet 0x123..." <br> "What are the recent transactions for this ETH address?" |
10
+ | `token_balances` | Gets token balances and USD value with spam filtering options | `GET /wallets/{address}/tokens` | "What tokens does wallet 0x123 hold?" <br> "Show me token balances with USD values for this address" |
11
+ | `wallet_approvals` | Lists active ERC20 token approvals to identify spend permissions | `GET /wallets/{address}/approvals` | "Check what contracts have approval to spend from wallet 0x123" <br> "Has this wallet approved any token spending?" |
12
+ | `wallet_swaps` | Lists all swap-related transactions (buy/sell) for trade analysis | `GET /wallets/{address}/swaps` | "Show me all token swaps for wallet 0x123" <br> "What trading activity has this address performed?" |
13
+ | `wallet_net_worth` | Calculates total wallet value in USD across multiple chains | `GET /wallets/{address}/net-worth` | "What's the total value of wallet 0x123?" <br> "Calculate the net worth of this address across all chains" |
14
+ | `wallet_profitability_summary` | Provides overview of wallet profitability metrics | `GET /wallets/{address}/profitability/summary` | "Is wallet 0x123 profitable overall?" <br> "Give me a summary of trading performance for this address" |
15
+ | `wallet_profitability` | Delivers detailed profitability by token with buy/sell prices | `GET /wallets/{address}/profitability` | "Show detailed profit/loss for each token in wallet 0x123" <br> "What's the cost basis of tokens in this wallet?" |
16
+ | `wallet_stats` | Provides statistics about NFTs, collections, and transactions | `GET /wallets/{address}/stats` | "How many NFTs does wallet 0x123 have?" <br> "Give me stats about this wallet's activity" |
17
+ | `wallet_defi_positions` | Get DeFi positions for a wallet | `GET /wallets/{address}/defi/positions` | "What DeFi positions does my wallet have?" <br> "Show my liquidity positions." |
18
+ | `wallet_nfts` | Get NFTs owned by a wallet address | `GET /{address}/nft` | "What NFTs does wallet 0x123 own?" <br> "Show me all the NFTs in my wallet." |
19
+
20
+ All endpoints use the base URL defined in `constants.py`: `https://deep-index.moralis.io/api/v2.2`
21
+
22
+ ## Migration Note
23
+
24
+ If you're currently using the Moralis module, simply update your configuration by changing `moralis:` to `portfolio:`. All functionality remains identical.
25
+
26
+ ## Authentication
27
+
28
+ All API requests include the Moralis API key in the header:
29
+ ```
30
+ X-API-Key: YOUR_MORALIS_API_KEY
31
+ ```
32
+
33
+ ## Supported Chains
34
+
35
+ These skills support various EVM-compatible chains:
36
+ - Ethereum (eth)
37
+ - Polygon (polygon)
38
+ - Binance Smart Chain (bsc)
39
+ - Avalanche (avalanche)
40
+ - Arbitrum (arbitrum)
41
+ - Optimism (optimism)
42
+ - Base (base)
43
+
44
+ ## Key Parameters
45
+
46
+ Most endpoints support these common parameters:
47
+ - `chain`: The chain to query (default: eth)
48
+ - `limit`: Number of results per page
49
+ - `cursor`: Pagination cursor for subsequent requests
50
+
51
+ ## Getting a Moralis API Key
52
+
53
+ 1. Create an account at [Moralis.io](https://moralis.io/)
54
+ 2. Navigate to the API Keys section in your dashboard
55
+ 3. Create a new key with appropriate permissions
@@ -0,0 +1,151 @@
1
+ """Portfolio skills for blockchain wallet analysis."""
2
+
3
+ import logging
4
+ from typing import TypedDict
5
+
6
+ from intentkit.abstracts.skill import SkillStoreABC
7
+ from intentkit.skills.base import SkillConfig, SkillState
8
+ from intentkit.skills.portfolio.base import PortfolioBaseTool
9
+ from intentkit.skills.portfolio.token_balances import TokenBalances
10
+ from intentkit.skills.portfolio.wallet_approvals import WalletApprovals
11
+ from intentkit.skills.portfolio.wallet_defi_positions import WalletDefiPositions
12
+ from intentkit.skills.portfolio.wallet_history import WalletHistory
13
+ from intentkit.skills.portfolio.wallet_net_worth import WalletNetWorth
14
+ from intentkit.skills.portfolio.wallet_nfts import WalletNFTs
15
+ from intentkit.skills.portfolio.wallet_profitability import WalletProfitability
16
+ from intentkit.skills.portfolio.wallet_profitability_summary import (
17
+ WalletProfitabilitySummary,
18
+ )
19
+ from intentkit.skills.portfolio.wallet_stats import WalletStats
20
+ from intentkit.skills.portfolio.wallet_swaps import WalletSwaps
21
+
22
+ # Cache skills at the system level, because they are stateless
23
+ _cache: dict[str, PortfolioBaseTool] = {}
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class SkillStates(TypedDict):
29
+ """State configurations for Portfolio skills."""
30
+
31
+ wallet_history: SkillState
32
+ token_balances: SkillState
33
+ wallet_approvals: SkillState
34
+ wallet_swaps: SkillState
35
+ wallet_net_worth: SkillState
36
+ wallet_profitability_summary: SkillState
37
+ wallet_profitability: SkillState
38
+ wallet_stats: SkillState
39
+ wallet_defi_positions: SkillState
40
+ wallet_nfts: SkillState
41
+
42
+
43
+ class Config(SkillConfig):
44
+ """Configuration for Portfolio blockchain analysis skills."""
45
+
46
+ states: SkillStates
47
+ api_key: str
48
+ api_key_provider: str
49
+
50
+
51
+ async def get_skills(
52
+ config: "Config",
53
+ is_private: bool,
54
+ store: SkillStoreABC,
55
+ **_,
56
+ ) -> list[PortfolioBaseTool]:
57
+ """Get all Portfolio blockchain analysis skills.
58
+
59
+ Args:
60
+ config: The configuration for Portfolio skills.
61
+ is_private: Whether to include private skills.
62
+ store: The skill store for persisting data.
63
+
64
+ Returns:
65
+ A list of Portfolio blockchain analysis skills.
66
+ """
67
+ available_skills = []
68
+
69
+ # Include skills based on their state
70
+ for skill_name, state in config["states"].items():
71
+ if state == "disabled":
72
+ continue
73
+ elif state == "public" or (state == "private" and is_private):
74
+ available_skills.append(skill_name)
75
+
76
+ # Get each skill using the cached getter
77
+ result = []
78
+ for name in available_skills:
79
+ skill = get_portfolio_skill(name, store)
80
+ if skill:
81
+ result.append(skill)
82
+ return result
83
+
84
+
85
+ def get_portfolio_skill(
86
+ name: str,
87
+ store: SkillStoreABC,
88
+ ) -> PortfolioBaseTool:
89
+ """Get a portfolio skill by name."""
90
+ if name == "wallet_history":
91
+ if name not in _cache:
92
+ _cache[name] = WalletHistory(
93
+ skill_store=store,
94
+ )
95
+ return _cache[name]
96
+ elif name == "token_balances":
97
+ if name not in _cache:
98
+ _cache[name] = TokenBalances(
99
+ skill_store=store,
100
+ )
101
+ return _cache[name]
102
+ elif name == "wallet_approvals":
103
+ if name not in _cache:
104
+ _cache[name] = WalletApprovals(
105
+ skill_store=store,
106
+ )
107
+ return _cache[name]
108
+ elif name == "wallet_swaps":
109
+ if name not in _cache:
110
+ _cache[name] = WalletSwaps(
111
+ skill_store=store,
112
+ )
113
+ return _cache[name]
114
+ elif name == "wallet_net_worth":
115
+ if name not in _cache:
116
+ _cache[name] = WalletNetWorth(
117
+ skill_store=store,
118
+ )
119
+ return _cache[name]
120
+ elif name == "wallet_profitability_summary":
121
+ if name not in _cache:
122
+ _cache[name] = WalletProfitabilitySummary(
123
+ skill_store=store,
124
+ )
125
+ return _cache[name]
126
+ elif name == "wallet_profitability":
127
+ if name not in _cache:
128
+ _cache[name] = WalletProfitability(
129
+ skill_store=store,
130
+ )
131
+ return _cache[name]
132
+ elif name == "wallet_stats":
133
+ if name not in _cache:
134
+ _cache[name] = WalletStats(
135
+ skill_store=store,
136
+ )
137
+ return _cache[name]
138
+ elif name == "wallet_defi_positions":
139
+ if name not in _cache:
140
+ _cache[name] = WalletDefiPositions(
141
+ skill_store=store,
142
+ )
143
+ return _cache[name]
144
+ elif name == "wallet_nfts":
145
+ if name not in _cache:
146
+ _cache[name] = WalletNFTs(
147
+ skill_store=store,
148
+ )
149
+ return _cache[name]
150
+ else:
151
+ raise ValueError(f"Unknown portfolio skill: {name}")