intentkit 0.8.6.dev2__py3-none-any.whl → 0.8.17__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (312) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/agent.py +4 -5
  3. intentkit/abstracts/engine.py +5 -5
  4. intentkit/abstracts/graph.py +10 -5
  5. intentkit/abstracts/skill.py +6 -144
  6. intentkit/abstracts/twitter.py +4 -5
  7. intentkit/clients/__init__.py +3 -2
  8. intentkit/clients/cdp.py +53 -92
  9. intentkit/clients/twitter.py +56 -57
  10. intentkit/clients/web3.py +1 -3
  11. intentkit/config/config.py +5 -0
  12. intentkit/core/agent.py +16 -388
  13. intentkit/core/asset.py +64 -18
  14. intentkit/core/client.py +1 -1
  15. intentkit/core/credit.py +19 -20
  16. intentkit/core/engine.py +26 -11
  17. intentkit/core/node.py +2 -1
  18. intentkit/core/prompt.py +53 -15
  19. intentkit/core/scheduler.py +9 -9
  20. intentkit/core/statistics.py +6 -7
  21. intentkit/models/agent.py +256 -176
  22. intentkit/models/agent_data.py +62 -36
  23. intentkit/models/agent_schema.json +6 -9
  24. intentkit/models/app_setting.py +6 -6
  25. intentkit/models/chat.py +28 -24
  26. intentkit/models/conversation.py +8 -8
  27. intentkit/models/credit.py +62 -64
  28. intentkit/models/db.py +8 -7
  29. intentkit/models/db_mig.py +2 -2
  30. intentkit/models/llm.csv +15 -12
  31. intentkit/models/llm.py +18 -16
  32. intentkit/models/redis.py +2 -3
  33. intentkit/models/skill.py +62 -66
  34. intentkit/models/skills.csv +30 -26
  35. intentkit/models/user.py +46 -21
  36. intentkit/skills/acolyt/__init__.py +2 -9
  37. intentkit/skills/acolyt/ask.py +3 -4
  38. intentkit/skills/acolyt/base.py +4 -9
  39. intentkit/skills/aixbt/__init__.py +2 -13
  40. intentkit/skills/aixbt/base.py +1 -7
  41. intentkit/skills/aixbt/projects.py +14 -15
  42. intentkit/skills/allora/__init__.py +2 -9
  43. intentkit/skills/allora/base.py +4 -9
  44. intentkit/skills/allora/price.py +3 -4
  45. intentkit/skills/base.py +175 -52
  46. intentkit/skills/basename/__init__.py +4 -8
  47. intentkit/skills/carv/__init__.py +115 -121
  48. intentkit/skills/carv/base.py +184 -185
  49. intentkit/skills/carv/fetch_news.py +3 -3
  50. intentkit/skills/carv/onchain_query.py +4 -4
  51. intentkit/skills/carv/token_info_and_price.py +5 -5
  52. intentkit/skills/casino/__init__.py +4 -15
  53. intentkit/skills/casino/base.py +1 -7
  54. intentkit/skills/casino/deck_draw.py +5 -8
  55. intentkit/skills/casino/deck_shuffle.py +6 -6
  56. intentkit/skills/casino/dice_roll.py +2 -4
  57. intentkit/skills/cdp/__init__.py +3 -10
  58. intentkit/skills/cdp/base.py +1 -7
  59. intentkit/skills/cdp/schema.json +1 -17
  60. intentkit/skills/chainlist/__init__.py +2 -7
  61. intentkit/skills/chainlist/base.py +1 -7
  62. intentkit/skills/chainlist/chain_lookup.py +18 -18
  63. intentkit/skills/common/__init__.py +2 -9
  64. intentkit/skills/common/base.py +1 -7
  65. intentkit/skills/common/current_time.py +1 -2
  66. intentkit/skills/cookiefun/__init__.py +6 -9
  67. intentkit/skills/cookiefun/base.py +2 -7
  68. intentkit/skills/cookiefun/get_account_details.py +7 -7
  69. intentkit/skills/cookiefun/get_account_feed.py +19 -19
  70. intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
  71. intentkit/skills/cookiefun/get_sectors.py +3 -3
  72. intentkit/skills/cookiefun/search_accounts.py +9 -9
  73. intentkit/skills/cryptocompare/__init__.py +7 -24
  74. intentkit/skills/cryptocompare/api.py +2 -3
  75. intentkit/skills/cryptocompare/base.py +10 -24
  76. intentkit/skills/cryptocompare/fetch_news.py +4 -5
  77. intentkit/skills/cryptocompare/fetch_price.py +6 -7
  78. intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
  79. intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
  80. intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
  81. intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
  82. intentkit/skills/cryptopanic/__init__.py +7 -10
  83. intentkit/skills/cryptopanic/base.py +51 -55
  84. intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
  85. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
  86. intentkit/skills/dapplooker/__init__.py +2 -9
  87. intentkit/skills/dapplooker/base.py +4 -9
  88. intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
  89. intentkit/skills/defillama/__init__.py +24 -74
  90. intentkit/skills/defillama/api.py +6 -9
  91. intentkit/skills/defillama/base.py +8 -19
  92. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
  93. intentkit/skills/defillama/coins/fetch_block.py +6 -8
  94. intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
  95. intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
  96. intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
  97. intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
  98. intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
  99. intentkit/skills/defillama/config/chains.py +1 -3
  100. intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
  101. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
  102. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
  103. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
  104. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
  105. intentkit/skills/defillama/tests/api_integration.test.py +1 -1
  106. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
  107. intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
  108. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
  109. intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
  110. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
  111. intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
  112. intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
  113. intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
  114. intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
  115. intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
  116. intentkit/skills/defillama/yields/fetch_pools.py +26 -30
  117. intentkit/skills/dexscreener/__init__.py +97 -102
  118. intentkit/skills/dexscreener/base.py +125 -130
  119. intentkit/skills/dexscreener/get_pair_info.py +4 -5
  120. intentkit/skills/dexscreener/get_token_pairs.py +4 -5
  121. intentkit/skills/dexscreener/get_tokens_info.py +7 -8
  122. intentkit/skills/dexscreener/model/search_token_response.py +80 -82
  123. intentkit/skills/dexscreener/search_token.py +182 -184
  124. intentkit/skills/dexscreener/utils.py +15 -14
  125. intentkit/skills/dune_analytics/__init__.py +7 -9
  126. intentkit/skills/dune_analytics/base.py +48 -52
  127. intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
  128. intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
  129. intentkit/skills/elfa/__init__.py +5 -18
  130. intentkit/skills/elfa/base.py +10 -14
  131. intentkit/skills/elfa/mention.py +19 -21
  132. intentkit/skills/elfa/stats.py +4 -4
  133. intentkit/skills/elfa/tokens.py +12 -12
  134. intentkit/skills/elfa/utils.py +26 -28
  135. intentkit/skills/enso/__init__.py +11 -31
  136. intentkit/skills/enso/base.py +9 -15
  137. intentkit/skills/enso/best_yield.py +5 -7
  138. intentkit/skills/enso/networks.py +3 -9
  139. intentkit/skills/enso/prices.py +2 -4
  140. intentkit/skills/enso/route.py +6 -12
  141. intentkit/skills/enso/tokens.py +4 -16
  142. intentkit/skills/enso/wallet.py +6 -6
  143. intentkit/skills/erc20/__init__.py +5 -11
  144. intentkit/skills/erc721/__init__.py +5 -9
  145. intentkit/skills/firecrawl/__init__.py +5 -18
  146. intentkit/skills/firecrawl/base.py +4 -9
  147. intentkit/skills/firecrawl/clear.py +4 -8
  148. intentkit/skills/firecrawl/crawl.py +19 -19
  149. intentkit/skills/firecrawl/query.py +4 -3
  150. intentkit/skills/firecrawl/scrape.py +17 -22
  151. intentkit/skills/firecrawl/utils.py +50 -42
  152. intentkit/skills/github/__init__.py +2 -7
  153. intentkit/skills/github/base.py +1 -7
  154. intentkit/skills/github/github_search.py +1 -2
  155. intentkit/skills/heurist/__init__.py +8 -27
  156. intentkit/skills/heurist/base.py +4 -9
  157. intentkit/skills/heurist/image_generation_animagine_xl.py +12 -13
  158. intentkit/skills/heurist/image_generation_arthemy_comics.py +12 -13
  159. intentkit/skills/heurist/image_generation_arthemy_real.py +12 -13
  160. intentkit/skills/heurist/image_generation_braindance.py +12 -13
  161. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +12 -13
  162. intentkit/skills/heurist/image_generation_flux_1_dev.py +12 -13
  163. intentkit/skills/heurist/image_generation_sdxl.py +12 -13
  164. intentkit/skills/http/__init__.py +4 -15
  165. intentkit/skills/http/base.py +1 -7
  166. intentkit/skills/http/get.py +21 -16
  167. intentkit/skills/http/post.py +23 -18
  168. intentkit/skills/http/put.py +23 -18
  169. intentkit/skills/lifi/__init__.py +5 -10
  170. intentkit/skills/lifi/base.py +1 -7
  171. intentkit/skills/lifi/token_execute.py +14 -17
  172. intentkit/skills/lifi/token_quote.py +7 -9
  173. intentkit/skills/lifi/utils.py +16 -16
  174. intentkit/skills/moralis/__init__.py +6 -10
  175. intentkit/skills/moralis/api.py +6 -7
  176. intentkit/skills/moralis/base.py +5 -10
  177. intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
  178. intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
  179. intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
  180. intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
  181. intentkit/skills/morpho/__init__.py +5 -9
  182. intentkit/skills/nation/__init__.py +4 -9
  183. intentkit/skills/nation/base.py +5 -10
  184. intentkit/skills/nation/nft_check.py +3 -4
  185. intentkit/skills/onchain.py +23 -0
  186. intentkit/skills/openai/__init__.py +17 -18
  187. intentkit/skills/openai/base.py +10 -14
  188. intentkit/skills/openai/dalle_image_generation.py +3 -8
  189. intentkit/skills/openai/gpt_avatar_generator.py +102 -0
  190. intentkit/skills/openai/gpt_image_generation.py +4 -8
  191. intentkit/skills/openai/gpt_image_mini_generator.py +91 -0
  192. intentkit/skills/openai/gpt_image_to_image.py +4 -8
  193. intentkit/skills/openai/image_to_text.py +3 -7
  194. intentkit/skills/openai/schema.json +32 -0
  195. intentkit/skills/portfolio/__init__.py +11 -35
  196. intentkit/skills/portfolio/base.py +33 -19
  197. intentkit/skills/portfolio/token_balances.py +21 -21
  198. intentkit/skills/portfolio/wallet_approvals.py +17 -18
  199. intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
  200. intentkit/skills/portfolio/wallet_history.py +31 -31
  201. intentkit/skills/portfolio/wallet_net_worth.py +13 -13
  202. intentkit/skills/portfolio/wallet_nfts.py +19 -19
  203. intentkit/skills/portfolio/wallet_profitability.py +18 -18
  204. intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
  205. intentkit/skills/portfolio/wallet_stats.py +3 -3
  206. intentkit/skills/portfolio/wallet_swaps.py +19 -19
  207. intentkit/skills/pyth/__init__.py +4 -10
  208. intentkit/skills/skills.toml +4 -0
  209. intentkit/skills/slack/__init__.py +5 -17
  210. intentkit/skills/slack/base.py +3 -9
  211. intentkit/skills/slack/get_channel.py +8 -8
  212. intentkit/skills/slack/get_message.py +9 -9
  213. intentkit/skills/slack/schedule_message.py +5 -5
  214. intentkit/skills/slack/send_message.py +3 -5
  215. intentkit/skills/supabase/__init__.py +7 -23
  216. intentkit/skills/supabase/base.py +1 -7
  217. intentkit/skills/supabase/delete_data.py +4 -4
  218. intentkit/skills/supabase/fetch_data.py +12 -12
  219. intentkit/skills/supabase/insert_data.py +4 -4
  220. intentkit/skills/supabase/invoke_function.py +6 -6
  221. intentkit/skills/supabase/update_data.py +6 -6
  222. intentkit/skills/supabase/upsert_data.py +4 -4
  223. intentkit/skills/superfluid/__init__.py +5 -9
  224. intentkit/skills/system/__init__.py +7 -24
  225. intentkit/skills/system/add_autonomous_task.py +10 -12
  226. intentkit/skills/system/delete_autonomous_task.py +2 -2
  227. intentkit/skills/system/edit_autonomous_task.py +14 -18
  228. intentkit/skills/system/list_autonomous_tasks.py +3 -5
  229. intentkit/skills/system/read_agent_api_key.py +6 -4
  230. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  231. intentkit/skills/tavily/__init__.py +3 -12
  232. intentkit/skills/tavily/base.py +4 -9
  233. intentkit/skills/tavily/tavily_extract.py +2 -4
  234. intentkit/skills/tavily/tavily_search.py +4 -6
  235. intentkit/skills/token/__init__.py +5 -10
  236. intentkit/skills/token/base.py +7 -11
  237. intentkit/skills/token/erc20_transfers.py +19 -19
  238. intentkit/skills/token/token_analytics.py +3 -3
  239. intentkit/skills/token/token_price.py +13 -13
  240. intentkit/skills/token/token_search.py +9 -9
  241. intentkit/skills/twitter/__init__.py +11 -35
  242. intentkit/skills/twitter/base.py +22 -34
  243. intentkit/skills/twitter/follow_user.py +2 -6
  244. intentkit/skills/twitter/get_mentions.py +5 -12
  245. intentkit/skills/twitter/get_timeline.py +4 -12
  246. intentkit/skills/twitter/get_user_by_username.py +2 -6
  247. intentkit/skills/twitter/get_user_tweets.py +5 -13
  248. intentkit/skills/twitter/like_tweet.py +2 -6
  249. intentkit/skills/twitter/post_tweet.py +6 -9
  250. intentkit/skills/twitter/reply_tweet.py +6 -9
  251. intentkit/skills/twitter/retweet.py +2 -6
  252. intentkit/skills/twitter/search_tweets.py +4 -12
  253. intentkit/skills/unrealspeech/__init__.py +2 -7
  254. intentkit/skills/unrealspeech/base.py +2 -8
  255. intentkit/skills/unrealspeech/text_to_speech.py +8 -8
  256. intentkit/skills/venice_audio/__init__.py +98 -106
  257. intentkit/skills/venice_audio/base.py +117 -121
  258. intentkit/skills/venice_audio/input.py +41 -41
  259. intentkit/skills/venice_audio/venice_audio.py +7 -11
  260. intentkit/skills/venice_image/__init__.py +147 -154
  261. intentkit/skills/venice_image/api.py +138 -138
  262. intentkit/skills/venice_image/base.py +185 -192
  263. intentkit/skills/venice_image/config.py +33 -35
  264. intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
  265. intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
  266. intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
  267. intentkit/skills/venice_image/image_generation/image_generation_base.py +9 -9
  268. intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
  269. intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
  270. intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
  271. intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
  272. intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
  273. intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
  274. intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
  275. intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
  276. intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
  277. intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
  278. intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
  279. intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
  280. intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
  281. intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
  282. intentkit/skills/venice_image/utils.py +77 -78
  283. intentkit/skills/web_scraper/__init__.py +5 -18
  284. intentkit/skills/web_scraper/base.py +21 -7
  285. intentkit/skills/web_scraper/document_indexer.py +7 -6
  286. intentkit/skills/web_scraper/scrape_and_index.py +15 -15
  287. intentkit/skills/web_scraper/utils.py +62 -63
  288. intentkit/skills/web_scraper/website_indexer.py +17 -19
  289. intentkit/skills/weth/__init__.py +5 -11
  290. intentkit/skills/wow/__init__.py +5 -11
  291. intentkit/skills/x402/__init__.py +61 -0
  292. intentkit/skills/x402/ask_agent.py +98 -0
  293. intentkit/skills/x402/base.py +99 -0
  294. intentkit/skills/x402/http_request.py +117 -0
  295. intentkit/skills/x402/schema.json +45 -0
  296. intentkit/skills/x402/x402.webp +0 -0
  297. intentkit/skills/xmtp/__init__.py +4 -15
  298. intentkit/skills/xmtp/base.py +5 -5
  299. intentkit/skills/xmtp/price.py +6 -6
  300. intentkit/skills/xmtp/swap.py +6 -8
  301. intentkit/skills/xmtp/transfer.py +4 -6
  302. intentkit/utils/error.py +2 -2
  303. intentkit/utils/logging.py +2 -4
  304. intentkit/utils/s3.py +8 -9
  305. intentkit/utils/schema.py +100 -0
  306. intentkit/utils/slack_alert.py +7 -8
  307. {intentkit-0.8.6.dev2.dist-info → intentkit-0.8.17.dist-info}/METADATA +3 -4
  308. intentkit-0.8.17.dist-info/RECORD +466 -0
  309. intentkit/models/generator.py +0 -347
  310. intentkit-0.8.6.dev2.dist-info/RECORD +0 -457
  311. {intentkit-0.8.6.dev2.dist-info → intentkit-0.8.17.dist-info}/WHEEL +0 -0
  312. {intentkit-0.8.6.dev2.dist-info → intentkit-0.8.17.dist-info}/licenses/LICENSE +0 -0
