intentkit 0.8.12.dev2__py3-none-any.whl → 0.8.12.dev3__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 (168) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/skill.py +2 -59
  3. intentkit/clients/twitter.py +35 -28
  4. intentkit/core/agent.py +2 -279
  5. intentkit/core/engine.py +2 -3
  6. intentkit/models/agent.py +109 -89
  7. intentkit/models/agent_schema.json +4 -2
  8. intentkit/skills/acolyt/__init__.py +2 -9
  9. intentkit/skills/acolyt/base.py +2 -5
  10. intentkit/skills/aixbt/__init__.py +2 -13
  11. intentkit/skills/aixbt/base.py +0 -4
  12. intentkit/skills/aixbt/projects.py +1 -2
  13. intentkit/skills/allora/__init__.py +2 -9
  14. intentkit/skills/allora/base.py +2 -5
  15. intentkit/skills/base.py +101 -27
  16. intentkit/skills/basename/__init__.py +1 -3
  17. intentkit/skills/carv/__init__.py +116 -121
  18. intentkit/skills/carv/base.py +184 -185
  19. intentkit/skills/casino/__init__.py +4 -15
  20. intentkit/skills/casino/base.py +0 -4
  21. intentkit/skills/casino/deck_draw.py +1 -2
  22. intentkit/skills/casino/deck_shuffle.py +1 -2
  23. intentkit/skills/casino/dice_roll.py +1 -2
  24. intentkit/skills/cdp/__init__.py +0 -4
  25. intentkit/skills/cdp/base.py +0 -4
  26. intentkit/skills/chainlist/__init__.py +2 -7
  27. intentkit/skills/chainlist/base.py +0 -4
  28. intentkit/skills/common/__init__.py +2 -9
  29. intentkit/skills/common/base.py +0 -4
  30. intentkit/skills/cookiefun/__init__.py +6 -9
  31. intentkit/skills/cookiefun/base.py +0 -4
  32. intentkit/skills/cryptocompare/__init__.py +7 -24
  33. intentkit/skills/cryptocompare/base.py +0 -5
  34. intentkit/skills/cryptopanic/__init__.py +3 -6
  35. intentkit/skills/cryptopanic/base.py +53 -55
  36. intentkit/skills/cryptopanic/fetch_crypto_news.py +0 -2
  37. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +1 -3
  38. intentkit/skills/dapplooker/__init__.py +2 -9
  39. intentkit/skills/dapplooker/base.py +2 -5
  40. intentkit/skills/defillama/__init__.py +24 -74
  41. intentkit/skills/defillama/base.py +0 -4
  42. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +2 -2
  43. intentkit/skills/defillama/coins/fetch_block.py +2 -2
  44. intentkit/skills/defillama/coins/fetch_current_prices.py +2 -2
  45. intentkit/skills/defillama/coins/fetch_first_price.py +2 -2
  46. intentkit/skills/defillama/coins/fetch_historical_prices.py +2 -2
  47. intentkit/skills/defillama/coins/fetch_price_chart.py +2 -2
  48. intentkit/skills/defillama/coins/fetch_price_percentage.py +2 -2
  49. intentkit/skills/defillama/fees/fetch_fees_overview.py +2 -2
  50. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +2 -2
  51. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +2 -2
  52. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +2 -2
  53. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +2 -2
  54. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +2 -2
  55. intentkit/skills/defillama/tvl/fetch_chains.py +2 -2
  56. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +2 -2
  57. intentkit/skills/defillama/tvl/fetch_protocol.py +2 -2
  58. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +2 -2
  59. intentkit/skills/defillama/tvl/fetch_protocols.py +2 -2
  60. intentkit/skills/defillama/volumes/fetch_dex_overview.py +2 -2
  61. intentkit/skills/defillama/volumes/fetch_dex_summary.py +2 -2
  62. intentkit/skills/defillama/volumes/fetch_options_overview.py +2 -2
  63. intentkit/skills/defillama/yields/fetch_pool_chart.py +2 -2
  64. intentkit/skills/defillama/yields/fetch_pools.py +2 -2
  65. intentkit/skills/dexscreener/__init__.py +97 -102
  66. intentkit/skills/dexscreener/base.py +125 -130
  67. intentkit/skills/dexscreener/get_pair_info.py +2 -3
  68. intentkit/skills/dexscreener/get_token_pairs.py +2 -3
  69. intentkit/skills/dexscreener/get_tokens_info.py +2 -3
  70. intentkit/skills/dexscreener/search_token.py +2 -4
  71. intentkit/skills/dune_analytics/__init__.py +4 -6
  72. intentkit/skills/dune_analytics/base.py +50 -52
  73. intentkit/skills/dune_analytics/fetch_kol_buys.py +0 -2
  74. intentkit/skills/dune_analytics/fetch_nation_metrics.py +0 -2
  75. intentkit/skills/elfa/__init__.py +5 -18
  76. intentkit/skills/elfa/base.py +8 -10
  77. intentkit/skills/enso/__init__.py +9 -29
  78. intentkit/skills/enso/base.py +3 -6
  79. intentkit/skills/enso/route.py +1 -3
  80. intentkit/skills/erc20/__init__.py +1 -5
  81. intentkit/skills/erc721/__init__.py +1 -3
  82. intentkit/skills/firecrawl/__init__.py +5 -18
  83. intentkit/skills/firecrawl/base.py +2 -5
  84. intentkit/skills/firecrawl/crawl.py +10 -9
  85. intentkit/skills/firecrawl/query.py +3 -1
  86. intentkit/skills/firecrawl/scrape.py +8 -10
  87. intentkit/skills/firecrawl/utils.py +25 -26
  88. intentkit/skills/github/__init__.py +2 -7
  89. intentkit/skills/github/base.py +0 -4
  90. intentkit/skills/heurist/__init__.py +8 -27
  91. intentkit/skills/heurist/base.py +2 -5
  92. intentkit/skills/heurist/image_generation_animagine_xl.py +5 -5
  93. intentkit/skills/heurist/image_generation_arthemy_comics.py +5 -5
  94. intentkit/skills/heurist/image_generation_arthemy_real.py +5 -5
  95. intentkit/skills/heurist/image_generation_braindance.py +5 -5
  96. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +5 -5
  97. intentkit/skills/heurist/image_generation_flux_1_dev.py +5 -5
  98. intentkit/skills/heurist/image_generation_sdxl.py +5 -5
  99. intentkit/skills/http/__init__.py +4 -15
  100. intentkit/skills/http/base.py +0 -4
  101. intentkit/skills/lifi/__init__.py +1 -6
  102. intentkit/skills/lifi/base.py +0 -4
  103. intentkit/skills/lifi/token_execute.py +1 -4
  104. intentkit/skills/lifi/token_quote.py +1 -3
  105. intentkit/skills/moralis/__init__.py +3 -7
  106. intentkit/skills/moralis/base.py +2 -5
  107. intentkit/skills/morpho/__init__.py +1 -3
  108. intentkit/skills/nation/__init__.py +2 -7
  109. intentkit/skills/nation/base.py +4 -7
  110. intentkit/skills/openai/__init__.py +5 -18
  111. intentkit/skills/openai/base.py +8 -10
  112. intentkit/skills/openai/dalle_image_generation.py +2 -5
  113. intentkit/skills/openai/gpt_image_generation.py +2 -5
  114. intentkit/skills/openai/gpt_image_to_image.py +2 -5
  115. intentkit/skills/openai/image_to_text.py +2 -5
  116. intentkit/skills/portfolio/__init__.py +11 -35
  117. intentkit/skills/portfolio/base.py +2 -5
  118. intentkit/skills/pyth/__init__.py +1 -5
  119. intentkit/skills/slack/__init__.py +5 -17
  120. intentkit/skills/slack/base.py +0 -4
  121. intentkit/skills/supabase/__init__.py +7 -23
  122. intentkit/skills/supabase/base.py +0 -4
  123. intentkit/skills/superfluid/__init__.py +1 -3
  124. intentkit/skills/system/__init__.py +7 -24
  125. intentkit/skills/system/add_autonomous_task.py +2 -2
  126. intentkit/skills/system/delete_autonomous_task.py +2 -2
  127. intentkit/skills/system/edit_autonomous_task.py +2 -4
  128. intentkit/skills/system/list_autonomous_tasks.py +2 -2
  129. intentkit/skills/system/read_agent_api_key.py +6 -4
  130. intentkit/skills/system/regenerate_agent_api_key.py +6 -4
  131. intentkit/skills/tavily/__init__.py +3 -12
  132. intentkit/skills/tavily/base.py +2 -5
  133. intentkit/skills/tavily/tavily_extract.py +1 -2
  134. intentkit/skills/tavily/tavily_search.py +3 -3
  135. intentkit/skills/token/__init__.py +5 -10
  136. intentkit/skills/token/base.py +2 -6
  137. intentkit/skills/twitter/__init__.py +11 -35
  138. intentkit/skills/twitter/base.py +14 -16
  139. intentkit/skills/twitter/follow_user.py +0 -1
  140. intentkit/skills/twitter/get_mentions.py +0 -1
  141. intentkit/skills/twitter/get_timeline.py +0 -1
  142. intentkit/skills/twitter/get_user_by_username.py +0 -1
  143. intentkit/skills/twitter/get_user_tweets.py +0 -1
  144. intentkit/skills/twitter/like_tweet.py +0 -1
  145. intentkit/skills/twitter/post_tweet.py +2 -2
  146. intentkit/skills/twitter/reply_tweet.py +2 -2
  147. intentkit/skills/twitter/retweet.py +0 -1
  148. intentkit/skills/twitter/search_tweets.py +0 -1
  149. intentkit/skills/unrealspeech/__init__.py +2 -7
  150. intentkit/skills/unrealspeech/base.py +0 -4
  151. intentkit/skills/venice_audio/__init__.py +99 -106
  152. intentkit/skills/venice_audio/base.py +118 -121
  153. intentkit/skills/venice_audio/venice_audio.py +1 -5
  154. intentkit/skills/venice_image/__init__.py +147 -154
  155. intentkit/skills/venice_image/base.py +185 -192
  156. intentkit/skills/web_scraper/__init__.py +5 -18
  157. intentkit/skills/web_scraper/base.py +20 -4
  158. intentkit/skills/web_scraper/document_indexer.py +6 -4
  159. intentkit/skills/web_scraper/scrape_and_index.py +11 -8
  160. intentkit/skills/web_scraper/utils.py +31 -27
  161. intentkit/skills/web_scraper/website_indexer.py +7 -8
  162. intentkit/skills/weth/__init__.py +1 -5
  163. intentkit/skills/wow/__init__.py +1 -5
  164. intentkit/skills/xmtp/__init__.py +4 -15
  165. {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev3.dist-info}/METADATA +1 -1
  166. {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev3.dist-info}/RECORD +168 -168
  167. {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev3.dist-info}/WHEEL +0 -0
  168. {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev3.dist-info}/licenses/LICENSE +0 -0
