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
@@ -10,14 +10,14 @@ import base64
10
10
  import logging
11
11
  import os
12
12
  import tempfile
13
- from typing import Dict, List, Optional, Tuple
14
13
 
15
14
  from langchain_community.vectorstores import FAISS
16
15
  from langchain_core.documents import Document
17
16
  from langchain_openai import OpenAIEmbeddings
18
17
  from langchain_text_splitters import RecursiveCharacterTextSplitter
19
18
 
20
- from intentkit.abstracts.skill import SkillStoreABC
19
+ from intentkit.config.config import config
20
+ from intentkit.models.skill import AgentSkillData, AgentSkillDataCreate
21
21
 
22
22
  logger = logging.getLogger(__name__)
23
23
 
@@ -62,21 +62,29 @@ METADATA_KEY_PREFIX = "indexed_urls"
62
62
  class VectorStoreManager:
63
63
  """Manages vector store operations including creation, saving, loading, and merging."""
64
64
 
65
- def __init__(self, skill_store: SkillStoreABC):
66
- self.skill_store = skill_store
65
+ def __init__(self, embedding_api_key: str | None = None):
66
+ self._embedding_api_key = embedding_api_key
67
+
68
+ def _resolve_api_key(self) -> str:
69
+ """Resolve the OpenAI API key to use for embeddings."""
70
+ if self._embedding_api_key:
71
+ return self._embedding_api_key
72
+ if config.openai_api_key:
73
+ return config.openai_api_key
74
+ raise ValueError("OpenAI API key is not configured")
67
75
 
68
76
  def create_embeddings(self) -> OpenAIEmbeddings:
69
- """Create OpenAI embeddings using system API key."""
70
- api_key = self.skill_store.get_system_config("openai_api_key")
77
+ """Create OpenAI embeddings using the resolved API key."""
78
+ api_key = self._resolve_api_key()
71
79
  return OpenAIEmbeddings(api_key=api_key)
72
80
 
73
- def get_storage_keys(self, agent_id: str) -> Tuple[str, str]:
81
+ def get_storage_keys(self, agent_id: str) -> tuple[str, str]:
74
82
  """Get storage keys for vector store and metadata."""
75
83
  vector_store_key = f"{VECTOR_STORE_KEY_PREFIX}_{agent_id}"
76
84
  metadata_key = f"{METADATA_KEY_PREFIX}_{agent_id}"
77
85
  return vector_store_key, metadata_key
78
86
 
79
- def encode_vector_store(self, vector_store: FAISS) -> Dict[str, str]:
87
+ def encode_vector_store(self, vector_store: FAISS) -> dict[str, str]:
80
88
  """Encode FAISS vector store to base64 for storage."""
81
89
  with tempfile.TemporaryDirectory() as temp_dir:
82
90
  vector_store.save_local(temp_dir)
@@ -93,7 +101,7 @@ class VectorStoreManager:
93
101
  return encoded_files
94
102
 
95
103
  def decode_vector_store(
96
- self, encoded_files: Dict[str, str], embeddings: OpenAIEmbeddings
104
+ self, encoded_files: dict[str, str], embeddings: OpenAIEmbeddings
97
105
  ) -> FAISS:
98
106
  """Decode base64 files back to FAISS vector store."""
99
107
  with tempfile.TemporaryDirectory() as temp_dir:
@@ -110,20 +118,18 @@ class VectorStoreManager:
110
118
  allow_dangerous_deserialization=True,
111
119
  )
112
120
 
113
- async def get_existing_vector_store(self, agent_id: str) -> Optional[Dict]:
121
+ async def get_existing_vector_store(self, agent_id: str) -> dict | None:
114
122
  """Get existing vector store data if it exists."""
115
123
  vector_store_key, _ = self.get_storage_keys(agent_id)
116
- return await self.skill_store.get_agent_skill_data(
117
- agent_id, "web_scraper", vector_store_key
118
- )
124
+ return await AgentSkillData.get(agent_id, "web_scraper", vector_store_key)
119
125
 
