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
intentkit/models/db.py ADDED
@@ -0,0 +1,120 @@
1
+ from contextlib import asynccontextmanager
2
+ from typing import Annotated, AsyncGenerator, Optional
3
+ from urllib.parse import quote_plus
4
+
5
+ from intentkit.models.db_mig import safe_migrate
6
+ from langgraph.checkpoint.memory import InMemorySaver
7
+ from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
8
+ from langgraph.types import Checkpointer
9
+ from psycopg_pool import AsyncConnectionPool
10
+ from pydantic import Field
11
+ from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
12
+
13
+ engine = None
14
+ _langgraph_checkpointer: Optional[Checkpointer] = None
15
+
16
+
17
+ async def init_db(
18
+ host: Optional[str],
19
+ username: Optional[str],
20
+ password: Optional[str],
21
+ dbname: Optional[str],
22
+ port: Annotated[Optional[str], Field(default="5432", description="Database port")],
23
+ auto_migrate: Annotated[
24
+ bool, Field(default=True, description="Whether to run migrations automatically")
25
+ ],
26
+ ) -> None:
27
+ """Initialize the database and handle schema updates.
28
+
29
+ Args:
30
+ host: Database host
31
+ username: Database username
32
+ password: Database password
33
+ dbname: Database name
34
+ port: Database port (default: 5432)
35
+ auto_migrate: Whether to run migrations automatically (default: True)
36
+ """
37
+ global engine, _langgraph_checkpointer
38
+ # Initialize psycopg pool and AsyncPostgresSaver if not already initialized
39
+ if _langgraph_checkpointer is None:
40
+ if host:
41
+ pool = AsyncConnectionPool(
42
+ conninfo=f"postgresql://{username}:{quote_plus(password)}@{host}:{port}/{dbname}",
43
+ min_size=3,
44
+ max_size=20,
45
+ timeout=60,
46
+ max_idle=30 * 60,
47
+ )
48
+ _langgraph_checkpointer = AsyncPostgresSaver(pool)
49
+ if auto_migrate:
50
+ await _langgraph_checkpointer.setup()
51
+ else:
52
+ _langgraph_checkpointer = InMemorySaver()
53
+ # Initialize SQLAlchemy engine with pool settings
54
+ if engine is None:
55
+ if host:
56
+ engine = create_async_engine(
57
+ f"postgresql+asyncpg://{username}:{quote_plus(password)}@{host}:{port}/{dbname}",
58
+ pool_size=20, # Increase pool size
59
+ max_overflow=30, # Increase max overflow
60
+ pool_timeout=60, # Increase timeout
61
+ pool_pre_ping=True, # Enable connection health checks
62
+ pool_recycle=3600, # Recycle connections after 1 hour
63
+ )
64
+ else:
65
+ engine = create_async_engine(
66
+ "sqlite+aiosqlite:///:memory:",
67
+ connect_args={"check_same_thread": False},
68
+ )
69
+ if auto_migrate:
70
+ await safe_migrate(engine)
71
+
72
+
73
+ async def get_db() -> AsyncGenerator[AsyncSession, None]:
74
+ async with AsyncSession(engine) as session:
75
+ yield session
76
+
77
+
78
+ @asynccontextmanager
79
+ async def get_session() -> AsyncSession:
80
+ """Get a database session using an async context manager.
81
+
82
+ This function is designed to be used with the 'async with' statement,
83
+ ensuring proper session cleanup.
84
+
85
+ Returns:
86
+ AsyncSession: A SQLAlchemy async session that will be automatically closed
87
+
88
+ Example:
89
+ ```python
90
+ async with get_session() as session:
91
+ # use session here
92
+ session.query(...)
93
+ # session is automatically closed
94
+ ```
95
+ """
96
+ session = AsyncSession(engine)
97
+ try:
98
+ yield session
99
+ finally:
100
+ await session.close()
101
+
102
+
103
+ def get_engine() -> AsyncEngine:
104
+ """Get the SQLAlchemy async engine.
105
+
106
+ Returns:
107
+ AsyncEngine: The SQLAlchemy async engine
108
+ """
109
+ return engine
110
+
111
+
112
+ def get_langgraph_checkpointer() -> Checkpointer:
113
+ """Get the AsyncPostgresSaver instance for langgraph.
114
+
115
+ Returns:
116
+ AsyncPostgresSaver: The AsyncPostgresSaver instance
117
+ """
118
+ if _langgraph_checkpointer is None:
119
+ raise RuntimeError("Database pool not initialized. Call init_db first.")
120
+ return _langgraph_checkpointer
@@ -0,0 +1,102 @@
1
+ """Database migration utilities."""
2
+
3
+ import logging
4
+ from typing import Callable
5
+
6
+ from intentkit.models.base import Base
7
+ from sqlalchemy import Column, MetaData, inspect, text
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ async def add_column_if_not_exists(
13
+ conn, dialect, table_name: str, column: Column
14
+ ) -> None:
15
+ """Add a column to a table if it doesn't exist.
16
+
17
+ Args:
18
+ conn: SQLAlchemy conn
19
+ table_name: Name of the table
20
+ column: Column to add
21
+ """
22
+
23
+ # Use run_sync to perform inspection on the connection
24
+ def _get_columns(connection):
25
+ inspector = inspect(connection)
26
+ return [c["name"] for c in inspector.get_columns(table_name)]
27
+
28
+ columns = await conn.run_sync(_get_columns)
29
+
30
+ if column.name not in columns:
31
+ # Build column definition
32
+ column_def = f"{column.name} {column.type.compile(dialect)}"
33
+
34
+ # Add DEFAULT if specified
35
+ if column.default is not None:
36
+ if hasattr(column.default, "arg"):
37
+ default_value = column.default.arg
38
+ if not isinstance(default_value, Callable):
39
+ if isinstance(default_value, bool):
40
+ default_value = str(default_value).lower()
41
+ elif isinstance(default_value, str):
42
+ default_value = f"'{default_value}'"
43
+ elif isinstance(default_value, (list, dict)):
44
+ default_value = "'{}'"
45
+ column_def += f" DEFAULT {default_value}"
46
+
47
+ # Execute ALTER TABLE
48
+ await conn.execute(text(f"ALTER TABLE {table_name} ADD COLUMN {column_def}"))
49
+ logger.info(f"Added column {column.name} to table {table_name}")
50
+
51
+
52
+ async def update_table_schema(conn, dialect, model_cls) -> None:
53
+ """Update table schema by adding missing columns from the model.
54
+
55
+ Args:
56
+ conn: SQLAlchemy conn
57
+ dialect: SQLAlchemy dialect
58
+ model_cls: SQLAlchemy model class to check for new columns
59
+ """
60
+ if not hasattr(model_cls, "__table__"):
61
+ return
62
+
63
+ table_name = model_cls.__tablename__
64
+ for name, column in model_cls.__table__.columns.items():
65
+ if name != "id": # Skip primary key
66
+ await add_column_if_not_exists(conn, dialect, table_name, column)
67
+
68
+
69
+ async def safe_migrate(engine) -> None:
70
+ """Safely migrate all SQLAlchemy models by adding new columns.
71
+
72
+ Args:
73
+ engine: SQLAlchemy engine
74
+ """
75
+ logger.info("Starting database schema migration")
76
+ dialect = engine.dialect
77
+
78
+ async with engine.begin() as conn:
79
+ try:
80
+ # Create tables if they don't exist
81
+ await conn.run_sync(Base.metadata.create_all)
82
+
83
+ # Get existing table metadata
84
+ metadata = MetaData()
85
+ await conn.run_sync(metadata.reflect)
86
+
87
+ # Update schema for all model classes
88
+ for mapper in Base.registry.mappers:
89
+ model_cls = mapper.class_
90
+ if hasattr(model_cls, "__tablename__"):
91
+ table_name = model_cls.__tablename__
92
+ if table_name in metadata.tables:
93
+ # We need a sync wrapper for the async update_table_schema
94
+ async def update_table_wrapper():
95
+ await update_table_schema(conn, dialect, model_cls)
96
+
97
+ await update_table_wrapper()
98
+ except Exception as e:
99
+ logger.error(f"Error updating database schema: {str(e)}")
100
+ raise
101
+
102
+ logger.info("Database schema updated successfully")
@@ -0,0 +1,347 @@
1
+ """Agent Generation Log Model.
2
+
3
+ This module defines the database models for logging agent generation operations,
4
+ including token usage, prompts, AI responses, and generation metadata.
5
+ """
6
+
7
+ from datetime import datetime, timezone
8
+ from typing import Annotated, Optional
9
+
10
+ from epyxid import XID
11
+ from intentkit.models.base import Base
12
+ from pydantic import BaseModel, ConfigDict, Field
13
+ from sqlalchemy import (
14
+ Boolean,
15
+ Column,
16
+ DateTime,
17
+ Integer,
18
+ String,
19
+ Text,
20
+ func,
21
+ select,
22
+ )
23
+ from sqlalchemy.dialects.postgresql import JSON, JSONB
24
+ from sqlalchemy.ext.asyncio import AsyncSession
25
+
26
+
27
+ class AgentGenerationLogTable(Base):
28
+ """Agent generation log database table model."""
29
+
30
+ __tablename__ = "agent_generation_logs"
31
+
32
+ id = Column(
33
+ String,
34
+ primary_key=True,
35
+ )
36
+ user_id = Column(
37
+ String,
38
+ nullable=True,
39
+ )
40
+ prompt = Column(
41
+ Text,
42
+ nullable=False,
43
+ )
44
+ existing_agent_id = Column(
45
+ String,
46
+ nullable=True,
47
+ )
48
+ is_update = Column(
49
+ Boolean,
50
+ default=False,
51
+ nullable=False,
52
+ )
53
+ generated_agent_schema = Column(
54
+ JSON().with_variant(JSONB(), "postgresql"),
55
+ nullable=True,
56
+ )
57
+ identified_skills = Column(
58
+ JSON().with_variant(JSONB(), "postgresql"),
59
+ nullable=True,
60
+ )
61
+ # LLM API response data
62
+ llm_model = Column(
63
+ String,
64
+ nullable=True,
65
+ )
66
+ total_tokens = Column(
67
+ Integer,
68
+ default=0,
69
+ )
70
+ input_tokens = Column(
71
+ Integer,
72
+ default=0,
73
+ )
74
+ cached_input_tokens = Column(
75
+ Integer,
76
+ default=0,
77
+ )
78
+ output_tokens = Column(
79
+ Integer,
80
+ default=0,
81
+ )
82
+ input_tokens_details = Column(
83
+ JSON().with_variant(JSONB(), "postgresql"),
84
+ nullable=True,
85
+ )
86
+ completion_tokens_details = Column(
87
+ JSON().with_variant(JSONB(), "postgresql"),
88
+ nullable=True,
89
+ )
90
+ # Performance metrics
91
+ generation_time_ms = Column(
92
+ Integer,
93
+ nullable=True,
94
+ )
95
+ retry_count = Column(
96
+ Integer,
97
+ default=0,
98
+ )
99
+ validation_errors = Column(
100
+ JSON().with_variant(JSONB(), "postgresql"),
101
+ nullable=True,
102
+ )
103
+ # Status and results
104
+ success = Column(
105
+ Boolean,
106
+ default=False,
107
+ nullable=False,
108
+ )
109
+ error_message = Column(
110
+ Text,
111
+ nullable=True,
112
+ )
113
+ # Timestamps
114
+ created_at = Column(
115
+ DateTime(timezone=True),
116
+ nullable=False,
117
+ server_default=func.now(),
118
+ )
119
+ completed_at = Column(
120
+ DateTime(timezone=True),
121
+ nullable=True,
122
+ )
123
+
124
+
125
+ class AgentGenerationLogCreate(BaseModel):
126
+ """Model for creating agent generation log entries."""
127
+
128
+ model_config = ConfigDict(
129
+ use_enum_values=True,
130
+ from_attributes=True,
131
+ )
132
+
133
+ id: Annotated[
134
+ str,
135
+ Field(
136
+ default_factory=lambda: str(XID()),
137
+ description="Unique identifier for the generation log",
138
+ ),
139
+ ]
140
+ user_id: Optional[str] = Field(
141
+ None,
142
+ description="User ID who initiated the generation",
143
+ )
144
+ prompt: str = Field(
145
+ ...,
146
+ description="The original prompt used for generation",
147
+ )
148
+ existing_agent_id: Optional[str] = Field(
149
+ None,
150
+ description="ID of existing agent if this is an update operation",
151
+ )
152
+ is_update: bool = Field(
153
+ False,
154
+ description="Whether this is an update to existing agent",
155
+ )
156
+
157
+
158
+ class AgentGenerationLog(BaseModel):
159
+ """Agent generation log model."""
160
+
161
+ model_config = ConfigDict(
162
+ use_enum_values=True,
163
+ from_attributes=True,
164
+ )
165
+
166
+ id: str
167
+ user_id: Optional[str] = None
168
+ prompt: str
169
+ existing_agent_id: Optional[str] = None
170
+ is_update: bool = False
171
+ generated_agent_schema: Optional[dict] = None
172
+ identified_skills: Optional[dict] = None
173
+ llm_model: Optional[str] = None
174
+ total_tokens: int = 0
175
+ input_tokens: int = 0
176
+ cached_input_tokens: int = 0
177
+ output_tokens: int = 0
178
+ input_tokens_details: Optional[dict] = None
179
+ completion_tokens_details: Optional[dict] = None
180
+ generation_time_ms: Optional[int] = None
181
+ retry_count: int = 0
182
+ validation_errors: Optional[dict] = None
183
+ success: bool = False
184
+ error_message: Optional[str] = None
185
+ created_at: datetime
186
+ completed_at: Optional[datetime] = None
187
+
188
+ @classmethod
189
+ async def create(
190
+ cls,
191
+ session: AsyncSession,
192
+ log_data: AgentGenerationLogCreate,
193
+ ) -> "AgentGenerationLog":
194
+ """Create a new agent generation log entry.
195
+
196
+ Args:
197
+ session: Database session
198
+ log_data: Log data to create
199
+
200
+ Returns:
201
+ Created log instance
202
+ """
203
+ # Create database record
204
+ log_record = AgentGenerationLogTable(
205
+ id=log_data.id,
206
+ user_id=log_data.user_id,
207
+ prompt=log_data.prompt,
208
+ existing_agent_id=log_data.existing_agent_id,
209
+ is_update=log_data.is_update,
210
+ )
211
+
212
+ session.add(log_record)
213
+ await session.commit()
214
+ await session.refresh(log_record)
215
+
216
+ return cls.model_validate(log_record)
217
+
218
+ async def update_completion(
219
+ self,
220
+ session: AsyncSession,
221
+ generated_agent_schema: Optional[dict] = None,
222
+ identified_skills: Optional[dict] = None,
223
+ llm_model: Optional[str] = None,
224
+ total_tokens: int = 0,
225
+ input_tokens: int = 0,
226
+ cached_input_tokens: int = 0,
227
+ output_tokens: int = 0,
228
+ input_tokens_details: Optional[dict] = None,
229
+ completion_tokens_details: Optional[dict] = None,
230
+ generation_time_ms: Optional[int] = None,
231
+ retry_count: int = 0,
232
+ validation_errors: Optional[dict] = None,
233
+ success: bool = False,
234
+ error_message: Optional[str] = None,
235
+ ) -> None:
236
+ """Update the log entry with completion data.
237
+
238
+ Args:
239
+ session: Database session
240
+ generated_agent_schema: The generated agent schema
241
+ identified_skills: Skills identified during generation
242
+ llm_model: LLM model used
243
+ total_tokens: Total tokens used
244
+ input_tokens: Input tokens used
245
+ cached_input_tokens: Cached input tokens used (for cost calculation)
246
+ output_tokens: Output tokens used
247
+ input_tokens_details: Detailed input token breakdown
248
+ completion_tokens_details: Detailed completion token breakdown
249
+ generation_time_ms: Generation time in milliseconds
250
+ retry_count: Number of retries attempted
251
+ validation_errors: Any validation errors encountered
252
+ success: Whether generation was successful
253
+ error_message: Error message if generation failed
254
+ """
255
+ # Get the database record
256
+ log_record = await session.get(AgentGenerationLogTable, self.id)
257
+ if not log_record:
258
+ return
259
+
260
+ # Update fields
261
+ log_record.generated_agent_schema = generated_agent_schema
262
+ log_record.identified_skills = identified_skills
263
+ log_record.llm_model = llm_model
264
+ log_record.total_tokens = total_tokens
265
+ log_record.input_tokens = input_tokens
266
+ log_record.cached_input_tokens = cached_input_tokens
267
+ log_record.output_tokens = output_tokens
268
+ log_record.input_tokens_details = input_tokens_details
269
+ log_record.completion_tokens_details = completion_tokens_details
270
+ log_record.generation_time_ms = generation_time_ms
271
+ log_record.retry_count = retry_count
272
+ log_record.validation_errors = validation_errors
273
+ log_record.success = success
274
+ log_record.error_message = error_message
275
+ log_record.completed_at = datetime.now(timezone.utc)
276
+
277
+ session.add(log_record)
278
+ await session.commit()
279
+ await session.refresh(log_record)
280
+
281
+ # Update this instance
282
+ self.generated_agent_schema = log_record.generated_agent_schema
283
+ self.identified_skills = log_record.identified_skills
284
+ self.llm_model = log_record.llm_model
285
+ self.total_tokens = log_record.total_tokens
286
+ self.input_tokens = log_record.input_tokens
287
+ self.cached_input_tokens = log_record.cached_input_tokens
288
+ self.output_tokens = log_record.output_tokens
289
+ self.input_tokens_details = log_record.input_tokens_details
290
+ self.completion_tokens_details = log_record.completion_tokens_details
291
+ self.generation_time_ms = log_record.generation_time_ms
292
+ self.retry_count = log_record.retry_count
293
+ self.validation_errors = log_record.validation_errors
294
+ self.success = log_record.success
295
+ self.error_message = log_record.error_message
296
+ self.completed_at = log_record.completed_at
297
+
298
+ @classmethod
299
+ async def get_by_id(
300
+ cls,
301
+ session: AsyncSession,
302
+ log_id: str,
303
+ ) -> Optional["AgentGenerationLog"]:
304
+ """Get an agent generation log by ID.
305
+
306
+ Args:
307
+ session: Database session
308
+ log_id: Log ID
309
+
310
+ Returns:
311
+ Log instance if found, None otherwise
312
+ """
313
+ result = await session.execute(
314
+ select(AgentGenerationLogTable).where(AgentGenerationLogTable.id == log_id)
315
+ )
316
+ log_record = result.scalar_one_or_none()
317
+
318
+ if log_record:
319
+ return cls.model_validate(log_record)
320
+ return None
321
+
322
+ @classmethod
323
+ async def get_by_user(
324
+ cls,
325
+ session: AsyncSession,
326
+ user_id: str,
327
+ limit: int = 50,
328
+ ) -> list["AgentGenerationLog"]:
329
+ """Get agent generation logs for a user.
330
+
331
+ Args:
332
+ session: Database session
333
+ user_id: User ID
334
+ limit: Maximum number of logs to return
335
+
336
+ Returns:
337
+ List of log instances
338
+ """
339
+ result = await session.execute(
340
+ select(AgentGenerationLogTable)
341
+ .where(AgentGenerationLogTable.user_id == user_id)
342
+ .order_by(AgentGenerationLogTable.created_at.desc())
343
+ .limit(limit)
344
+ )
345
+ log_records = result.scalars().all()
346
+
347
+ return [cls.model_validate(record) for record in log_records]