@@ -1,192 +1,185 @@
1
- import logging
2
- from typing import Any, Dict, Optional, Tuple
3
-
4
- from langchain_core.tools.base import ToolException
5
- from pydantic import Field
6
-
7
- from intentkit.abstracts.skill import SkillStoreABC
8
- from intentkit.skills.base import IntentKitSkill
9
- from intentkit.skills.venice_image.api import (
10
- make_venice_api_request,
11
- )
12
- from intentkit.skills.venice_image.config import VeniceImageConfig
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- venice_base_url = "https://api.venice.ai" # Common base URL for all Venice endpoints
17
-
18
-
19
- class VeniceImageBaseTool(IntentKitSkill):
20
- """
21
- Base class for all Venice AI image-related skills.
22
-
23
- This class provides common functionality for interacting with the
24
- Venice AI API, including:
25
-
26
- - Retrieving the API key (from agent or system configuration).
27
- - Applying rate limits to prevent overuse of the API.
28
- - A standardized `post` method for making API requests.
29
-
30
- Subclasses should inherit from this class and implement their specific
31
- API interactions (e.g., image generation, upscaling, inpainting)
32
- by defining their own `_arun` methods and setting appropriate `name`
33
- and `description` attributes.
34
- """
35
-
36
- @property
37
- def category(self) -> str:
38
- """
39
- Returns the category of this skill, used for configuration and logging.
40
- """
41
- return "venice_image"
42
-
43
- skill_store: SkillStoreABC = Field(
44
- description="The skill store for persisting data and configs."
45
- )
46
-
47
- def getSkillConfig(self, context) -> VeniceImageConfig:
48
- """
49
- Creates a VeniceImageConfig instance from a dictionary of configuration values.
50
-
51
- Args:
52
- config: A dictionary containing configuration settings.
53
-
54
- Returns:
55
- A VeniceImageConfig object.
56
- """
57
-
58
- skill_config = context.agent.skill_config(self.category)
59
- return VeniceImageConfig(
60
- api_key_provider=skill_config.get("api_key_provider", "agent_owner"),
61
- safe_mode=skill_config.get("safe_mode", True),
62
- hide_watermark=skill_config.get("hide_watermark", True),
63
- embed_exif_metadata=skill_config.get("embed_exif_metadata", False),
64
- negative_prompt=skill_config.get(
65
- "negative_prompt", "(worst quality: 1.4), bad quality, nsfw"
66
- ),
67
- rate_limit_number=skill_config.get("rate_limit_number"),
68
- rate_limit_minutes=skill_config.get("rate_limit_minutes"),
69
- )
70
-
71
- def get_api_key(self) -> str:
72
- """
73
- Retrieves the Venice AI API key based on the api_key_provider setting.
74
-
75
- Returns:
76
- The API key if found.
77
-
78
- Raises:
79
- ToolException: If the API key is not found or provider is invalid.
80
- """
81
- try:
82
- context = self.get_context()
83
- skillConfig = self.getSkillConfig(context=context)
84
- if skillConfig.api_key_provider == "agent_owner":
85
- skill_config = context.agent.skill_config(self.category)
86
- agent_api_key = skill_config.get("api_key")
87
- if agent_api_key:
88
- logger.debug(
89
- f"Using agent-specific Venice API key for skill {self.name} in category {self.category}"
90
- )
91
- return agent_api_key
92
- raise ToolException(
93
- f"No agent-owned Venice API key found for skill '{self.name}' in category '{self.category}'."
94
- )
95
-
96
- elif skillConfig.api_key_provider == "platform":
97
- system_api_key = self.skill_store.get_system_config("venice_api_key")
98
- if system_api_key:
99
- logger.debug(
100
- f"Using system Venice API key for skill {self.name} in category {self.category}"
101
- )
102
- return system_api_key
103
- raise ToolException(
104
- f"No platform-hosted Venice API key found for skill '{self.name}' in category '{self.category}'."
105
- )
106
-
107
- else:
108
- raise ToolException(
109
- f"Invalid API key provider '{skillConfig.api_key_provider}' for skill '{self.name}'"
110
- )
111
-
112
- except Exception as e:
113
- raise ToolException(f"Failed to retrieve Venice API key: {str(e)}") from e
114
-
115
- async def apply_venice_rate_limit(self, context) -> None:
116
- """
117
- Applies rate limiting to prevent exceeding the Venice AI API's rate limits.
118
-
119
- Rate limits are applied based on the api_key_provider setting:
120
- - 'agent_owner': uses agent-specific configuration.
121
- - 'platform': uses system-wide configuration.
122
- """
123
- try:
124
- # Get user_id from the agent context (venice_image only supports agent_owner)
125
- skillConfig = self.getSkillConfig(context=context)
126
-
127
- if skillConfig.api_key_provider == "agent_owner":
128
- limit_num = skillConfig.rate_limit_number
129
- limit_min = skillConfig.rate_limit_minutes
130
-
131
- if limit_num and limit_min:
132
- # For agent_owner, use agent.id as user_id for rate limiting
133
- user_id = context.agent.id
134
- logger.debug(
135
- f"Applying Agent rate limit ({limit_num}/{limit_min} min) for user {user_id} on {self.name}"
136
- )
137
- await self.user_rate_limit_by_category(
138
- user_id, limit_num, limit_min
139
- )
140
-
141
- elif skillConfig.api_key_provider == "platform":
142
- system_limit_num = self.skill_store.get_system_config(
143
- f"{self.category}_rate_limit_number"
144
- )
145
- system_limit_min = self.skill_store.get_system_config(
146
- f"{self.category}_rate_limit_minutes"
147
- )
148
-
149
- if system_limit_num and system_limit_min:
150
- # For platform, use agent.id as user_id for rate limiting
151
- user_id = context.agent.id
152
- logger.debug(
153
- f"Applying System rate limit ({system_limit_num}/{system_limit_min} min) for user {user_id} on {self.name}"
154
- )
155
- await self.user_rate_limit_by_category(
156
- user_id, system_limit_num, system_limit_min
157
- )
158
- # do nothing if no rate limit is
159
- return None
160
-
161
- except Exception as e:
162
- raise ToolException(f"Failed to apply Venice rate limit: {str(e)}") from e
163
-
164
- async def post(
165
- self, path: str, payload: Dict[str, Any], context
166
- ) -> Tuple[Dict[str, Any], Optional[Dict[str, Any]]]:
167
- """
168
- Makes a POST request to the Venice AI API using the `make_venice_api_request`
169
- function from the `skills.venice_image.api` module.
170
-
171
- This method handles the following:
172
-
173
- 1. Retrieving the API key using `get_api_key`.
174
- 2. Constructing the request payload.
175
- 3. Calling `make_venice_api_request` to make the actual API call.
176
- 4. Returning the results from `make_venice_api_request`.
177
-
178
- Args:
179
- path: The API endpoint path (e.g., "/api/v1/image/generate").
180
- payload: The request payload as a dictionary.
181
- context: The SkillContext for accessing API keys and configs.
182
-
183
- Returns:
184
- A tuple: (success_data, error_data).
185
- - If successful, success contains the JSON response from the API.
186
- - If an error occurs, success is an empty dictionary, and error contains error details.
187
- """
188
- api_key = self.get_api_key()
189
-
190
- return await make_venice_api_request(
191
- api_key, path, payload, self.category, self.name
192
- )
1
+ import logging
2
+ from typing import Any, Dict, Optional, Tuple
3
+
4
+ from langchain_core.tools.base import ToolException
5
+
6
+ from intentkit.config.config import config
7
+ from intentkit.skills.base import IntentKitSkill
8
+ from intentkit.skills.venice_image.api import (
9
+ make_venice_api_request,
10
+ )
11
+ from intentkit.skills.venice_image.config import VeniceImageConfig
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ venice_base_url = "https://api.venice.ai" # Common base URL for all Venice endpoints
16
+
17
+
18
+ class VeniceImageBaseTool(IntentKitSkill):
19
+ """
20
+ Base class for all Venice AI image-related skills.
21
+
22
+ This class provides common functionality for interacting with the
23
+ Venice AI API, including:
24
+
25
+ - Retrieving the API key (from agent or system configuration).
26
+ - Applying rate limits to prevent overuse of the API.
27
+ - A standardized `post` method for making API requests.
28
+
29
+ Subclasses should inherit from this class and implement their specific
30
+ API interactions (e.g., image generation, upscaling, inpainting)
31
+ by defining their own `_arun` methods and setting appropriate `name`
32
+ and `description` attributes.
33
+ """
34
+
35
+ @property
36
+ def category(self) -> str:
37
+ """
38
+ Returns the category of this skill, used for configuration and logging.
39
+ """
40
+ return "venice_image"
41
+
42
+ def getSkillConfig(self, context) -> VeniceImageConfig:
43
+ """
44
+ Creates a VeniceImageConfig instance from a dictionary of configuration values.
45
+
46
+ Args:
47
+ config: A dictionary containing configuration settings.
48
+
49
+ Returns:
50
+ A VeniceImageConfig object.
51
+ """
52
+
53
+ skill_config = context.agent.skill_config(self.category)
54
+ return VeniceImageConfig(
55
+ api_key_provider=skill_config.get("api_key_provider", "agent_owner"),
56
+ safe_mode=skill_config.get("safe_mode", True),
57
+ hide_watermark=skill_config.get("hide_watermark", True),
58
+ embed_exif_metadata=skill_config.get("embed_exif_metadata", False),
59
+ negative_prompt=skill_config.get(
60
+ "negative_prompt", "(worst quality: 1.4), bad quality, nsfw"
61
+ ),
62
+ rate_limit_number=skill_config.get("rate_limit_number"),
63
+ rate_limit_minutes=skill_config.get("rate_limit_minutes"),
64
+ )
65
+
66
+ def get_api_key(self) -> str:
67
+ """
68
+ Retrieves the Venice AI API key based on the api_key_provider setting.
69
+
70
+ Returns:
71
+ The API key if found.
72
+
73
+ Raises:
74
+ ToolException: If the API key is not found or provider is invalid.
75
+ """
76
+ try:
77
+ context = self.get_context()
78
+ skillConfig = self.getSkillConfig(context=context)
79
+ if skillConfig.api_key_provider == "agent_owner":
80
+ skill_config = context.agent.skill_config(self.category)
81
+ agent_api_key = skill_config.get("api_key")
82
+ if agent_api_key:
83
+ logger.debug(
84
+ f"Using agent-specific Venice API key for skill {self.name} in category {self.category}"
85
+ )
86
+ return agent_api_key
87
+ raise ToolException(
88
+ f"No agent-owned Venice API key found for skill '{self.name}' in category '{self.category}'."
89
+ )
90
+
91
+ elif skillConfig.api_key_provider == "platform":
92
+ system_api_key = config.venice_api_key
93
+ if system_api_key:
94
+ logger.debug(
95
+ f"Using system Venice API key for skill {self.name} in category {self.category}"
96
+ )
97
+ return system_api_key
98
+ raise ToolException(
99
+ f"No platform-hosted Venice API key found for skill '{self.name}' in category '{self.category}'."
100
+ )
101
+
102
+ else:
103
+ raise ToolException(
104
+ f"Invalid API key provider '{skillConfig.api_key_provider}' for skill '{self.name}'"
105
+ )
106
+
107
+ except Exception as e:
108
+ raise ToolException(f"Failed to retrieve Venice API key: {str(e)}") from e
109
+
110
+ async def apply_venice_rate_limit(self, context) -> None:
111
+ """
112
+ Applies rate limiting to prevent exceeding the Venice AI API's rate limits.
113
+
114
+ Rate limits are applied based on the api_key_provider setting:
115
+ - 'agent_owner': uses agent-specific configuration.
116
+ - 'platform': uses system-wide configuration.
117
+ """
118
+ try:
119
+ # Get user_id from the agent context (venice_image only supports agent_owner)
120
+ skillConfig = self.getSkillConfig(context=context)
121
+
122
+ if skillConfig.api_key_provider == "agent_owner":
123
+ limit_num = skillConfig.rate_limit_number
124
+ limit_min = skillConfig.rate_limit_minutes
125
+
126
+ if limit_num and limit_min:
127
+ # For agent_owner, use agent.id as user_id for rate limiting
128
+ user_id = context.agent.id
129
+ logger.debug(
130
+ f"Applying Agent rate limit ({limit_num}/{limit_min} min) for user {user_id} on {self.name}"
131
+ )
132
+ await self.user_rate_limit_by_category(limit_num, limit_min * 60)
133
+
134
+ elif skillConfig.api_key_provider == "platform":
135
+ system_limit_num = getattr(
136
+ config, f"{self.category}_rate_limit_number", None
137
+ )
138
+ system_limit_min = getattr(
139
+ config, f"{self.category}_rate_limit_minutes", None
140
+ )
141
+
142
+ if system_limit_num and system_limit_min:
143
+ # For platform, use agent.id as user_id for rate limiting
144
+ user_id = context.agent.id
145
+ logger.debug(
146
+ f"Applying System rate limit ({system_limit_num}/{system_limit_min} min) for user {user_id} on {self.name}"
147
+ )
148
+ await self.user_rate_limit_by_category(
149
+ system_limit_num, system_limit_min * 60
150
+ )
151
+ # do nothing if no rate limit is
152
+ return None
153
+
154
+ except Exception as e:
155
+ raise ToolException(f"Failed to apply Venice rate limit: {str(e)}") from e
156
+
157
+ async def post(
158
+ self, path: str, payload: Dict[str, Any], context
159
+ ) -> Tuple[Dict[str, Any], Optional[Dict[str, Any]]]:
160
+ """
161
+ Makes a POST request to the Venice AI API using the `make_venice_api_request`
162
+ function from the `skills.venice_image.api` module.
163
+
164
+ This method handles the following:
165
+
166
+ 1. Retrieving the API key using `get_api_key`.
167
+ 2. Constructing the request payload.
168
+ 3. Calling `make_venice_api_request` to make the actual API call.
169
+ 4. Returning the results from `make_venice_api_request`.
170
+
171
+ Args:
172
+ path: The API endpoint path (e.g., "/api/v1/image/generate").
173
+ payload: The request payload as a dictionary.
174
+ context: The SkillContext for accessing API keys and configs.
175
+
176
+ Returns:
177
+ A tuple: (success_data, error_data).
178
+ - If successful, success contains the JSON response from the API.
179
+ - If an error occurs, success is an empty dictionary, and error contains error details.
180
+ """
181
+ api_key = self.get_api_key()
182
+
183
+ return await make_venice_api_request(
184
+ api_key, path, payload, self.category, self.name
185
+ )
@@ -3,7 +3,6 @@
3
3
  import logging
