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,181 @@
1
+ from typing import Any, Dict, List, Optional, Type, Union
2
+
3
+ import httpx
4
+ from langchain_core.runnables import RunnableConfig
5
+ from pydantic import BaseModel, Field
6
+
7
+ from intentkit.skills.cookiefun.base import CookieFunBaseTool, logger
8
+ from intentkit.skills.cookiefun.constants import DEFAULT_HEADERS, ENDPOINTS
9
+
10
+
11
+ class GetAccountSmartFollowersInput(BaseModel):
12
+ """Input for GetAccountSmartFollowers tool."""
13
+
14
+ username: Optional[str] = Field(
15
+ default=None,
16
+ description="Twitter username (either username or userId is required)",
17
+ )
18
+
19
+ userId: Optional[str] = Field(
20
+ default=None,
21
+ description="Twitter user ID (either username or userId is required)",
22
+ )
23
+
24
+
25
+ class GetAccountSmartFollowers(CookieFunBaseTool):
26
+ """Tool to get smart followers for a Twitter account."""
27
+
28
+ name: str = "cookiefun_get_account_smart_followers"
29
+ description: str = "Returns a list of top smart followers for a specific Twitter account, with detailed metrics about these followers."
30
+ args_schema: Type[BaseModel] = GetAccountSmartFollowersInput
31
+
32
+ async def _arun(
33
+ self,
34
+ config: RunnableConfig,
35
+ username: Optional[str] = None,
36
+ userId: Optional[str] = None,
37
+ **kwargs,
38
+ ) -> Union[List[Dict[str, Any]], str]:
39
+ """
40
+ Get smart followers for a Twitter account.
41
+
42
+ Args:
43
+ username: Twitter username (either username or userId is required)
44
+ userId: Twitter user ID (either username or userId is required)
45
+
46
+ Returns:
47
+ List of top smart followers with their metrics.
48
+ """
49
+ logger.info(
50
+ "Getting smart followers for username=%s, userId=%s", username, userId
51
+ )
52
+
53
+ # Validate input parameters
54
+ if not username and not userId:
55
+ logger.error("Neither username nor userId provided")
56
+ return "Error: Either username or userId must be provided."
57
+
58
+ try:
59
+ # Get context to retrieve API key
60
+ api_key = self.get_api_key(config)
61
+
62
+ if not api_key:
63
+ logger.error("No API key provided for CookieFun API")
64
+ return "Error: No API key provided for CookieFun API. Please configure the API key in the agent settings."
65
+
66
+ # Prepare request payload
67
+ payload = {}
68
+ if username:
69
+ payload["username"] = username
70
+ if userId:
71
+ payload["userId"] = userId
72
+
73
+ # Make API request
74
+ headers = {**DEFAULT_HEADERS, "x-api-key": api_key}
75
+
76
+ async with httpx.AsyncClient() as client:
77
+ response = await client.post(
78
+ ENDPOINTS["smart_followers"], headers=headers, json=payload
79
+ )
80
+ logger.debug(
81
+ "Received response with status code: %d", response.status_code
82
+ )
83
+
84
+ response.raise_for_status()
85
+ data = response.json()
86
+
87
+ # Check different possible response structures
88
+ if data.get("success") and "ok" in data and "entries" in data["ok"]:
89
+ followers = data["ok"]["entries"]
90
+ logger.info(
91
+ "Successfully retrieved %d smart followers from entries field",
92
+ len(followers),
93
+ )
94
+ return followers
95
+ elif data.get("success") and "ok" in data and "accounts" in data["ok"]:
96
+ followers = data["ok"]["accounts"]
97
+ logger.info(
98
+ "Successfully retrieved %d smart followers", len(followers)
99
+ )
100
+ return followers
101
+ elif data.get("success") and "ok" in data and "followers" in data["ok"]:
102
+ followers = data["ok"]["followers"]
103
+ logger.info(
104
+ "Successfully retrieved %d smart followers from followers field",
105
+ len(followers),
106
+ )
107
+ return followers
108
+ elif (
109
+ data.get("success")
110
+ and "ok" in data
111
+ and isinstance(data["ok"], list)
112
+ ):
113
+ followers = data["ok"]
114
+ logger.info(
115
+ "Successfully retrieved %d smart followers from ok list",
116
+ len(followers),
117
+ )
118
+ return followers
119
+ elif data.get("success") and isinstance(data.get("accounts"), list):
120
+ followers = data["accounts"]
121
+ logger.info(
122
+ "Successfully retrieved %d smart followers from top level accounts",
123
+ len(followers),
124
+ )
125
+ return followers
126
+ elif data.get("success") and isinstance(data.get("followers"), list):
127
+ followers = data["followers"]
128
+ logger.info(
129
+ "Successfully retrieved %d smart followers from top level followers",
130
+ len(followers),
131
+ )
132
+ return followers
133
+ elif data.get("success") and isinstance(data.get("entries"), list):
134
+ followers = data["entries"]
135
+ logger.info(
136
+ "Successfully retrieved %d smart followers from top level entries",
137
+ len(followers),
138
+ )
139
+ return followers
140
+ elif "followers" in data and isinstance(data["followers"], list):
141
+ followers = data["followers"]
142
+ logger.info(
143
+ "Successfully retrieved %d smart followers from direct followers field",
144
+ len(followers),
145
+ )
146
+ return followers
147
+ elif "accounts" in data and isinstance(data["accounts"], list):
148
+ followers = data["accounts"]
149
+ logger.info(
150
+ "Successfully retrieved %d smart followers from direct accounts field",
151
+ len(followers),
152
+ )
153
+ return followers
154
+ elif "entries" in data and isinstance(data["entries"], list):
155
+ followers = data["entries"]
156
+ logger.info(
157
+ "Successfully retrieved %d smart followers from direct entries field",
158
+ len(followers),
159
+ )
160
+ return followers
161
+ else:
162
+ # If we can't find followers in the expected structure, log the full response
163
+ logger.error(
164
+ "Could not find smart followers in response structure. Full response: %s",
165
+ data,
166
+ )
167
+ error_msg = data.get(
168
+ "error", "Unknown error - check API response format"
169
+ )
170
+ logger.error("Error in API response: %s", error_msg)
171
+ return f"Error fetching smart followers: {error_msg}"
172
+
173
+ except httpx.HTTPStatusError as e:
174
+ logger.error("HTTP error: %d - %s", e.response.status_code, e.response.text)
175
+ return f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
176
+ except httpx.RequestError as e:
177
+ logger.error("Request error: %s", str(e))
178
+ return f"Request error occurred: {str(e)}"
179
+ except Exception as e:
180
+ logger.exception("Unexpected error occurred")
181
+ return f"An unexpected error occurred: {str(e)}"
@@ -0,0 +1,128 @@
1
+ from typing import Any, Dict, List, Type
2
+
3
+ import httpx
4
+ from langchain_core.runnables import RunnableConfig
5
+ from pydantic import BaseModel
6
+
7
+ from intentkit.skills.cookiefun.base import CookieFunBaseTool, logger
8
+ from intentkit.skills.cookiefun.constants import DEFAULT_HEADERS, ENDPOINTS
9
+
10
+
11
+ class GetSectorsInput(BaseModel):
12
+ """Input for GetSectors tool."""
13
+
14
+ pass
15
+
16
+
17
+ class GetSectors(CookieFunBaseTool):
18
+ """Tool to get all available sectors from the CookieFun API."""
19
+
20
+ name: str = "cookiefun_get_sectors"
21
+ description: str = (
22
+ "Returns a list of all available sectors in the CookieFun system."
23
+ )
24
+ args_schema: Type[BaseModel] = GetSectorsInput
25
+
26
+ async def _arun(self, config: RunnableConfig, **kwargs) -> List[Dict[str, Any]]:
27
+ """
28
+ Get all available sectors from the CookieFun API.
29
+
30
+ Returns:
31
+ List of sector objects, each containing id, name, and other metadata.
32
+ """
33
+ logger.info("Getting sectors from CookieFun API")
34
+ try:
35
+ # Get API key
36
+ api_key = self.get_api_key(config)
37
+
38
+ if not api_key:
39
+ logger.error("No API key provided for CookieFun API")
40
+ return "Error: No API key provided for CookieFun API. Please configure the API key in the agent settings."
41
+
42
+ # Make API request
43
+ headers = {**DEFAULT_HEADERS, "x-api-key": api_key}
44
+
45
+ async with httpx.AsyncClient() as client:
46
+ response = await client.get(ENDPOINTS["sectors"], headers=headers)
47
+ logger.debug(
48
+ "Received response with status code: %d", response.status_code
49
+ )
50
+
51
+ response.raise_for_status()
52
+ data = response.json()
53
+
54
+ # Check different possible response structures
55
+ if data.get("success") and "ok" in data and "entries" in data["ok"]:
56
+ sectors = data["ok"]["entries"]
57
+ logger.info(
58
+ "Successfully retrieved %d sectors from entries field",
59
+ len(sectors),
60
+ )
61
+ return sectors
62
+ elif data.get("success") and "ok" in data and "sectors" in data["ok"]:
63
+ sectors = data["ok"]["sectors"]
64
+ logger.info("Successfully retrieved %d sectors", len(sectors))
65
+ return sectors
66
+ elif (
67
+ data.get("success")
68
+ and "ok" in data
69
+ and isinstance(data["ok"], list)
70
+ ):
71
+ # If "ok" is directly a list
72
+ sectors = data["ok"]
73
+ logger.info(
74
+ "Successfully retrieved %d sectors from ok list", len(sectors)
75
+ )
76
+ return sectors
77
+ elif data.get("success") and isinstance(data.get("sectors"), list):
78
+ # If sectors is at the top level
79
+ sectors = data["sectors"]
80
+ logger.info(
81
+ "Successfully retrieved %d sectors from top level", len(sectors)
82
+ )
83
+ return sectors
84
+ elif data.get("success") and isinstance(data.get("entries"), list):
85
+ # If entries is at the top level
86
+ sectors = data["entries"]
87
+ logger.info(
88
+ "Successfully retrieved %d sectors from entries top level",
89
+ len(sectors),
90
+ )
91
+ return sectors
92
+ elif "sectors" in data and isinstance(data["sectors"], list):
93
+ # If only sectors field exists
94
+ sectors = data["sectors"]
95
+ logger.info(
96
+ "Successfully retrieved %d sectors from direct field",
97
+ len(sectors),
98
+ )
99
+ return sectors
100
+ elif "entries" in data and isinstance(data["entries"], list):
101
+ # If only entries field exists
102
+ sectors = data["entries"]
103
+ logger.info(
104
+ "Successfully retrieved %d sectors from direct entries field",
105
+ len(sectors),
106
+ )
107
+ return sectors
108
+ else:
109
+ # If we can't find sectors in the expected structure, log the full response for debugging
110
+ logger.error(
111
+ "Could not find sectors in response structure. Full response: %s",
112
+ data,
113
+ )
114
+ error_msg = data.get(
115
+ "error", "Unknown error - check API response format"
116
+ )
117
+ logger.error("Error in API response: %s", error_msg)
118
+ return f"Error fetching sectors: {error_msg}"
119
+
120
+ except httpx.HTTPStatusError as e:
121
+ logger.error("HTTP error: %d - %s", e.response.status_code, e.response.text)
122
+ return f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
123
+ except httpx.RequestError as e:
124
+ logger.error("Request error: %s", str(e))
125
+ return f"Request error occurred: {str(e)}"
126
+ except Exception as e:
127
+ logger.exception("Unexpected error occurred")
128
+ return f"An unexpected error occurred: {str(e)}"
@@ -0,0 +1,155 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "CookieFun Skills",
5
+ "description": "Access Twitter/X analytics and insights using CookieFun API. Get data about accounts, tweets, followers, and trends across different industry sectors.",
6
+ "x-icon": "https://ai.service.crestal.dev/skills/cookiefun/cookiefun.png",
7
+ "x-tags": [
8
+ "Twitter",
9
+ "Social Media",
10
+ "Analytics",
11
+ "X"
12
+ ],
13
+ "x-nft-requirement": 10,
14
+ "properties": {
15
+ "enabled": {
16
+ "type": "boolean",
17
+ "title": "Enabled",
18
+ "description": "Toggle to enable or disable all CookieFun skills",
19
+ "default": false
20
+ },
21
+ "states": {
22
+ "type": "object",
23
+ "properties": {
24
+ "get_sectors": {
25
+ "type": "string",
26
+ "title": "Get Sectors",
27
+ "enum": [
28
+ "disabled",
29
+ "public",
30
+ "private"
31
+ ],
32
+ "x-enum-title": [
33
+ "Disabled",
34
+ "Agent Owner + All Users",
35
+ "Agent Owner Only"
36
+ ],
37
+ "description": "Retrieve a list of all available industry sectors in CookieFun, useful for exploring trending topics and categorization",
38
+ "default": "disabled"
39
+ },
40
+ "get_account_details": {
41
+ "type": "string",
42
+ "title": "Get Account Details",
43
+ "enum": [
44
+ "disabled",
45
+ "public",
46
+ "private"
47
+ ],
48
+ "x-enum-title": [
49
+ "Disabled",
50
+ "Agent Owner + All Users",
51
+ "Agent Owner Only"
52
+ ],
53
+ "description": "Fetch comprehensive metrics about any Twitter account including followers, engagement rates, impressions, and other analytics",
54
+ "default": "disabled"
55
+ },
56
+ "get_account_smart_followers": {
57
+ "type": "string",
58
+ "title": "Get Account Smart Followers",
59
+ "enum": [
60
+ "disabled",
61
+ "public",
62
+ "private"
63
+ ],
64
+ "x-enum-title": [
65
+ "Disabled",
66
+ "Agent Owner + All Users",
67
+ "Agent Owner Only"
68
+ ],
69
+ "description": "Identify the most valuable followers of any Twitter account based on influence, engagement, and reach metrics",
70
+ "default": "disabled"
71
+ },
72
+ "search_accounts": {
73
+ "type": "string",
74
+ "title": "Search Accounts",
75
+ "enum": [
76
+ "disabled",
77
+ "public",
78
+ "private"
79
+ ],
80
+ "x-enum-title": [
81
+ "Disabled",
82
+ "Agent Owner + All Users",
83
+ "Agent Owner Only"
84
+ ],
85
+ "description": "Find Twitter accounts posting about specific topics with filtering by engagement, impressions, and tweet types",
86
+ "default": "disabled"
87
+ },
88
+ "get_account_feed": {
89
+ "type": "string",
90
+ "title": "Get Account Feed",
91
+ "enum": [
92
+ "disabled",
93
+ "public",
94
+ "private"
95
+ ],
96
+ "x-enum-title": [
97
+ "Disabled",
98
+ "Agent Owner + All Users",
99
+ "Agent Owner Only"
100
+ ],
101
+ "description": "Access a Twitter account's feed with powerful filtering by date range, media content, tweet type, and sorting options",
102
+ "default": "disabled"
103
+ }
104
+ },
105
+ "description": "Configure access levels for each CookieFun skill - disabled, available to all users, or restricted to agent owner only"
106
+ },
107
+ "api_key_provider": {
108
+ "type": "string",
109
+ "title": "API Key Provider",
110
+ "description": "Choose whether to use a platform-provided API key or provide your own CookieFun API key",
111
+ "enum": [
112
+ "agent_owner"
113
+ ],
114
+ "x-enum-title": [
115
+ "Owner Provided"
116
+ ],
117
+ "default": "agent_owner"
118
+ }
119
+ },
120
+ "required": [
121
+ "states",
122
+ "enabled"
123
+ ],
124
+ "if": {
125
+ "properties": {
126
+ "api_key_provider": {
127
+ "const": "agent_owner"
128
+ }
129
+ }
130
+ },
131
+ "then": {
132
+ "properties": {
133
+ "api_key": {
134
+ "type": "string",
135
+ "title": "CookieFun API Key",
136
+ "description": "Your personal CookieFun API key, required when using Owner Provided option (sign up at cookie.fun)",
137
+ "x-sensitive": true,
138
+ "x-link": "[Get your API key](https://cookie.fun/)"
139
+ }
140
+ },
141
+ "if": {
142
+ "properties": {
143
+ "enabled": {
144
+ "const": true
145
+ }
146
+ }
147
+ },
148
+ "then": {
149
+ "required": [
150
+ "api_key"
151
+ ]
152
+ }
153
+ },
154
+ "additionalProperties": true
155
+ }
@@ -0,0 +1,225 @@
1
+ from enum import IntEnum
2
+ from typing import Any, Dict, List, Optional, Type, Union
3
+
4
+ import httpx
5
+ from langchain_core.runnables import RunnableConfig
6
+ from pydantic import BaseModel, Field
7
+
8
+ from intentkit.skills.cookiefun.base import CookieFunBaseTool, logger
9
+ from intentkit.skills.cookiefun.constants import DEFAULT_HEADERS, ENDPOINTS
10
+
11
+
12
+ class TweetType(IntEnum):
13
+ """Tweet type for filtering."""
14
+
15
+ Original = 0
16
+ Reply = 1
17
+ Quote = 2
18
+
19
+
20
+ class SortBy(IntEnum):
21
+ """Sort options for account search results."""
22
+
23
+ SmartEngagementPoints = 0
24
+ Impressions = 1
25
+ MatchingTweetsCount = 2
26
+
27
+
28
+ class SortOrder(IntEnum):
29
+ """Sort order options."""
30
+
31
+ Ascending = 0
32
+ Descending = 1
33
+
34
+
35
+ class SearchAccountsInput(BaseModel):
36
+ """Input for SearchAccounts tool."""
37
+
38
+ searchQuery: str = Field(
39
+ description="Search query to find Twitter accounts that authored tweets matching the criteria"
40
+ )
41
+
42
+ type: Optional[int] = Field(
43
+ default=None,
44
+ description="Type of tweets to search for: 0 for Original, 1 for Reply, 2 for Quote (leave empty for all types)",
45
+ )
46
+
47
+ sortBy: Optional[int] = Field(
48
+ default=None,
49
+ description="Sort by: 0 for SmartEngagementPoints, 1 for Impressions, 2 for MatchingTweetsCount",
50
+ )
51
+
52
+ sortOrder: Optional[int] = Field(
53
+ default=None,
54
+ description="Sort order: 0 for Ascending, 1 for Descending",
55
+ )
56
+
57
+
58
+ class SearchAccounts(CookieFunBaseTool):
59
+ """Tool to search for Twitter accounts based on tweet content."""
60
+
61
+ name: str = "cookiefun_search_accounts"
62
+ description: str = "Searches for Twitter accounts that authored tweets matching specified search criteria."
63
+ args_schema: Type[BaseModel] = SearchAccountsInput
64
+
65
+ async def _arun(
66
+ self,
67
+ config: RunnableConfig,
68
+ searchQuery: str,
69
+ type: Optional[int] = None,
70
+ sortBy: Optional[int] = None,
71
+ sortOrder: Optional[int] = None,
72
+ **kwargs,
73
+ ) -> Union[List[Dict[str, Any]], str]:
74
+ """
75
+ Search for Twitter accounts based on tweet content.
76
+
77
+ Args:
78
+ searchQuery: Search query to match tweet content
79
+ type: Type of tweets to search for (0=Original, 1=Reply, 2=Quote)
80
+ sortBy: Sort by field (0=SmartEngagementPoints, 1=Impressions, 2=MatchingTweetsCount)
81
+ sortOrder: Sort order (0=Ascending, 1=Descending)
82
+
83
+ Returns:
84
+ List of Twitter accounts matching the search criteria with metrics.
85
+ """
86
+ logger.info(
87
+ "Searching accounts with query=%s, type=%s, sortBy=%s, sortOrder=%s",
88
+ searchQuery,
89
+ type,
90
+ sortBy,
91
+ sortOrder,
92
+ )
93
+
94
+ if not searchQuery:
95
+ logger.error("No search query provided")
96
+ return "Error: searchQuery is required."
97
+
98
+ try:
99
+ # Get context to retrieve API key
100
+ api_key = self.get_api_key(config)
101
+
102
+ if not api_key:
103
+ logger.error("No API key provided for CookieFun API")
104
+ return "Error: No API key provided for CookieFun API. Please configure the API key in the agent settings."
105
+
106
+ # Prepare request payload
107
+ payload = {"searchQuery": searchQuery}
108
+
109
+ # Add optional parameters if provided
110
+ if type is not None:
111
+ payload["type"] = type
112
+ if sortBy is not None:
113
+ payload["sortBy"] = sortBy
114
+ if sortOrder is not None:
115
+ payload["sortOrder"] = sortOrder
116
+
117
+ # Make API request
118
+ headers = {**DEFAULT_HEADERS, "x-api-key": api_key}
119
+
120
+ async with httpx.AsyncClient() as client:
121
+ response = await client.post(
122
+ ENDPOINTS["search_accounts"], headers=headers, json=payload
123
+ )
124
+ logger.debug(
125
+ "Received response with status code: %d", response.status_code
126
+ )
127
+
128
+ response.raise_for_status()
129
+ data = response.json()
130
+
131
+ # Check different possible response structures
132
+ if data.get("success") and "ok" in data and "entries" in data["ok"]:
133
+ accounts = data["ok"]["entries"]
134
+ logger.info(
135
+ "Successfully retrieved %d matching accounts from entries field",
136
+ len(accounts),
137
+ )
138
+ return accounts
139
+ elif data.get("success") and "ok" in data and "accounts" in data["ok"]:
140
+ accounts = data["ok"]["accounts"]
141
+ logger.info(
142
+ "Successfully retrieved %d matching accounts", len(accounts)
143
+ )
144
+ return accounts
145
+ elif data.get("success") and "ok" in data and "results" in data["ok"]:
146
+ accounts = data["ok"]["results"]
147
+ logger.info(
148
+ "Successfully retrieved %d matching accounts from results field",
149
+ len(accounts),
150
+ )
151
+ return accounts
152
+ elif (
153
+ data.get("success")
154
+ and "ok" in data
155
+ and isinstance(data["ok"], list)
156
+ ):
157
+ accounts = data["ok"]
158
+ logger.info(
159
+ "Successfully retrieved %d matching accounts from ok list",
160
+ len(accounts),
161
+ )
162
+ return accounts
163
+ elif data.get("success") and isinstance(data.get("accounts"), list):
164
+ accounts = data["accounts"]
165
+ logger.info(
166
+ "Successfully retrieved %d matching accounts from top level accounts",
167
+ len(accounts),
168
+ )
169
+ return accounts
170
+ elif data.get("success") and isinstance(data.get("results"), list):
171
+ accounts = data["results"]
172
+ logger.info(
173
+ "Successfully retrieved %d matching accounts from top level results",
174
+ len(accounts),
175
+ )
176
+ return accounts
177
+ elif data.get("success") and isinstance(data.get("entries"), list):
178
+ accounts = data["entries"]
179
+ logger.info(
180
+ "Successfully retrieved %d matching accounts from top level entries",
181
+ len(accounts),
182
+ )
183
+ return accounts
184
+ elif "accounts" in data and isinstance(data["accounts"], list):
185
+ accounts = data["accounts"]
186
+ logger.info(
187
+ "Successfully retrieved %d matching accounts from direct accounts field",
188
+ len(accounts),
189
+ )
190
+ return accounts
191
+ elif "results" in data and isinstance(data["results"], list):
192
+ accounts = data["results"]
193
+ logger.info(
194
+ "Successfully retrieved %d matching accounts from direct results field",
195
+ len(accounts),
196
+ )
197
+ return accounts
198
+ elif "entries" in data and isinstance(data["entries"], list):
199
+ accounts = data["entries"]
200
+ logger.info(
201
+ "Successfully retrieved %d matching accounts from direct entries field",
202
+ len(accounts),
203
+ )
204
+ return accounts
205
+ else:
206
+ # If we can't find accounts in the expected structure, log the full response
207
+ logger.error(
208
+ "Could not find matching accounts in response structure. Full response: %s",
209
+ data,
210
+ )
211
+ error_msg = data.get(
212
+ "error", "Unknown error - check API response format"
213
+ )
214
+ logger.error("Error in API response: %s", error_msg)
215
+ return f"Error searching accounts: {error_msg}"
216
+
217
+ except httpx.HTTPStatusError as e:
218
+ logger.error("HTTP error: %d - %s", e.response.status_code, e.response.text)
219
+ return f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
220
+ except httpx.RequestError as e:
221
+ logger.error("Request error: %s", str(e))
222
+ return f"Request error occurred: {str(e)}"
223
+ except Exception as e:
224
+ logger.exception("Unexpected error occurred")
225
+ return f"An unexpected error occurred: {str(e)}"