120
126
  async def merge_with_existing(
121
127
  self,
122
- new_documents: List[Document],
128
+ new_documents: list[Document],
123
129
  agent_id: str,
124
130
  chunk_size: int = DEFAULT_CHUNK_SIZE,
125
131
  chunk_overlap: int = DEFAULT_CHUNK_OVERLAP,
126
- ) -> Tuple[FAISS, bool]:
132
+ ) -> tuple[FAISS, bool]:
127
133
  """
128
134
  Merge new documents with existing vector store or create new one.
129
135
 
@@ -184,12 +190,13 @@ class VectorStoreManager:
184
190
 
185
191
  try:
186
192
  # Save to storage
187
- await self.skill_store.save_agent_skill_data(
193
+ skill_data = AgentSkillDataCreate(
188
194
  agent_id=agent_id,
189
195
  skill="web_scraper",
190
196
  key=vector_store_key,
191
197
  data=storage_data,
192
198
  )
199
+ await skill_data.save()
193
200
 
194
201
  logger.info(f"[{agent_id}] Successfully saved vector store")
195
202
 
@@ -197,7 +204,7 @@ class VectorStoreManager:
197
204
  logger.error(f"[{agent_id}] Failed to save vector store: {e}")
198
205
  raise
199
206
 
200
- async def load_vector_store(self, agent_id: str) -> Optional[FAISS]:
207
+ async def load_vector_store(self, agent_id: str) -> FAISS | None:
201
208
  """Load vector store for an agent."""
202
209
  stored_data = await self.get_existing_vector_store(agent_id)
203
210
 
@@ -226,7 +233,8 @@ class VectorStoreManager:
226
233
 
227
234
  return total_size
228
235
 
229
- def format_size(self, size_bytes: int) -> str:
236
+ @staticmethod
237
+ def format_size(size_bytes: int) -> str:
230
238
  """Format size in bytes to human readable format."""
231
239
  if size_bytes < 1024:
232
240
  return f"{size_bytes} B"
@@ -241,10 +249,10 @@ class DocumentProcessor:
241
249
 
242
250
  @staticmethod
243
251
  def create_chunks(
244
- documents: List[Document],
252
+ documents: list[Document],
245
253
  chunk_size: int = DEFAULT_CHUNK_SIZE,
246
254
  chunk_overlap: int = DEFAULT_CHUNK_OVERLAP,
247
- ) -> List[Document]:
255
+ ) -> list[Document]:
248
256
  """Split documents into chunks."""
249
257
  text_splitter = RecursiveCharacterTextSplitter(
250
258
  chunk_size=chunk_size,
@@ -283,7 +291,7 @@ class DocumentProcessor:
283
291
  title: str,
284
292
  source: str,
285
293
  tags: str = "",
286
- extra_metadata: Optional[Dict] = None,
294
+ extra_metadata: dict | None = None,
287
295
  ) -> Document:
288
296
  """Create a Document with standardized metadata."""
289
297
  cleaned_content = DocumentProcessor.clean_text(content)
@@ -312,27 +320,21 @@ class DocumentProcessor:
312
320
  class MetadataManager:
313
321
  """Manages metadata for indexed content."""
314
322
 
315
- def __init__(self, skill_store: SkillStoreABC):
316
- self.skill_store = skill_store
323
+ def __init__(self, vector_manager: VectorStoreManager):
324
+ self._vector_manager = vector_manager
317
325
 
318
- async def get_existing_metadata(self, agent_id: str) -> Dict:
326
+ async def get_existing_metadata(self, agent_id: str) -> dict:
319
327
  """Get existing metadata for an agent."""
320
- vs_manager = VectorStoreManager(self.skill_store)
321
- _, metadata_key = vs_manager.get_storage_keys(agent_id)
322
- return (
323
- await self.skill_store.get_agent_skill_data(
324
- agent_id, "web_scraper", metadata_key
325
- )
326
- or {}
327
- )
328
+ _, metadata_key = self._vector_manager.get_storage_keys(agent_id)
329
+ return await AgentSkillData.get(agent_id, "web_scraper", metadata_key) or {}
328
330
 
329
331
  def create_url_metadata(
330
332
  self,
331
- urls: List[str],
332
- split_docs: List[Document],
333
+ urls: list[str],
334
+ split_docs: list[Document],
333
335
  source_type: str = "web_scraper",
334
- extra_fields: Optional[Dict] = None,
335
- ) -> Dict:
336
+ extra_fields: dict | None = None,
337
+ ) -> dict:
336
338
  """Create metadata for a list of URLs."""
337
339
  metadata = {}
338
340
  current_time = str(asyncio.get_event_loop().time())
@@ -358,9 +360,9 @@ class MetadataManager:
358
360
  title: str,
359
361
  source: str,
360
362
  tags: str,
361
- split_docs: List[Document],
363
+ split_docs: list[Document],
362
364
  document_length: int,
363
- ) -> Dict:
365
+ ) -> dict:
364
366
  """Create metadata for a document."""
365
367
  # Generate unique key
366
368
  key = f"document_{title.lower().replace(' ', '_')}"
@@ -379,10 +381,9 @@ class MetadataManager:
379
381
  }
380
382
  }
381
383
 
382
- async def update_metadata(self, agent_id: str, new_metadata: Dict) -> None:
384
+ async def update_metadata(self, agent_id: str, new_metadata: dict) -> None:
383
385
  """Update metadata for an agent."""
384
- vs_manager = VectorStoreManager(self.skill_store)
385
- _, metadata_key = vs_manager.get_storage_keys(agent_id)
386
+ _, metadata_key = self._vector_manager.get_storage_keys(agent_id)
386
387
 
387
388
  # Get existing metadata
388
389
  existing_metadata = await self.get_existing_metadata(agent_id)
@@ -391,12 +392,13 @@ class MetadataManager:
391
392
  existing_metadata.update(new_metadata)
392
393
 
393
394
  # Save updated metadata
394
- await self.skill_store.save_agent_skill_data(
395
+ skill_data = AgentSkillDataCreate(
395
396
  agent_id=agent_id,
396
397
  skill="web_scraper",
397
398
  key=metadata_key,
398
399
  data=existing_metadata,
399
400
  )
401
+ await skill_data.save()
400
402
 
401
403
 
402
404
  class ResponseFormatter:
@@ -405,12 +407,12 @@ class ResponseFormatter:
405
407
  @staticmethod
406
408
  def format_indexing_response(
407
409
  operation_type: str,
408
- urls_or_content: List[str] | str,
410
+ urls_or_content: list[str] | str,
409
411
  total_chunks: int,
410
412
  chunk_size: int,
411
413
  chunk_overlap: int,
412
414
  was_merged: bool,
413
- extra_info: Optional[Dict] = None,
415
+ extra_info: dict | None = None,
414
416
  current_size_bytes: int = 0,
415
417
  size_limit_reached: bool = False,
416
418
  total_requested_urls: int = 0,
@@ -457,9 +459,8 @@ class ResponseFormatter:
457
459
 
458
460
  # Add size information
459
461
  if current_size_bytes > 0:
460
- vs_manager = VectorStoreManager(None) # Just for formatting
461
- formatted_size = vs_manager.format_size(current_size_bytes)
462
- max_size = vs_manager.format_size(MAX_CONTENT_SIZE_BYTES)
462
+ formatted_size = VectorStoreManager.format_size(current_size_bytes)
463
+ max_size = VectorStoreManager.format_size(MAX_CONTENT_SIZE_BYTES)
463
464
  response_parts.append(
464
465
  f"Current storage size: {formatted_size} / {max_size}"
465
466
  )
@@ -479,20 +480,20 @@ class ResponseFormatter:
479
480
 
480
481
 
481
482
  async def scrape_and_index_urls(
482
- urls: List[str],
483
+ urls: list[str],
483
484
  agent_id: str,
484
- skill_store: SkillStoreABC,
485
+ vector_manager: VectorStoreManager,
485
486
  chunk_size: int = DEFAULT_CHUNK_SIZE,
486
487
  chunk_overlap: int = DEFAULT_CHUNK_OVERLAP,
487
488
  requests_per_second: int = DEFAULT_REQUESTS_PER_SECOND,
488
- ) -> Tuple[int, bool, List[str]]:
489
+ ) -> tuple[int, bool, list[str]]:
489
490
  """