4
4
  from typing import TypedDict
5
5
 
6
- from intentkit.abstracts.skill import SkillStoreABC
7
6
  from intentkit.skills.base import SkillConfig, SkillOwnerState, SkillState
8
7
  from intentkit.skills.web_scraper.base import WebScraperBaseTool
9
8
  from intentkit.skills.web_scraper.document_indexer import DocumentIndexer
@@ -35,7 +34,6 @@ class Config(SkillConfig):
35
34
  async def get_skills(
36
35
  config: "Config",
37
36
  is_private: bool,
38
- store: SkillStoreABC,
39
37
  **_,
40
38
  ) -> list[WebScraperBaseTool]:
41
39
  """Get all web scraper skills.
@@ -43,7 +41,6 @@ async def get_skills(
43
41
  Args:
44
42
  config: The configuration for web scraper skills.
45
43
  is_private: Whether to include private skills.
46
- store: The skill store for persisting data.
47
44
 
48
45
  Returns:
49
46
  A list of web scraper skills.
@@ -60,7 +57,7 @@ async def get_skills(
60
57
  # Get each skill using the cached getter
61
58
  result = []
62
59
  for name in available_skills:
63
- skill = get_web_scraper_skill(name, store)
60
+ skill = get_web_scraper_skill(name)
64
61
  if skill:
65
62
  result.append(skill)
66
63
  return result
@@ -68,40 +65,30 @@ async def get_skills(
68
65
 
69
66
  def get_web_scraper_skill(
70
67
  name: str,
71
- store: SkillStoreABC,
72
68
  ) -> WebScraperBaseTool:
73
69
  """Get a web scraper skill by name.