intentkit/models/skill.py CHANGED
@@ -1,10 +1,12 @@
1
+ from __future__ import annotations
2
+
1
3
  import csv
2
4
  import json
3
5
  import logging
4
- from datetime import datetime, timezone
6
+ from datetime import UTC, datetime
5
7
  from decimal import Decimal
6
8
  from pathlib import Path
7
- from typing import Annotated, Any, Dict, Optional
9
+ from typing import Annotated, Any
8
10
 
9
11
  from intentkit.models.base import Base
10
12
  from intentkit.models.db import get_session
@@ -46,7 +48,7 @@ class AgentSkillDataTable(Base):
46
48
  DateTime(timezone=True),
47
49
  nullable=False,
48
50
  server_default=func.now(),
49
- onupdate=lambda: datetime.now(timezone.utc),
51
+ onupdate=lambda: datetime.now(UTC),
50
52
  )
51
53
 
52
54
 
@@ -58,7 +60,7 @@ class AgentSkillDataCreate(BaseModel):
58
60
  agent_id: Annotated[str, Field(description="ID of the agent this data belongs to")]
59
61
  skill: Annotated[str, Field(description="Name of the skill this data is for")]
60
62
  key: Annotated[str, Field(description="Key for this specific piece of data")]
61
- data: Annotated[Dict[str, Any], Field(description="JSON data stored for this key")]
63
+ data: Annotated[dict[str, Any], Field(description="JSON data stored for this key")]
62
64
 