490
491
  Scrape URLs and index their content into vector store with size limits.
491
492
 
492
493
  Args:
493
494
  urls: List of URLs to scrape
494
495
  agent_id: Agent identifier for storage
495
- skill_store: Skill store instance
496
+ vector_manager: Manager for vector store operations
496
497
  chunk_size: Size of text chunks
497
498
  chunk_overlap: Overlap between chunks
498
499
  requests_per_second: Rate limiting for requests
@@ -520,16 +521,15 @@ async def scrape_and_index_urls(
520
521
  return 0, False, []
521
522
 
522
523
  # Check existing content size
523
- vs_manager = VectorStoreManager(skill_store)
524
- current_size = await vs_manager.get_content_size(agent_id)
524
+ current_size = await vector_manager.get_content_size(agent_id)
525
525
 
526
526
  logger.info(
527
- f"[{agent_id}] Current storage size: {vs_manager.format_size(current_size)}"
527
+ f"[{agent_id}] Current storage size: {VectorStoreManager.format_size(current_size)}"
528
528
  )
529
529
 
530
530
  if current_size >= MAX_CONTENT_SIZE_BYTES:
531
531
  logger.warning(
532
- f"[{agent_id}] Storage limit already reached: {vs_manager.format_size(current_size)}"
532
+ f"[{agent_id}] Storage limit already reached: {VectorStoreManager.format_size(current_size)}"
533
533
  )
534
534
  return 0, False, []
535
535
 
@@ -599,7 +599,7 @@ async def scrape_and_index_urls(
599
599
 
600
600
  # Process and index this URL's content
601
601
  chunks, merged = await index_documents(
602
- documents, agent_id, skill_store, chunk_size, chunk_overlap
602
+ documents, agent_id, vector_manager, chunk_size, chunk_overlap
603
603
  )
604
604
 
605
605
  if chunks > 0:
@@ -609,7 +609,7 @@ async def scrape_and_index_urls(
609
609
  current_size += content_size
610
610
 
611
611
  logger.info(
612
- f"[{agent_id}] Processed {url}: {chunks} chunks, current size: {vs_manager.format_size(current_size)}"
612
+ f"[{agent_id}] Processed {url}: {chunks} chunks, current size: {VectorStoreManager.format_size(current_size)}"
613
613
  )
614
614
 
615
615
  # Add delay for rate limiting
@@ -635,12 +635,12 @@ async def scrape_and_index_urls(
635
635
 
636
636
  # Convenience function that combines all operations
637
637
  async def index_documents(
638
- documents: List[Document],
638
+ documents: list[Document],
639
639
  agent_id: str,
640
- skill_store: SkillStoreABC,
640
+ vector_manager: VectorStoreManager,
641
641
  chunk_size: int = DEFAULT_CHUNK_SIZE,
642
642
  chunk_overlap: int = DEFAULT_CHUNK_OVERLAP,
643
- ) -> Tuple[int, bool]:
643
+ ) -> tuple[int, bool]:
644
644
  """
645
645
  Complete document indexing workflow.
646
646
 
@@ -654,13 +654,12 @@ async def index_documents(
654
654
  raise ValueError("No content could be processed into chunks")
655
655
 
656
656
  # Handle vector store
657
- vs_manager = VectorStoreManager(skill_store)
658
- vector_store, was_merged = await vs_manager.merge_with_existing(
657
+ vector_store, was_merged = await vector_manager.merge_with_existing(
659
658
  split_docs, agent_id, chunk_size, chunk_overlap
660
659
  )
661
660
 
662
661
  # Save vector store
663
- await vs_manager.save_vector_store(
662
+ await vector_manager.save_vector_store(
664
663
  vector_store, agent_id, chunk_size, chunk_overlap
665
664
  )
666
665
 
@@ -1,5 +1,4 @@
1
1
  import logging
2
- from typing import List, Type
3
2
  from urllib.parse import urljoin, urlparse
4
3
 
5
4
  import httpx
@@ -44,11 +43,11 @@ class WebsiteIndexerInput(BaseModel):
44
43
  ge=0,
45
44
  le=1000,
46
45
  )
47
- include_patterns: List[str] = Field(
46
+ include_patterns: list[str] = Field(
48
47
  description="URL patterns to include (e.g., ['/blog/', '/docs/']). If empty, all URLs are included",
49
48
  default=[],
50
49
  )
51
- exclude_patterns: List[str] = Field(
50
+ exclude_patterns: list[str] = Field(
52
51
  description="URL patterns to exclude (e.g., ['/admin/', '/private/'])",
53
52
  default=[],
54
53
  )
@@ -68,7 +67,7 @@ class WebsiteIndexer(WebScraperBaseTool):
68
67
  "This tool finds sitemaps from robots.txt, parses the XML content to extract URLs, "
69
68
  "and then uses the reliable scrape_and_index functionality for content indexing."
70
69
  )
71
- args_schema: Type[BaseModel] = WebsiteIndexerInput
70
+ args_schema: type[BaseModel] = WebsiteIndexerInput
72
71
 
73
72
  def _normalize_url(self, url: str) -> str:
74
73
  """Normalize URL by ensuring it has a proper scheme."""
@@ -106,7 +105,7 @@ class WebsiteIndexer(WebScraperBaseTool):
106
105
 
107
106
  def _extract_sitemaps_from_robots(
108
107
  self, robots_content: str, base_url: str
109
- ) -> List[str]:
108
+ ) -> list[str]:
110
109
  """Extract sitemap URLs from robots.txt content."""
111
110
  sitemaps = []
112
111
 
@@ -121,7 +120,7 @@ class WebsiteIndexer(WebScraperBaseTool):
121
120
 
122
121
  return sitemaps
123
122
 
124
- def _get_common_sitemap_patterns(self, base_url: str) -> List[str]:
123
+ def _get_common_sitemap_patterns(self, base_url: str) -> list[str]:
125
124
  """Generate common sitemap URL patterns."""
126
125
  return [
127
126
  urljoin(base_url, "/sitemap.xml"),
@@ -157,7 +156,7 @@ class WebsiteIndexer(WebScraperBaseTool):
157
156
  logger.warning(f"Could not fetch sitemap from {sitemap_url}: {e}")
158
157
  return ""
159
158
 
160
- async def _get_all_sitemap_content(self, base_url: str) -> tuple[str, List[str]]:
159
+ async def _get_all_sitemap_content(self, base_url: str) -> tuple[str, list[str]]:
161
160
  """Get all sitemap content for AI analysis."""
162
161
  all_content = []
163
162
  found_sitemaps = []
@@ -200,7 +199,7 @@ class WebsiteIndexer(WebScraperBaseTool):
200
199
  return combined_xml, found_sitemaps
201
200
 
202
201
  def _create_ai_extraction_prompt(
203
- self, sitemap_xml: str, include_patterns: List[str], exclude_patterns: List[str]
202
+ self, sitemap_xml: str, include_patterns: list[str], exclude_patterns: list[str]
204
203
  ) -> str:
205
204
  """Create a prompt for AI to extract URLs from sitemap XML."""
206
205
  filter_instructions = ""
@@ -225,7 +224,7 @@ INSTRUCTIONS:
225
224
 
226
225
  Extract the URLs now:"""
227
226
 
228
- def _parse_ai_response(self, ai_response: str) -> List[str]:
227
+ def _parse_ai_response(self, ai_response: str) -> list[str]:
229
228
  """Parse AI response to extract clean URLs."""
230
229
  urls = []
231
230
 
@@ -250,10 +249,7 @@ Extract the URLs now:"""
250
249
  """Call OpenAI GPT-4o-mini to extract URLs from sitemap content."""
251
250
  try:
252
251
  # Get OpenAI API key using the standard pattern
253
- from intentkit.skills.openai.base import OpenAIBaseTool
254
-
255
- temp_tool = OpenAIBaseTool(skill_store=self.skill_store)
256
- api_key = temp_tool.get_api_key()
252
+ api_key = self.get_openai_api_key()
257
253
 
258
254
  # Initialize OpenAI client
259
255
  client = openai.AsyncOpenAI(api_key=api_key)
@@ -284,8 +280,8 @@ Extract the URLs now:"""
284
280
  max_urls: int = 50,
285
281
  chunk_size: int = DEFAULT_CHUNK_SIZE,
286
282
  chunk_overlap: int = DEFAULT_CHUNK_OVERLAP,
287
- include_patterns: List[str] = None,
288
- exclude_patterns: List[str] = None,
283
+ include_patterns: list[str] = None,
284
+ exclude_patterns: list[str] = None,
289
285
  **kwargs,
290
286
  ) -> str:
291
287
  """Discover website sitemaps, extract URLs with AI, and delegate to scrape_and_index."""
@@ -385,9 +381,12 @@ Extract the URLs now:"""
385
381
  f"[{agent_id}] Extracted {len(unique_urls)} URLs from sitemaps. Scraping and indexing..."
386
382
  )
387
383
 
384
+ embedding_api_key = self.get_openai_api_key()
385
+ vector_manager = VectorStoreManager(embedding_api_key)
386
+
388
387
  # Use the utility function to scrape and index URLs directly
389
388
  total_chunks, was_merged, valid_urls = await scrape_and_index_urls(
390
- unique_urls, agent_id, self.skill_store, chunk_size, chunk_overlap
389
+ unique_urls, agent_id, vector_manager, chunk_size, chunk_overlap
391
390
  )
392
391
 
393
392
  if total_chunks == 0:
@@ -397,12 +396,11 @@ Extract the URLs now:"""
397
396
  return f"Error: No content could be extracted from the discovered URLs. Found sitemaps: {', '.join(found_sitemaps)}"
398
397
 
399
398
  # Get current storage size for response
400
- vs_manager = VectorStoreManager(self.skill_store)
401
- current_size = await vs_manager.get_content_size(agent_id)
399
+ current_size = await vector_manager.get_content_size(agent_id)
402
400
  size_limit_reached = len(valid_urls) < len(unique_urls)
403
401
 
404
402
  # Update metadata
405
- metadata_manager = MetadataManager(self.skill_store)
403
+ metadata_manager = MetadataManager(vector_manager)
406
404
  new_metadata = metadata_manager.create_url_metadata(
407
405
  valid_urls, [], "website_indexer"
408
406
  )
@@ -1,10 +1,10 @@
1
1
  """WETH AgentKit skills."""
2
2
 
3
- from typing import TYPE_CHECKING, Optional, TypedDict
3
+ from typing import TypedDict
4
4
 
5
5
  from coinbase_agentkit import weth_action_provider
6
6
 
7
- from intentkit.abstracts.skill import SkillStoreABC
7
+ from intentkit.models.agent import Agent
8
8
  from intentkit.skills.base import (
9
9
  SkillConfig,
10
10
  SkillState,
@@ -13,9 +13,6 @@ from intentkit.skills.base import (
13
13
  )
14
14
  from intentkit.skills.weth.base import WethBaseTool
15
15
 
16
- if TYPE_CHECKING:
17
- from intentkit.models.agent import Agent
18
-
19
16
 
20
17
  class SkillStates(TypedDict):
21
18
  WethActionProvider_wrap_eth: SkillState
@@ -28,11 +25,10 @@ class Config(SkillConfig):
28
25
 
29
26
 
30
27
  async def get_skills(
31
- config: "Config",
28
+ config: Config,
32
29
  is_private: bool,
33
- store: SkillStoreABC,
34
30
  agent_id: str,
35
- agent: Optional["Agent"] = None,
31
+ agent: Agent | None = None,
36
32
  **_,
37
33
  ) -> list[WethBaseTool]:
38
34
  """Get all WETH skills."""
@@ -44,9 +40,7 @@ async def get_skills(
44
40
  if state == "public" or (state == "private" and is_private):
45
41
  available_skills.append(skill_name)
46
42
 
47
- actions = await get_agentkit_actions(
48
- agent_id, store, [weth_action_provider], agent=agent
49
- )
43
+ actions = await get_agentkit_actions(agent_id, [weth_action_provider], agent=agent)
50
44
  tools: list[WethBaseTool] = []
51
45
  for skill in available_skills:
52
46
  for action in actions:
@@ -1,10 +1,10 @@
1
1
  """WOW AgentKit skills."""
2
2
 
3
- from typing import TYPE_CHECKING, Optional, TypedDict
3
+ from typing import TypedDict
4
4
 
5
5
  from coinbase_agentkit import wow_action_provider
6
6
 
7
- from intentkit.abstracts.skill import SkillStoreABC
7
+ from intentkit.models.agent import Agent
8
8
  from intentkit.skills.base import (
9
9
  SkillConfig,
10
10
  SkillState,
@@ -13,9 +13,6 @@ from intentkit.skills.base import (
13
13
  )
14
14
  from intentkit.skills.wow.base import WowBaseTool
15
15
 
16
- if TYPE_CHECKING:
17
- from intentkit.models.agent import Agent
18
-
19
16
 
20
17
  class SkillStates(TypedDict):
21
18
  WowActionProvider_buy_token: SkillState
@@ -30,11 +27,10 @@ class Config(SkillConfig):
30
27
 
31
28
 
32
29
  async def get_skills(
33
- config: "Config",
30
+ config: Config,
34
31
  is_private: bool,
35
- store: SkillStoreABC,
36
32
  agent_id: str,
37
- agent: Optional["Agent"] = None,
33
+ agent: Agent | None = None,
38
34
  **_,
39
35
  ) -> list[WowBaseTool]:
40
36
  """Get all WOW skills."""
@@ -46,9 +42,7 @@ async def get_skills(
46
42
  if state == "public" or (state == "private" and is_private):
47
43
  available_skills.append(skill_name)
48
44
 
49
- actions = await get_agentkit_actions(
50
- agent_id, store, [wow_action_provider], agent=agent
51
- )
45
+ actions = await get_agentkit_actions(agent_id, [wow_action_provider], agent=agent)
52
46
  tools: list[WowBaseTool] = []
53
47
  for skill in available_skills:
54
48
  for action in actions:
@@ -0,0 +1,61 @@
1
+ """x402 skill category."""
2
+
3
+ import logging
4
+ from typing import TypedDict
5
+
6
+ from intentkit.skills.base import SkillConfig, SkillState
7
+ from intentkit.skills.x402.ask_agent import X402AskAgent
8
+ from intentkit.skills.x402.base import X402BaseSkill
9
+ from intentkit.skills.x402.http_request import X402HttpRequest
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ _cache: dict[str, X402BaseSkill] = {}
14
+
15
+
16
+ class SkillStates(TypedDict):
17
+ x402_ask_agent: SkillState
18
+ x402_http_request: SkillState
19
+
20
+
21
+ class Config(SkillConfig):
22
+ """Configuration for x402 skills."""
23
+
24
+ states: SkillStates
25
+
26
+
27
+ _SKILL_BUILDERS: dict[str, type[X402BaseSkill]] = {
28
+ "x402_ask_agent": X402AskAgent,
29
+ "x402_http_request": X402HttpRequest,
30
+ }
31
+
32
+
33
+ async def get_skills(
34
+ config: "Config",
35
+ is_private: bool,
36
+ **_,
37
+ ) -> list[X402BaseSkill]:
38
+ """Return enabled x402 skills for the agent."""
39
+ enabled_skills = []
40
+ for skill_name, state in config["states"].items():
41
+ if state == "disabled":
42
+ continue
43
+ if state == "public" or (state == "private" and is_private):
44
+ enabled_skills.append(skill_name)
45
+
46
+ result: list[X402BaseSkill] = []
47
+ for name in enabled_skills:
48
+ skill = _get_skill(name)
49
+ if skill:
50
+ result.append(skill)
51
+ return result
52
+
53
+
54
+ def _get_skill(name: str) -> X402BaseSkill | None:
55
+ builder = _SKILL_BUILDERS.get(name)
56
+ if builder:
57
+ if name not in _cache:
58
+ _cache[name] = builder()
59
+ return _cache[name]
60
+ logger.warning("Unknown x402 skill requested: %s", name)
61
+ return None