74
70
 
75
71
  Args:
76
72
  name: The name of the skill to get
77
- store: The skill store for persisting data
78
73
 
79
74
  Returns:
80
75
  The requested web scraper skill
81
76
  """
82
77
  if name == "scrape_and_index":
83
78
  if name not in _cache:
84
- _cache[name] = ScrapeAndIndex(
85
- skill_store=store,
86
- )
79
+ _cache[name] = ScrapeAndIndex()
87
80
  return _cache[name]
88
81
  elif name == "query_indexed_content":
89
82
  if name not in _cache:
90
- _cache[name] = QueryIndexedContent(
91
- skill_store=store,
92
- )
83
+ _cache[name] = QueryIndexedContent()
93
84
  return _cache[name]
94
85
  elif name == "website_indexer":
95
86
  if name not in _cache:
96
- _cache[name] = WebsiteIndexer(
97
- skill_store=store,
98
- )
87
+ _cache[name] = WebsiteIndexer()
99
88
  return _cache[name]
100
89
  elif name == "document_indexer":
101
90
  if name not in _cache:
102
- _cache[name] = DocumentIndexer(
103
- skill_store=store,
104
- )
91
+ _cache[name] = DocumentIndexer()
105
92
  return _cache[name]
106
93
  else:
107
94
  logger.warning(f"Unknown web scraper skill: {name}")
@@ -1,8 +1,9 @@
1
1
  from typing import Type
2
2
 
3
+ from langchain_core.tools.base import ToolException
3
4
  from pydantic import BaseModel, Field
4
5
 
5
- from intentkit.abstracts.skill import SkillStoreABC
6
+ from intentkit.config.config import config
6
7
  from intentkit.skills.base import IntentKitSkill
7
8
 
8
9
 
@@ -12,10 +13,25 @@ class WebScraperBaseTool(IntentKitSkill):
12
13
  name: str = Field(description="The name of the tool")
13
14
  description: str = Field(description="A description of what the tool does")
14
15
  args_schema: Type[BaseModel]
15
- skill_store: SkillStoreABC = Field(
16
- description="The skill store for persisting data"
17
- )
18
16
 
19
17
  @property
20
18
  def category(self) -> str:
21
19
  return "web_scraper"
20
+
21
+ def get_openai_api_key(self) -> str:
22
+ """Retrieve the OpenAI API key for embedding operations."""
23
+ context = self.get_context()
24
+ skill_config = context.agent.skill_config(self.category)
25
+ api_key_provider = skill_config.get("api_key_provider")
26
+
27
+ if api_key_provider == "platform":
28
+ if not config.openai_api_key:
29
+ raise ToolException("OpenAI API key is not configured")
30
+ return config.openai_api_key
31
+
32
+ if skill_config.get("api_key"):
33
+ return skill_config["api_key"]
34
+
35
+ raise ToolException(
36
+ f"Invalid API key provider: {api_key_provider}, or no api_key in config"
37
+ )
@@ -108,17 +108,19 @@ class DocumentIndexer(WebScraperBaseTool):
108
108
  f"[{agent_id}] Document created, length: {len(document.page_content)} chars"
109
109
  )
110
110
 
111
+ embedding_api_key = self.get_openai_api_key()
112
+ vector_manager = VectorStoreManager(embedding_api_key)
113
+
111
114
  # Index the document
112
115
  total_chunks, was_merged = await index_documents(
113
- [document], agent_id, self.skill_store, chunk_size, chunk_overlap
116
+ [document], agent_id, vector_manager, chunk_size, chunk_overlap
114
117
  )
115
118
 
116
119
  # Get current storage size for response
117
- vs_manager = VectorStoreManager(self.skill_store)
118
- current_size = await vs_manager.get_content_size(agent_id)
120
+ current_size = await vector_manager.get_content_size(agent_id)
119
121
 
120
122
  # Update metadata
121
- metadata_manager = MetadataManager(self.skill_store)
123
+ metadata_manager = MetadataManager(vector_manager)
122
124
  new_metadata = metadata_manager.create_document_metadata(
123
125
  title, source, tags, [document], len(text_content)
124
126
  )
@@ -92,9 +92,12 @@ class ScrapeAndIndex(WebScraperBaseTool):
92
92
  f"[{agent_id}] Starting scrape and index operation with {len(urls)} URLs"
93
93
  )
94
94
 
95
+ embedding_api_key = self.get_openai_api_key()
96
+ vector_manager = VectorStoreManager(embedding_api_key)
97
+
95
98
  # Use the utility function to scrape and index URLs
96
99
  total_chunks, was_merged, valid_urls = await scrape_and_index_urls(
97
- urls, agent_id, self.skill_store, chunk_size, chunk_overlap
100
+ urls, agent_id, vector_manager, chunk_size, chunk_overlap
98
101
  )
99
102
 
100
103
  logger.info(
@@ -110,12 +113,11 @@ class ScrapeAndIndex(WebScraperBaseTool):
110
113
  return "Error: No content could be extracted from the provided URLs."
111
114
 
112
115
  # Get current storage size for response
113
- vs_manager = VectorStoreManager(self.skill_store)
114
- current_size = await vs_manager.get_content_size(agent_id)
116
+ current_size = await vector_manager.get_content_size(agent_id)
115
117
  size_limit_reached = len(valid_urls) < len(urls)
116
118
 
117
119
  # Update metadata
118
- metadata_manager = MetadataManager(self.skill_store)
120
+ metadata_manager = MetadataManager(vector_manager)
119
121
  new_metadata = metadata_manager.create_url_metadata(
120
122
  valid_urls, [], "scrape_and_index"
121
123
  )
@@ -196,8 +198,9 @@ class QueryIndexedContent(WebScraperBaseTool):
196
198
 
197
199
  logger.info(f"[{agent_id}] Looking for vector store: {vector_store_key}")
198
200
 
199
- vs_manager = VectorStoreManager(self.skill_store)
200
- stored_data = await vs_manager.get_existing_vector_store(agent_id)
201
+ embedding_api_key = self.get_openai_api_key()
202
+ vector_manager = VectorStoreManager(embedding_api_key)
203
+ stored_data = await vector_manager.get_existing_vector_store(agent_id)
201
204
 
202
205
  if not stored_data:
203
206
  logger.warning(f"[{agent_id}] No vector store found")
@@ -209,8 +212,8 @@ class QueryIndexedContent(WebScraperBaseTool):
209
212
 
210
213
  # Create embeddings and decode vector store
211
214
  logger.info(f"[{agent_id}] Decoding vector store")
212
- embeddings = vs_manager.create_embeddings()
213
- vector_store = vs_manager.decode_vector_store(
215
+ embeddings = vector_manager.create_embeddings()
216
+ vector_store = vector_manager.decode_vector_store(
214
217
  stored_data["faiss_files"], embeddings
215
218
  )
216
219