63
65
  async def save(self) -> "AgentSkillData":
64
66
  """Save or update skill data.
@@ -157,7 +159,7 @@ class AgentSkillData(AgentSkillDataCreate):
157
159
  return result or 0
158
160
 
159
161
  @classmethod
160
- async def get(cls, agent_id: str, skill: str, key: str) -> Optional[dict]:
162
+ async def get(cls, agent_id: str, skill: str, key: str) -> dict | None:
161
163
  """Get skill data for an agent.
162
164
 
163
165
  Args:
@@ -213,12 +215,12 @@ class AgentSkillData(AgentSkillDataCreate):
213
215
  await db.commit()
214
216
 
215
217
 
216
- class ThreadSkillDataTable(Base):
217
- """Database table model for storing skill-specific data for threads."""
218
+ class ChatSkillDataTable(Base):
219
+ """Database table model for storing skill-specific data for chats."""
218
220
 
219
- __tablename__ = "thread_skill_data"
221
+ __tablename__ = "chat_skill_data"
220
222
 
221
- thread_id = Column(String, primary_key=True)
223
+ chat_id = Column(String, primary_key=True)
222
224
  skill = Column(String, primary_key=True)
223
225
  key = Column(String, primary_key=True)
224
226
  agent_id = Column(String, nullable=False)
@@ -232,35 +234,33 @@ class ThreadSkillDataTable(Base):
232
234
  DateTime(timezone=True),
233
235
  nullable=False,
234
236
  server_default=func.now(),
235
- onupdate=lambda: datetime.now(timezone.utc),
237
+ onupdate=lambda: datetime.now(UTC),
236
238
  )
237
239
 
238
240
 
239
- class ThreadSkillDataCreate(BaseModel):
240
- """Base model for creating thread skill data records."""
241
+ class ChatSkillDataCreate(BaseModel):
242
+ """Base model for creating chat skill data records."""
241
243
 
242
244
  model_config = ConfigDict(from_attributes=True)
243
245
 
244
- thread_id: Annotated[
245
- str, Field(description="ID of the thread this data belongs to")
246
- ]
246
+ chat_id: Annotated[str, Field(description="ID of the chat this data belongs to")]
247
247
  skill: Annotated[str, Field(description="Name of the skill this data is for")]
248
248
  key: Annotated[str, Field(description="Key for this specific piece of data")]
249
- agent_id: Annotated[str, Field(description="ID of the agent that owns this thread")]
250
- data: Annotated[Dict[str, Any], Field(description="JSON data stored for this key")]
249
+ agent_id: Annotated[str, Field(description="ID of the agent that owns this chat")]
250
+ data: Annotated[dict[str, Any], Field(description="JSON data stored for this key")]
251
251
 
252
- async def save(self) -> "ThreadSkillData":
252
+ async def save(self) -> "ChatSkillData":
253
253
  """Save or update skill data.
254
254
 
255
255
  Returns:
256
- ThreadSkillData: The saved thread skill data instance
256
+ ChatSkillData: The saved chat skill data instance
257
257
  """
258
258
  async with get_session() as db:
259
259
  record = await db.scalar(
260
- select(ThreadSkillDataTable).where(
261
- ThreadSkillDataTable.thread_id == self.thread_id,
262
- ThreadSkillDataTable.skill == self.skill,
263
- ThreadSkillDataTable.key == self.key,
260
+ select(ChatSkillDataTable).where(
261
+ ChatSkillDataTable.chat_id == self.chat_id,
262
+ ChatSkillDataTable.skill == self.skill,
263
+ ChatSkillDataTable.key == self.key,
264
264
  )
265
265
  )
266
266
 
@@ -270,18 +270,18 @@ class ThreadSkillDataCreate(BaseModel):
270
270
  record.agent_id = self.agent_id
271
271
  else:
272
272
  # Create new record
273
- record = ThreadSkillDataTable(**self.model_dump())
273
+ record = ChatSkillDataTable(**self.model_dump())
274
274
  db.add(record)
275
275
  await db.commit()
276
276
  await db.refresh(record)
277
- return ThreadSkillData.model_validate(record)
277
+ return ChatSkillData.model_validate(record)
278
278
 
279
279
 
280
- class ThreadSkillData(ThreadSkillDataCreate):
281
- """Model for storing skill-specific data for threads.
280
+ class ChatSkillData(ChatSkillDataCreate):
281
+ """Model for storing skill-specific data for chats.
282
282
 
283
- This model uses a composite primary key of (thread_id, skill, key) to store
284
- skill-specific data for threads in a flexible way. It also includes agent_id
283
+ This model uses a composite primary key of (chat_id, skill, key) to store
284
+ skill-specific data for chats in a flexible way. It also includes agent_id
285
285
  as a required field for tracking ownership.
286
286
  """
287
287
 
@@ -298,11 +298,11 @@ class ThreadSkillData(ThreadSkillDataCreate):
298
298
  ]
299
299
 
300
300
  @classmethod
301
- async def get(cls, thread_id: str, skill: str, key: str) -> Optional[dict]:
302
- """Get skill data for a thread.
301
+ async def get(cls, chat_id: str, skill: str, key: str) -> dict | None:
302
+ """Get skill data for a chat.
303
303
 
304
304
  Args:
305
- thread_id: ID of the thread
305
+ chat_id: ID of the chat
306
306
  skill: Name of the skill
307
307
  key: Data key
308
308
 
@@ -311,10 +311,10 @@ class ThreadSkillData(ThreadSkillDataCreate):
311
311
  """
312
312
  async with get_session() as db:
313
313
  record = await db.scalar(
314
- select(ThreadSkillDataTable).where(
315
- ThreadSkillDataTable.thread_id == thread_id,
316
- ThreadSkillDataTable.skill == skill,
317
- ThreadSkillDataTable.key == key,
314
+ select(ChatSkillDataTable).where(
315
+ ChatSkillDataTable.chat_id == chat_id,
316
+ ChatSkillDataTable.skill == skill,
317
+ ChatSkillDataTable.key == key,
318
318
  )
319
319
  )
320
320
  return record.data if record else None
@@ -323,52 +323,52 @@ class ThreadSkillData(ThreadSkillDataCreate):
323
323
  async def clean_data(
324
324
  cls,
325
325
  agent_id: str,
326
- thread_id: Annotated[
326
+ chat_id: Annotated[
327
327
  str,
328
328
  Field(
329
329
  default="",
330
- description="Optional ID of the thread. If provided, only cleans data for that thread.",
330
+ description="Optional ID of the chat. If provided, only cleans data for that chat.",
331
331
  ),
332
332
  ],
333
333
  ):
334
- """Clean all skill data for a thread or agent.
334
+ """Clean all skill data for a chat or agent.
335
335
 
336
336
  Args:
337
337
  agent_id: ID of the agent
338
- thread_id: Optional ID of the thread. If provided, only cleans data for that thread.
339
- If empty, cleans all data for the agent.
338
+ chat_id: Optional ID of the chat. If provided, only cleans data for that chat.
339
+ If empty, cleans all data for the agent.
340
340
  """
341
341
  async with get_session() as db:
342
- if thread_id and thread_id != "":
342
+ if chat_id and chat_id != "":
343
343
  await db.execute(
344
- delete(ThreadSkillDataTable).where(
345
- ThreadSkillDataTable.agent_id == agent_id,
346
- ThreadSkillDataTable.thread_id == thread_id,
344
+ delete(ChatSkillDataTable).where(
345
+ ChatSkillDataTable.agent_id == agent_id,
346
+ ChatSkillDataTable.chat_id == chat_id,
347
347
  )
348
348
  )
349
349
  else:
350
350
  await db.execute(
351
- delete(ThreadSkillDataTable).where(
352
- ThreadSkillDataTable.agent_id == agent_id
351
+ delete(ChatSkillDataTable).where(
352
+ ChatSkillDataTable.agent_id == agent_id
353
353
  )
354
354
  )
355
355
  await db.commit()
356
356
 
357
357
 
358
- def _skill_parse_bool(value: Optional[str]) -> bool:
358
+ def _skill_parse_bool(value: str | None) -> bool:
359
359
  if value is None:
360
360
  return False
361
361
  return value.strip().lower() in {"true", "1", "yes"}
362
362
 
363
363
 
364
- def _skill_parse_optional_int(value: Optional[str]) -> Optional[int]:
364
+ def _skill_parse_optional_int(value: str | None) -> int | None:
365
365
  if value is None:
366
366
  return None
367
367
  value = value.strip()
368
368
  return int(value) if value else None
369
369
 
370
370
 
371
- def _skill_parse_decimal(value: Optional[str], default: str = "0") -> Decimal:
371
+ def _skill_parse_decimal(value: str | None, default: str = "0") -> Decimal:
372
372
  value = (value or "").strip()
373
373
  if not value:
374
374
  value = default
@@ -383,14 +383,14 @@ def _load_default_skills() -> tuple[dict[str, "Skill"], dict[tuple[str, str], "S
383
383
  logger.warning("Default skills CSV not found at %s", path)
384
384
  return {}, {}
385
385
 
386
- by_name: dict[str, "Skill"] = {}
387
- by_category_config: dict[tuple[str, str], "Skill"] = {}
386
+ by_name: dict[str, Skill] = {}
387
+ by_category_config: dict[tuple[str, str], Skill] = {}
388
388
 
389
389
  with path.open(newline="", encoding="utf-8") as csvfile:
390
390
  reader = csv.DictReader(csvfile)
391
391
  for row in reader:
392
392
  try:
393
- timestamp = datetime.now(timezone.utc)
393
+ timestamp = datetime.now(UTC)
394
394
  price_default = row.get("price") or "1"
395
395
  skill = Skill(
396
396
  name=row["name"],
@@ -449,7 +449,7 @@ class SkillTable(Base):
449
449
  DateTime(timezone=True),
450
450
  nullable=False,
451
451
  server_default=func.now(),
452
- onupdate=lambda: datetime.now(timezone.utc),
452
+ onupdate=lambda: datetime.now(UTC),
453
453
  )
454
454
 
455
455
 
@@ -466,10 +466,8 @@ class Skill(BaseModel):
466
466
  name: Annotated[str, Field(description="Name of the skill")]
467
467
  enabled: Annotated[bool, Field(description="Is this skill enabled?")]
468
468
  category: Annotated[str, Field(description="Category of the skill")]
469
- config_name: Annotated[Optional[str], Field(description="Config name of the skill")]
470
- price_level: Annotated[
471
- Optional[int], Field(description="Price level for this skill")
472
- ]
469
+ config_name: Annotated[str | None, Field(description="Config name of the skill")]
470
+ price_level: Annotated[int | None, Field(description="Price level for this skill")]
473
471
  price: Annotated[
474
472
  Decimal, Field(description="Price for this skill", default=Decimal("1"))
475
473
  ]
@@ -477,11 +475,9 @@ class Skill(BaseModel):
477
475
  Decimal,
478
476
  Field(description="Price for this skill with self key", default=Decimal("1")),
479
477
  ]
480
- rate_limit_count: Annotated[Optional[int], Field(description="Rate limit count")]
481
- rate_limit_minutes: Annotated[
482
- Optional[int], Field(description="Rate limit minutes")
483
- ]
484
- author: Annotated[Optional[str], Field(description="Author of the skill")]
478
+ rate_limit_count: Annotated[int | None, Field(description="Rate limit count")]
479
+ rate_limit_minutes: Annotated[int | None, Field(description="Rate limit minutes")]
480
+ author: Annotated[str | None, Field(description="Author of the skill")]
485
481
  created_at: Annotated[
486
482
  datetime, Field(description="Timestamp when this record was created")
487
483
  ]
@@ -490,7 +486,7 @@ class Skill(BaseModel):
490
486
  ]
491
487
 
492
488
  @staticmethod
493
- async def get(name: str) -> Optional["Skill"]:
489
+ async def get(name: str) -> Skill | None:
494
490
  """Get a skill by name with Redis caching.
495
491
 
496
492
  The skill is cached in Redis for 3 minutes.
@@ -539,7 +535,7 @@ class Skill(BaseModel):
539
535
  return None
540
536
 
541
537
  @staticmethod
542
- async def get_by_config_name(category: str, config_name: str) -> Optional["Skill"]:
538
+ async def get_by_config_name(category: str, config_name: str) -> "Skill" | None:
543
539
  """Get a skill by category and config_name.
544
540
 
545
541
  Args:
@@ -575,7 +571,7 @@ class Skill(BaseModel):
575
571
  async with get_session() as db:
576
572
  return await cls.get_all(session=db)
577
573
 
578
- skills: dict[str, "Skill"] = {
574
+ skills: dict[str, Skill] = {
579
575
  name: skill.model_copy(deep=True)
580
576
  for name, skill in DEFAULT_SKILLS_BY_NAME.items()
581
577
  }
@@ -2,29 +2,29 @@ category,config_name,name,enabled,price_level,price,price_self_key,rate_limit_co
2
2
  acolyt,ask_gpt,acolyt_ask_gpt,FALSE,1,1,1,,,0x2Bd32A312280bF5A01140e68ca630fB76cE8A3De
3
3
  aixbt,aixbt_projects,aixbt_projects,TRUE,3,100,5,,,0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0
4
4
  allora,get_price_prediction,allora_get_price_prediction,TRUE,4,230,5,,,0x2Bd32A312280bF5A01140e68ca630fB76cE8A3De
5
- basename,BasenameActionProvider_register_basename,BasenameActionProvider_register_basename,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
6
- cdp,CdpApiActionProvider_request_faucet_funds,CdpApiActionProvider_request_faucet_funds,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
7
- cdp,CdpEvmWalletActionProvider_get_swap_price,CdpEvmWalletActionProvider_get_swap_price,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
8
- cdp,CdpEvmWalletActionProvider_swap,CdpEvmWalletActionProvider_swap,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
9
- cdp,WalletActionProvider_get_balance,WalletActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
10
- cdp,WalletActionProvider_get_wallet_details,WalletActionProvider_get_wallet_details,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
11
- cdp,WalletActionProvider_native_transfer,WalletActionProvider_native_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
12
- erc20,ERC20ActionProvider_get_balance,ERC20ActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
13
- erc20,ERC20ActionProvider_transfer,ERC20ActionProvider_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
14
- erc721,Erc721ActionProvider_get_balance,Erc721ActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
15
- erc721,Erc721ActionProvider_mint,Erc721ActionProvider_mint,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
16
- erc721,Erc721ActionProvider_transfer,Erc721ActionProvider_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
17
- morpho,MorphoActionProvider_deposit,MorphoActionProvider_deposit,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
18
- morpho,MorphoActionProvider_withdraw,MorphoActionProvider_withdraw,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
19
- pyth,PythActionProvider_fetch_price,PythActionProvider_fetch_price,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
20
- pyth,PythActionProvider_fetch_price_feed,PythActionProvider_fetch_price_feed,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
21
- superfluid,SuperfluidActionProvider_create_flow,SuperfluidActionProvider_create_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
22
- superfluid,SuperfluidActionProvider_delete_flow,SuperfluidActionProvider_delete_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
23
- superfluid,SuperfluidActionProvider_update_flow,SuperfluidActionProvider_update_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
24
- weth,WethActionProvider_wrap_eth,WethActionProvider_wrap_eth,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
25
- wow,WowActionProvider_buy_token,WowActionProvider_buy_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
26
- wow,WowActionProvider_create_token,WowActionProvider_create_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
27
- wow,WowActionProvider_sell_token,WowActionProvider_sell_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
5
+ basename,BasenameActionProvider_register_basename,BasenameActionProvider_register_basename,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
6
+ cdp,CdpApiActionProvider_request_faucet_funds,CdpApiActionProvider_request_faucet_funds,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
7
+ cdp,CdpEvmWalletActionProvider_get_swap_price,CdpEvmWalletActionProvider_get_swap_price,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
8
+ cdp,CdpEvmWalletActionProvider_swap,CdpEvmWalletActionProvider_swap,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
9
+ cdp,WalletActionProvider_get_balance,WalletActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
10
+ cdp,WalletActionProvider_get_wallet_details,WalletActionProvider_get_wallet_details,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
11
+ cdp,WalletActionProvider_native_transfer,WalletActionProvider_native_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
12
+ erc20,ERC20ActionProvider_get_balance,ERC20ActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
13
+ erc20,ERC20ActionProvider_transfer,ERC20ActionProvider_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
14
+ erc721,Erc721ActionProvider_get_balance,Erc721ActionProvider_get_balance,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
15
+ erc721,Erc721ActionProvider_mint,Erc721ActionProvider_mint,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
16
+ erc721,Erc721ActionProvider_transfer,Erc721ActionProvider_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
17
+ morpho,MorphoActionProvider_deposit,MorphoActionProvider_deposit,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
18
+ morpho,MorphoActionProvider_withdraw,MorphoActionProvider_withdraw,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
19
+ pyth,PythActionProvider_fetch_price,PythActionProvider_fetch_price,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
20
+ pyth,PythActionProvider_fetch_price_feed,PythActionProvider_fetch_price_feed,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
21
+ superfluid,SuperfluidActionProvider_create_flow,SuperfluidActionProvider_create_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
22
+ superfluid,SuperfluidActionProvider_delete_flow,SuperfluidActionProvider_delete_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
23
+ superfluid,SuperfluidActionProvider_update_flow,SuperfluidActionProvider_update_flow,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
24
+ weth,WethActionProvider_wrap_eth,WethActionProvider_wrap_eth,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
25
+ wow,WowActionProvider_buy_token,WowActionProvider_buy_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
26
+ wow,WowActionProvider_create_token,WowActionProvider_create_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
27
+ wow,WowActionProvider_sell_token,WowActionProvider_sell_token,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
28
28
  chainlist,chain_lookup,chain-lookup,TRUE,1,5,5,,,0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0
29
29
  common,current_time,common_current_time,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
30
30
  cookiefun,get_account_details,cookiefun_get_account_details,TRUE,2,70,5,,,0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0
@@ -97,9 +97,11 @@ moralis,fetch_nft_portfolio,moralis_fetch_nft_portfolio,TRUE,1,5,5,,,0xd1a8Dd23e
97
97
  moralis,fetch_solana_portfolio,moralis_fetch_solana_portfolio,TRUE,1,5,5,,,0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e
98
98
  moralis,fetch_wallet_portfolio,moralis_fetch_wallet_portfolio,TRUE,1,5,5,,,0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e
99
99
  nation,nft_check,nft_check,FALSE,1,5,5,,,0x275960ad41DbE218bBf72cDF612F88b5C6f40648
100
- openai,dalle_image_generation,dalle_image_generation,TRUE,4,200,15,,,0x445750026A4a1906b61302442E085f9cbAfe206a
101
- openai,gpt_image_generation,gpt_image_generation,TRUE,5,400,15,,,0x445750026A4a1906b61302442E085f9cbAfe206a
102
- openai,gpt_image_to_image,gpt_image_to_image,TRUE,5,400,15,,,0x445750026A4a1906b61302442E085f9cbAfe206a
100
+ openai,dalle_image_generation,dalle_image_generation,TRUE,4,200,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
101
+ openai,gpt_image_generation,gpt_image_generation,TRUE,5,400,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
102
+ openai,gpt_image_mini_generator,gpt_image_mini_generator,TRUE,3,100,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
103
+ openai,gpt_avatar_generator,gpt_avatar_generator,TRUE,2,50,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
104
+ openai,gpt_image_to_image,gpt_image_to_image,TRUE,5,400,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
103
105
  openai,image_to_text,image_to_text,TRUE,4,200,15,,,0x445750026A4a1906b61302442E085f9cbAfe206a
104
106
  portfolio,token_balances,portfolio_token_balances,TRUE,1,5,5,,,0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0
105
107
  portfolio,wallet_approvals,portfolio_wallet_approvals,TRUE,1,5,5,,,0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0
@@ -165,6 +167,8 @@ firecrawl,firecrawl_clear_indexed_content,firecrawl_clear_indexed_content,TRUE,1
165
167
  xmtp,xmtp_transfer,xmtp_transfer,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
166
168
  xmtp,xmtp_swap,xmtp_swap,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
167
169
  xmtp,xmtp_get_swap_price,xmtp_get_swap_price,TRUE,1,5,5,,,0x445750026A4a1906b61302442E085f9cbAfe206a
170
+ x402,x402_ask_agent,x402_ask_agent,TRUE,1,1,1,,,0x445750026A4a1906b61302442E085f9cbAfe206a
171
+ x402,x402_http_request,x402_http_request,TRUE,1,1,1,,,0x445750026A4a1906b61302442E085f9cbAfe206a
168
172
  casino,deck_shuffle,casino_deck_shuffle,true,1,5,5,,,0x3cdd051eec909f94965f9c1c657f5b70a172b2c0
169
173
  casino,deck_draw,casino_deck_draw,true,1,5,5,,,0x3cdd051eec909f94965f9c1c657f5b70a172b2c0
170
174
  casino,dice_roll,casino_dice_roll,true,1,5,5,,,0x3cdd051eec909f94965f9c1c657f5b70a172b2c0
intentkit/models/user.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import logging
2
- from datetime import datetime, timezone
2
+ from datetime import UTC, datetime
3
3
  from decimal import ROUND_HALF_UP, Decimal
4
- from typing import Annotated, Optional, Type, TypeVar
4
+ from typing import Annotated, TypeVar
5
5
 
6
6
  from intentkit.models.base import Base
7
7
  from intentkit.models.credit import CreditAccount
@@ -13,7 +13,6 @@ from sqlalchemy.ext.asyncio import AsyncSession
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
-
17
16
  # TypeVar for User model constraint
18
17
  UserModelType = TypeVar("UserModelType", bound="User")
19
18
  UserTableType = TypeVar("UserTableType", bound="UserTable")
@@ -23,10 +22,10 @@ class UserRegistry:
23
22
  """Registry for extended model classes."""
24
23
 
25
24
  def __init__(self):
26
- self._user_table_class: Optional[Type[UserTableType]] = None
27
- self._user_model_class: Optional[Type[UserModelType]] = None
25
+ self._user_table_class: type[UserTableType] | None = None
26
+ self._user_model_class: type[UserModelType] | None = None
28
27
 
29
- def register_user_table(self, user_table_class: Type[UserTableType]) -> None:
28
+ def register_user_table(self, user_table_class: type[UserTableType]) -> None:
30
29
  """Register extended UserTable class.
31
30
 
32
31
  Args:
@@ -34,11 +33,11 @@ class UserRegistry:
34
33
  """
35
34
  self._user_table_class = user_table_class
36
35
 
37
- def get_user_table_class(self) -> Type[UserTableType]:
36
+ def get_user_table_class(self) -> type[UserTableType]:
38
37
  """Get registered UserTable class or default."""
39
38
  return self._user_table_class or UserTable
40
39
 
41
- def register_user_model(self, user_model_class: Type[UserModelType]) -> None:
40
+ def register_user_model(self, user_model_class: type[UserModelType]) -> None:
42
41
  """Register extended UserModel class.
43
42
 
44
43
  Args:
@@ -46,7 +45,7 @@ class UserRegistry:
46
45
  """
47
46
  self._user_model_class = user_model_class
48
47
 
49
- def get_user_model_class(self) -> Type[UserModelType]:
48
+ def get_user_model_class(self) -> type[UserModelType]:
50
49
  """Get registered UserModel class or default."""
51
50
  return self._user_model_class or User
52
51
 
@@ -114,7 +113,7 @@ class UserTable(Base):
114
113
  DateTime(timezone=True),
115
114
  nullable=False,
116
115
  server_default=func.now(),
117
- onupdate=lambda: datetime.now(timezone.utc),
116
+ onupdate=lambda: datetime.now(UTC),
118
117
  )
119
118
 
120
119
 
@@ -131,27 +130,27 @@ class UserUpdate(BaseModel):
131
130
  nft_count: Annotated[
132
131
  int, Field(default=0, description="Number of NFTs owned by the user")
133
132
  ]
134
- email: Annotated[Optional[str], Field(None, description="User's email address")]
133
+ email: Annotated[str | None, Field(None, description="User's email address")]
135
134
  x_username: Annotated[
136
- Optional[str], Field(None, description="User's X (Twitter) username")
135
+ str | None, Field(None, description="User's X (Twitter) username")
137
136
  ]
138
137
  github_username: Annotated[
139
- Optional[str], Field(None, description="User's GitHub username")
138
+ str | None, Field(None, description="User's GitHub username")
140
139
  ]
141
140
  telegram_username: Annotated[
142
- Optional[str], Field(None, description="User's Telegram username")
141
+ str | None, Field(None, description="User's Telegram username")
143
142
  ]
144
143
  extra: Annotated[
145
- Optional[dict], Field(None, description="Additional user information")
144
+ dict | None, Field(None, description="Additional user information")
146
145
  ]
147
146
  evm_wallet_address: Annotated[
148
- Optional[str], Field(None, description="User's EVM wallet address")
147
+ str | None, Field(None, description="User's EVM wallet address")
149
148
  ]
150
149
  solana_wallet_address: Annotated[
151
- Optional[str], Field(None, description="User's Solana wallet address")
150
+ str | None, Field(None, description="User's Solana wallet address")
152
151
  ]
153
152
  linked_accounts: Annotated[
154
- Optional[dict], Field(None, description="User's linked accounts information")
153
+ dict | None, Field(None, description="User's linked accounts information")
155
154
  ]
156
155
 
157
156
  async def _update_quota_for_nft_count(
@@ -165,7 +164,7 @@ class UserUpdate(BaseModel):
165
164
  new_nft_count: Current NFT count
166
165
  """
167
166
  # Generate upstream_tx_id
168
- timestamp = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
167
+ timestamp = datetime.now(UTC).strftime("%Y%m%d%H%M%S")
169
168
  upstream_tx_id = f"nft_{id}_{timestamp}"
170
169
 
171
170
  # Calculate new quota values based on nft_count
@@ -286,7 +285,7 @@ class User(UserUpdate):
286
285
  ]
287
286
 
288
287
  @classmethod
289
- async def get(cls, user_id: str) -> Optional[UserModelType]:
288
+ async def get(cls, user_id: str) -> UserModelType | None:
290
289
  """Get a user by ID.
291
290
 
292
291
  Args:
@@ -301,7 +300,7 @@ class User(UserUpdate):
301
300
  @classmethod
302
301
  async def get_in_session(
303
302
  cls, session: AsyncSession, user_id: str
304
- ) -> Optional[UserModelType]:
303
+ ) -> UserModelType | None:
305
304
  """Get a user by ID using the provided session.
306
305
 
307
306
  Args:
@@ -322,3 +321,29 @@ class User(UserUpdate):
322
321
  if user is None:
323
322
  return None
324
323
  return user_model_class.model_validate(user)
324
+
325
+ @classmethod
326
+ async def get_by_tg(cls, telegram_username: str) -> UserModelType | None:
327
+ """Get a user by telegram username.
328
+
329
+ Args:
330
+ telegram_username: Telegram username of the user to get
331
+
332
+ Returns:
333
+ User model or None if not found
334
+ """
335
+ user_model_class = user_model_registry.get_user_model_class()
336
+ assert issubclass(user_model_class, User)
337
+ user_table_class = user_model_registry.get_user_table_class()
338
+ assert issubclass(user_table_class, UserTable)
339
+
340
+ async with get_session() as session:
341
+ result = await session.execute(
342
+ select(user_table_class).where(
343
+ user_table_class.telegram_username == telegram_username
344
+ )
345
+ )
346
+ user = result.scalars().first()
347
+ if user is None:
348
+ return None
349
+ return user_model_class.model_validate(user)
@@ -3,7 +3,6 @@
3
3
  import logging
4
4
  from typing import NotRequired, TypedDict
5
5
 
6
- from intentkit.abstracts.skill import SkillStoreABC
7
6
  from intentkit.skills.acolyt.ask import AcolytAskGpt
8
7
  from intentkit.skills.acolyt.base import AcolytBaseTool
9
8
  from intentkit.skills.base import SkillConfig, SkillState
@@ -28,7 +27,6 @@ class Config(SkillConfig):
28
27
  async def get_skills(
29
28
  config: "Config",
30
29
  is_private: bool,
31
- store: SkillStoreABC,
32
30
  **_,
33
31
  ) -> list[AcolytBaseTool]:
34
32
  """Get all Acolyt skills.
@@ -36,7 +34,6 @@ async def get_skills(
36
34
  Args:
37
35
  config: The configuration for Acolyt skills.
38
36
  is_private: Whether to include private skills.
39
- store: The skill store for persisting data.
40
37
 
41
38
  Returns:
42
39
  A list of Acolyt skills.
@@ -53,7 +50,7 @@ async def get_skills(
53
50
  # Get each skill using the cached getter
54
51
  result = []
55
52
  for name in available_skills:
56
- skill = get_acolyt_skill(name, store)
53
+ skill = get_acolyt_skill(name)
57
54
  if skill:
58
55
  result.append(skill)
59
56
  return result
@@ -61,22 +58,18 @@ async def get_skills(
61
58
 
62
59
  def get_acolyt_skill(
63
60
  name: str,
64
- store: SkillStoreABC,
65
61
  ) -> AcolytBaseTool | None:
66
62
  """Get an Acolyt skill by name.
67
63
 
68
64
  Args:
69
65
  name: The name of the skill to get
70
- store: The skill store for persisting data
71
66
 
72
67
  Returns:
73
68
  The requested Acolyt skill
74
69
  """
75
70
  if name == "ask_gpt":
76
71
  if name not in _cache:
77
- _cache[name] = AcolytAskGpt(
78
- skill_store=store,
79
- )
72
+ _cache[name] = AcolytAskGpt()
80
73
  return _cache[name]
81
74
  else:
82
75
  logger.warning(f"Unknown Acolyt skill: {name}")
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Dict, Literal, Type
2
+ from typing import Literal
3
3
 
4
4
  import httpx
5
5
  from pydantic import BaseModel, Field
@@ -48,7 +48,6 @@ class AcolytAskGpt(AcolytBaseTool):
48
48
  - DEX & Trading: Get the 24-hour trading volume for tokens, Identify which DEX has the highest liquidity for tokens, Obtain the buy/sell ratio for tokens over specific time periods. Compare price changes across different timeframes for tokens. List trading pairs with over a value in liquidity for tokens.
49
49
  - Overall Metrics: Identify projects with the highest smart engagement relative to their market cap, Determine which agents have the best mindshare relative to their market cap. Compare the percentage of smart followers across the top n AI agents by market cap
50
50
 
51
-
52
51
  Attributes:
53
52
  name (str): Name of the tool, specifically "acolyt_ask_gpt".
54
53
  description (str): Comprehensive description of the tool's purpose and functionality.
@@ -64,9 +63,9 @@ class AcolytAskGpt(AcolytBaseTool):
64
63
  DEX & Trading: 24h volume, top DEX liquidity, buy/sell ratio, price change comparison, high liquidity pairs.
65
64
  Overall: Smart engagement/market cap ratio, mindshare/market cap ratio, smart follower percentage comparison across top AI agents.
66
65
  """
67
- args_schema: Type[BaseModel] = AcolytAskGptInput
66
+ args_schema: type[BaseModel] = AcolytAskGptInput
68
67
 
69
- async def _arun(self, question: str, **kwargs) -> Dict:
68
+ async def _arun(self, question: str, **kwargs) -> dict:
70
69
  """Run the tool to get answer from Acolyt GPT.
71
70
 
72
71
  Args:
@@ -1,9 +1,7 @@
1
- from typing import Type
2
-
3
- from langchain.tools.base import ToolException
1
+ from langchain_core.tools.base import ToolException
4
2
  from pydantic import BaseModel, Field
5
3
 
6
- from intentkit.abstracts.skill import SkillStoreABC
4
+ from intentkit.config.config import config
7
5
  from intentkit.skills.base import IntentKitSkill
8
6
 
9
7
  base_url = "https://acolyt-oracle-poc.vercel.app"
@@ -14,17 +12,14 @@ class AcolytBaseTool(IntentKitSkill):
14
12
 
15
13
  name: str = Field(description="The name of the tool")
16
14
  description: str = Field(description="A description of what the tool does")
17
- args_schema: Type[BaseModel]
18
- skill_store: SkillStoreABC = Field(
19
- description="The skill store for persisting data"
20
- )
15
+ args_schema: type[BaseModel]
21
16
 
22
17
  def get_api_key(self) -> str:
23
18
  context = self.get_context()
24
19
  skill_config = context.agent.skill_config(self.category)
25
20
  api_key_provider = skill_config.get("api_key_provider")
26
21
  if api_key_provider == "platform":
27
- return self.skill_store.get_system_config("acolyt_api_key")
22
+ return config.acolyt_api_key
28
23
  # for backward compatibility, may only have api_key in skill_config
29
24
  elif skill_config.get("api_key"):
30
25
  return skill_config.get("api_key")