intentkit 0.6.9.dev1__py3-none-any.whl → 0.6.10__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 (170) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/graph.py +17 -2
  3. intentkit/core/engine.py +49 -30
  4. intentkit/core/node.py +10 -20
  5. intentkit/models/agent.py +215 -11
  6. intentkit/models/agent_schema.json +4 -0
  7. intentkit/models/chat.py +9 -1
  8. intentkit/models/llm.py +53 -0
  9. intentkit/skills/acolyt/ask.py +2 -5
  10. intentkit/skills/acolyt/base.py +16 -6
  11. intentkit/skills/aixbt/__init__.py +3 -7
  12. intentkit/skills/aixbt/projects.py +12 -36
  13. intentkit/skills/allora/base.py +16 -6
  14. intentkit/skills/allora/price.py +2 -4
  15. intentkit/skills/base.py +8 -1
  16. intentkit/skills/carv/base.py +12 -10
  17. intentkit/skills/carv/fetch_news.py +90 -92
  18. intentkit/skills/carv/onchain_query.py +162 -164
  19. intentkit/skills/carv/token_info_and_price.py +108 -110
  20. intentkit/skills/chainlist/chain_lookup.py +1 -2
  21. intentkit/skills/common/current_time.py +1 -2
  22. intentkit/skills/cookiefun/base.py +20 -12
  23. intentkit/skills/cookiefun/get_account_details.py +1 -3
  24. intentkit/skills/cookiefun/get_account_feed.py +1 -3
  25. intentkit/skills/cookiefun/get_account_smart_followers.py +1 -3
  26. intentkit/skills/cookiefun/get_sectors.py +2 -3
  27. intentkit/skills/cookiefun/search_accounts.py +1 -3
  28. intentkit/skills/cryptocompare/fetch_news.py +3 -4
  29. intentkit/skills/cryptocompare/fetch_price.py +3 -4
  30. intentkit/skills/cryptocompare/fetch_top_exchanges.py +3 -4
  31. intentkit/skills/cryptocompare/fetch_top_market_cap.py +3 -4
  32. intentkit/skills/cryptocompare/fetch_top_volume.py +3 -4
  33. intentkit/skills/cryptocompare/fetch_trading_signals.py +3 -4
  34. intentkit/skills/cryptopanic/base.py +13 -9
  35. intentkit/skills/cryptopanic/fetch_crypto_news.py +150 -153
  36. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +133 -136
  37. intentkit/skills/dapplooker/base.py +16 -6
  38. intentkit/skills/dapplooker/dapplooker_token_data.py +2 -4
  39. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +2 -3
  40. intentkit/skills/defillama/coins/fetch_block.py +2 -3
  41. intentkit/skills/defillama/coins/fetch_current_prices.py +2 -5
  42. intentkit/skills/defillama/coins/fetch_first_price.py +2 -5
  43. intentkit/skills/defillama/coins/fetch_historical_prices.py +2 -3
  44. intentkit/skills/defillama/coins/fetch_price_chart.py +2 -5
  45. intentkit/skills/defillama/coins/fetch_price_percentage.py +2 -5
  46. intentkit/skills/defillama/fees/fetch_fees_overview.py +2 -3
  47. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +2 -3
  48. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +2 -3
  49. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +2 -3
  50. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +2 -3
  51. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +2 -5
  52. intentkit/skills/defillama/tvl/fetch_chains.py +2 -3
  53. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +2 -3
  54. intentkit/skills/defillama/tvl/fetch_protocol.py +2 -5
  55. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +2 -5
  56. intentkit/skills/defillama/tvl/fetch_protocols.py +2 -3
  57. intentkit/skills/defillama/volumes/fetch_dex_overview.py +2 -3
  58. intentkit/skills/defillama/volumes/fetch_dex_summary.py +2 -5
  59. intentkit/skills/defillama/volumes/fetch_options_overview.py +2 -3
  60. intentkit/skills/defillama/yields/fetch_pool_chart.py +2 -5
  61. intentkit/skills/defillama/yields/fetch_pools.py +2 -3
  62. intentkit/skills/dune_analytics/base.py +15 -9
  63. intentkit/skills/dune_analytics/fetch_kol_buys.py +125 -128
  64. intentkit/skills/dune_analytics/fetch_nation_metrics.py +234 -237
  65. intentkit/skills/elfa/base.py +16 -6
  66. intentkit/skills/elfa/mention.py +2 -7
  67. intentkit/skills/elfa/stats.py +2 -6
  68. intentkit/skills/elfa/tokens.py +1 -4
  69. intentkit/skills/enso/base.py +25 -13
  70. intentkit/skills/enso/best_yield.py +1 -4
  71. intentkit/skills/enso/networks.py +2 -5
  72. intentkit/skills/enso/prices.py +1 -5
  73. intentkit/skills/enso/route.py +2 -5
  74. intentkit/skills/enso/tokens.py +1 -4
  75. intentkit/skills/enso/wallet.py +3 -9
  76. intentkit/skills/firecrawl/base.py +16 -6
  77. intentkit/skills/firecrawl/clear.py +1 -3
  78. intentkit/skills/firecrawl/crawl.py +7 -8
  79. intentkit/skills/firecrawl/query.py +7 -9
  80. intentkit/skills/firecrawl/scrape.py +7 -8
  81. intentkit/skills/github/github_search.py +1 -3
  82. intentkit/skills/heurist/base.py +15 -0
  83. intentkit/skills/heurist/image_generation_animagine_xl.py +3 -4
  84. intentkit/skills/heurist/image_generation_arthemy_comics.py +3 -4
  85. intentkit/skills/heurist/image_generation_arthemy_real.py +3 -4
  86. intentkit/skills/heurist/image_generation_braindance.py +3 -4
  87. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +3 -4
  88. intentkit/skills/heurist/image_generation_flux_1_dev.py +3 -4
  89. intentkit/skills/heurist/image_generation_sdxl.py +3 -4
  90. intentkit/skills/http/get.py +0 -2
  91. intentkit/skills/http/post.py +0 -2
  92. intentkit/skills/http/put.py +0 -2
  93. intentkit/skills/lifi/token_execute.py +1 -3
  94. intentkit/skills/lifi/token_quote.py +0 -2
  95. intentkit/skills/moralis/base.py +15 -1
  96. intentkit/skills/nation/nft_check.py +2 -5
  97. intentkit/skills/openai/base.py +14 -5
  98. intentkit/skills/openai/dalle_image_generation.py +6 -5
  99. intentkit/skills/openai/gpt_image_generation.py +6 -5
  100. intentkit/skills/openai/gpt_image_to_image.py +6 -5
  101. intentkit/skills/openai/image_to_text.py +6 -6
  102. intentkit/skills/portfolio/base.py +4 -3
  103. intentkit/skills/portfolio/token_balances.py +2 -4
  104. intentkit/skills/portfolio/wallet_approvals.py +2 -4
  105. intentkit/skills/portfolio/wallet_defi_positions.py +3 -4
  106. intentkit/skills/portfolio/wallet_history.py +2 -4
  107. intentkit/skills/portfolio/wallet_net_worth.py +2 -4
  108. intentkit/skills/portfolio/wallet_nfts.py +2 -4
  109. intentkit/skills/portfolio/wallet_profitability.py +2 -4
  110. intentkit/skills/portfolio/wallet_profitability_summary.py +2 -4
  111. intentkit/skills/portfolio/wallet_stats.py +2 -4
  112. intentkit/skills/portfolio/wallet_swaps.py +2 -4
  113. intentkit/skills/slack/base.py +18 -0
  114. intentkit/skills/slack/get_channel.py +3 -4
  115. intentkit/skills/slack/get_message.py +3 -4
  116. intentkit/skills/slack/schedule_message.py +3 -4
  117. intentkit/skills/slack/send_message.py +3 -4
  118. intentkit/skills/supabase/delete_data.py +3 -6
  119. intentkit/skills/supabase/fetch_data.py +3 -6
  120. intentkit/skills/supabase/insert_data.py +3 -6
  121. intentkit/skills/supabase/invoke_function.py +3 -6
  122. intentkit/skills/supabase/update_data.py +3 -6
  123. intentkit/skills/supabase/upsert_data.py +3 -6
  124. intentkit/skills/system/add_autonomous_task.py +1 -3
  125. intentkit/skills/system/delete_autonomous_task.py +1 -3
  126. intentkit/skills/system/edit_autonomous_task.py +1 -3
  127. intentkit/skills/system/list_autonomous_tasks.py +1 -3
  128. intentkit/skills/system/read_agent_api_key.py +2 -3
  129. intentkit/skills/system/regenerate_agent_api_key.py +2 -5
  130. intentkit/skills/tavily/base.py +14 -5
  131. intentkit/skills/tavily/tavily_extract.py +7 -8
  132. intentkit/skills/tavily/tavily_search.py +11 -9
  133. intentkit/skills/token/base.py +4 -6
  134. intentkit/skills/token/erc20_transfers.py +2 -4
  135. intentkit/skills/token/token_analytics.py +2 -4
  136. intentkit/skills/token/token_price.py +2 -4
  137. intentkit/skills/token/token_search.py +2 -4
  138. intentkit/skills/twitter/base.py +41 -0
  139. intentkit/skills/twitter/follow_user.py +4 -4
  140. intentkit/skills/twitter/get_mentions.py +4 -4
  141. intentkit/skills/twitter/get_timeline.py +4 -4
  142. intentkit/skills/twitter/get_user_by_username.py +4 -4
  143. intentkit/skills/twitter/get_user_tweets.py +4 -4
  144. intentkit/skills/twitter/like_tweet.py +4 -4
  145. intentkit/skills/twitter/post_tweet.py +3 -4
  146. intentkit/skills/twitter/reply_tweet.py +3 -4
  147. intentkit/skills/twitter/retweet.py +4 -4
  148. intentkit/skills/twitter/search_tweets.py +4 -4
  149. intentkit/skills/unrealspeech/base.py +16 -0
  150. intentkit/skills/unrealspeech/text_to_speech.py +4 -4
  151. intentkit/skills/venice_audio/base.py +11 -9
  152. intentkit/skills/venice_audio/venice_audio.py +238 -240
  153. intentkit/skills/venice_image/base.py +23 -19
  154. intentkit/skills/venice_image/image_enhance/image_enhance.py +78 -80
  155. intentkit/skills/venice_image/image_generation/image_generation_base.py +115 -117
  156. intentkit/skills/venice_image/image_upscale/image_upscale.py +88 -90
  157. intentkit/skills/venice_image/image_vision/image_vision.py +98 -100
  158. intentkit/skills/web_scraper/document_indexer.py +3 -5
  159. intentkit/skills/web_scraper/scrape_and_index.py +14 -17
  160. intentkit/skills/web_scraper/website_indexer.py +8 -10
  161. intentkit/skills/xmtp/README.md +110 -0
  162. intentkit/skills/xmtp/__init__.py +82 -0
  163. intentkit/skills/xmtp/base.py +15 -0
  164. intentkit/skills/xmtp/schema.json +43 -0
  165. intentkit/skills/xmtp/transfer.py +155 -0
  166. intentkit/skills/xmtp/xmtp.png +0 -0
  167. {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dist-info}/METADATA +4 -3
  168. {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dist-info}/RECORD +170 -164
  169. {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dist-info}/WHEEL +0 -0
  170. {intentkit-0.6.9.dev1.dist-info → intentkit-0.6.10.dist-info}/licenses/LICENSE +0 -0
@@ -1,164 +1,162 @@
1
- import logging
2
- from decimal import Decimal, InvalidOperation
3
- from typing import Any, Dict, Literal, Type
4
-
5
- from langchain_core.runnables import RunnableConfig
6
- from pydantic import BaseModel, Field
7
-
8
- from intentkit.skills.carv.base import CarvBaseTool
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- class CarvInput(BaseModel):
14
- """
15
- Input schema for CARV SQL Query API.
16
- Defines parameters controllable by the user when invoking the tool.
17
- """
18
-
19
- question: str = Field(
20
- ...,
21
- description="The question to query on-chain data.",
22
- )
23
- chain: Literal["ethereum", "base", "bitcoin", "solana"] = Field(
24
- ...,
25
- description="supported chain is ethereum, base, bitcoin, solana",
26
- )
27
-
28
-
29
- class OnchainQueryTool(CarvBaseTool):
30
- """
31
- Tool for querying on-chain data using natural language via the CARV SQL Query API.
32
-
33
- This tool allows you to ask questions about blockchain data in plain English, and it will return
34
- the relevant information. Behind the scenes, it uses the CARV API to convert your question into a SQL query
35
- and retrieve the results.
36
-
37
- Supported Blockchains: Ethereum, Base, Bitcoin, and Solana.
38
-
39
- If the question is about a blockchain other than the ones listed above, or is not a clear question, the
40
- tool will return an error.
41
- """
42
-
43
- name: str = "carv_onchain_query"
44
- description: str = (
45
- "Query blockchain data from Ethereum, Base, Bitcoin, or Solana using natural language. "
46
- "This tool provides access to detailed metrics including block information (timestamps, hashes, miners, gas used/limits), "
47
- "transaction details (hashes, sender/receiver addresses, amounts, gas prices), and overall network utilization. "
48
- "It supports aggregate analytics such as daily transaction counts, average gas prices, top wallet activity, and blockchain growth trends. "
49
- "You can filter results by time range, address type, transaction value, and other parameters.\n\n"
50
- "IMPORTANT Rules:\n"
51
- "- Only Ethereum, Base, Bitcoin, and Solana are supported.\n"
52
- "- Always infer the target blockchain from the user's query.\n"
53
- "- If an unsupported blockchain is requested, clearly explain the limitation.\n"
54
- "- Convert user input into a specific and actionable natural language query (e.g., "
55
- '"What\'s the most active address on Ethereum over the past 24 hours?" or '
56
- '"Show the largest ETH transaction in the last 30 days").\n'
57
- "- Respond in clear, concise natural language using only the data returned by the tool.\n"
58
- "- Avoid markdown or bullet points unless explicitly requested.\n"
59
- "- ETH values are denominated in 18 decimals—consider 10^18 when interpreting amounts.\n"
60
- "- Never fabricate or infer data beyond what the tool provides."
61
- )
62
- args_schema: Type[BaseModel] = CarvInput
63
-
64
- async def _arun(
65
- self,
66
- question: str,
67
- chain: str,
68
- config: RunnableConfig = None, # type: ignore
69
- **kwargs: Any,
70
- ) -> Dict[str, Any]:
71
- """
72
- Queries the CARV SQL Query API and returns the response.
73
- """
74
- context = self.context_from_config(config)
75
- try:
76
- await self.apply_rate_limit(context)
77
-
78
- payload = {"question": question}
79
-
80
- result, error = await self._call_carv_api(
81
- context=context,
82
- endpoint="/ai-agent-backend/sql_query_by_llm",
83
- method="POST",
84
- payload=payload,
85
- )
86
-
87
- if error is not None or result is None:
88
- logger.error(f"Error returned from CARV API: {error}")
89
- return {
90
- "error": True,
91
- "error_type": "APIError",
92
- "message": "Failed to fetch data from CARV API.",
93
- "details": error,
94
- }
95
-
96
- _normalize_unit(result, chain)
97
- return {"success": True, **result}
98
-
99
- except Exception as e:
100
- logger.error(f"An unexpected error occurred: {e}", exc_info=True)
101
- return {
102
- "error": True,
103
- "error_type": type(e).__name__,
104
- "message": "An unexpected error occurred.",
105
- "details": str(e),
106
- }
107
-
108
-
109
- def _normalize_unit(response_data: Dict[str, Any], chain: str) -> None:
110
- """
111
- Normalizes the 'value' field in on-chain response data to a human-readable format.
112
- Adds the corresponding token ticker after the value.
113
-
114
- Supported chains:
115
- - Ethereum: 10^18 -> ETH
116
- - Base: 10^18 -> ETH
117
- - Solana: 10^9 -> SOL
118
- - Bitcoin: 10^8 -> BTC
119
- """
120
- column_infos = response_data.get("column_infos", [])
121
- rows = response_data.get("rows", [])
122
-
123
- if "value" not in column_infos:
124
- return
125
-
126
- value_index = column_infos.index("value")
127
-
128
- chain = chain.lower()
129
- if chain == "ethereum":
130
- divisor = Decimal("1e18")
131
- ticker = "ETH"
132
- elif chain == "base":
133
- divisor = Decimal("1e18")
134
- ticker = "ETH"
135
- elif chain == "solana":
136
- divisor = Decimal("1e9")
137
- ticker = "SOL"
138
- elif chain == "bitcoin":
139
- divisor = Decimal("1e8")
140
- ticker = "BTC"
141
- else:
142
- logger.warning(f"Unsupported chain '{chain}' for unit normalization.")
143
- return
144
-
145
- for row in rows:
146
- items = row.get("items", [])
147
- if len(items) > value_index:
148
- original_value = items[value_index]
149
- try:
150
- normalized = str(original_value).strip()
151
- try:
152
- value_decimal = Decimal(normalized)
153
- except InvalidOperation:
154
- value_decimal = Decimal.from_float(float(normalized))
155
-
156
- converted = value_decimal / divisor
157
- formatted_value = (
158
- format(converted, "f").rstrip("0").rstrip(".")
159
- if "." in format(converted, "f")
160
- else format(converted, "f")
161
- )
162
- items[value_index] = f"{formatted_value} {ticker}"
163
- except Exception as e:
164
- logger.warning(f"Unable to normalize value '{original_value}': {e}")
1
+ import logging
2
+ from decimal import Decimal, InvalidOperation
3
+ from typing import Any, Dict, Literal, Type
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from intentkit.skills.carv.base import CarvBaseTool
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class CarvInput(BaseModel):
13
+ """
14
+ Input schema for CARV SQL Query API.
15
+ Defines parameters controllable by the user when invoking the tool.
16
+ """
17
+
18
+ question: str = Field(
19
+ ...,
20
+ description="The question to query on-chain data.",
21
+ )
22
+ chain: Literal["ethereum", "base", "bitcoin", "solana"] = Field(
23
+ ...,
24
+ description="supported chain is ethereum, base, bitcoin, solana",
25
+ )
26
+
27
+
28
+ class OnchainQueryTool(CarvBaseTool):
29
+ """
30
+ Tool for querying on-chain data using natural language via the CARV SQL Query API.
31
+
32
+ This tool allows you to ask questions about blockchain data in plain English, and it will return
33
+ the relevant information. Behind the scenes, it uses the CARV API to convert your question into a SQL query
34
+ and retrieve the results.
35
+
36
+ Supported Blockchains: Ethereum, Base, Bitcoin, and Solana.
37
+
38
+ If the question is about a blockchain other than the ones listed above, or is not a clear question, the
39
+ tool will return an error.
40
+ """
41
+
42
+ name: str = "carv_onchain_query"
43
+ description: str = (
44
+ "Query blockchain data from Ethereum, Base, Bitcoin, or Solana using natural language. "
45
+ "This tool provides access to detailed metrics including block information (timestamps, hashes, miners, gas used/limits), "
46
+ "transaction details (hashes, sender/receiver addresses, amounts, gas prices), and overall network utilization. "
47
+ "It supports aggregate analytics such as daily transaction counts, average gas prices, top wallet activity, and blockchain growth trends. "
48
+ "You can filter results by time range, address type, transaction value, and other parameters.\n\n"
49
+ "IMPORTANT Rules:\n"
50
+ "- Only Ethereum, Base, Bitcoin, and Solana are supported.\n"
51
+ "- Always infer the target blockchain from the user's query.\n"
52
+ "- If an unsupported blockchain is requested, clearly explain the limitation.\n"
53
+ "- Convert user input into a specific and actionable natural language query (e.g., "
54
+ '"What\'s the most active address on Ethereum over the past 24 hours?" or '
55
+ '"Show the largest ETH transaction in the last 30 days").\n'
56
+ "- Respond in clear, concise natural language using only the data returned by the tool.\n"
57
+ "- Avoid markdown or bullet points unless explicitly requested.\n"
58
+ "- ETH values are denominated in 18 decimals—consider 10^18 when interpreting amounts.\n"
59
+ "- Never fabricate or infer data beyond what the tool provides."
60
+ )
61
+ args_schema: Type[BaseModel] = CarvInput
62
+
63
+ async def _arun(
64
+ self,
65
+ question: str,
66
+ chain: str, # type: ignore
67
+ **kwargs: Any,
68
+ ) -> Dict[str, Any]:
69
+ """
70
+ Queries the CARV SQL Query API and returns the response.
71
+ """
72
+ context = self.get_context()
73
+ try:
74
+ await self.apply_rate_limit(context)
75
+
76
+ payload = {"question": question}
77
+
78
+ result, error = await self._call_carv_api(
79
+ context=context,
80
+ endpoint="/ai-agent-backend/sql_query_by_llm",
81
+ method="POST",
82
+ payload=payload,
83
+ )
84
+
85
+ if error is not None or result is None:
86
+ logger.error(f"Error returned from CARV API: {error}")
87
+ return {
88
+ "error": True,
89
+ "error_type": "APIError",
90
+ "message": "Failed to fetch data from CARV API.",
91
+ "details": error,
92
+ }
93
+
94
+ _normalize_unit(result, chain)
95
+ return {"success": True, **result}
96
+
97
+ except Exception as e:
98
+ logger.error(f"An unexpected error occurred: {e}", exc_info=True)
99
+ return {
100
+ "error": True,
101
+ "error_type": type(e).__name__,
102
+ "message": "An unexpected error occurred.",
103
+ "details": str(e),
104
+ }
105
+
106
+
107
+ def _normalize_unit(response_data: Dict[str, Any], chain: str) -> None:
108
+ """
109
+ Normalizes the 'value' field in on-chain response data to a human-readable format.
110
+ Adds the corresponding token ticker after the value.
111
+
112
+ Supported chains:
113
+ - Ethereum: 10^18 -> ETH
114
+ - Base: 10^18 -> ETH
115
+ - Solana: 10^9 -> SOL
116
+ - Bitcoin: 10^8 -> BTC
117
+ """
118
+ column_infos = response_data.get("column_infos", [])
119
+ rows = response_data.get("rows", [])
120
+
121
+ if "value" not in column_infos:
122
+ return
123
+
124
+ value_index = column_infos.index("value")
125
+
126
+ chain = chain.lower()
127
+ if chain == "ethereum":
128
+ divisor = Decimal("1e18")
129
+ ticker = "ETH"
130
+ elif chain == "base":
131
+ divisor = Decimal("1e18")
132
+ ticker = "ETH"
133
+ elif chain == "solana":
134
+ divisor = Decimal("1e9")
135
+ ticker = "SOL"
136
+ elif chain == "bitcoin":
137
+ divisor = Decimal("1e8")
138
+ ticker = "BTC"
139
+ else:
140
+ logger.warning(f"Unsupported chain '{chain}' for unit normalization.")
141
+ return
142
+
143
+ for row in rows:
144
+ items = row.get("items", [])
145
+ if len(items) > value_index:
146
+ original_value = items[value_index]
147
+ try:
148
+ normalized = str(original_value).strip()
149
+ try:
150
+ value_decimal = Decimal(normalized)
151
+ except InvalidOperation:
152
+ value_decimal = Decimal.from_float(float(normalized))
153
+
154
+ converted = value_decimal / divisor
155
+ formatted_value = (
156
+ format(converted, "f").rstrip("0").rstrip(".")
157
+ if "." in format(converted, "f")
158
+ else format(converted, "f")
159
+ )
160
+ items[value_index] = f"{formatted_value} {ticker}"
161
+ except Exception as e:
162
+ logger.warning(f"Unable to normalize value '{original_value}': {e}")
@@ -1,110 +1,108 @@
1
- import logging
2
- import re
3
- from typing import Any, Dict, Optional, Type
4
-
5
- from langchain_core.runnables import RunnableConfig
6
- from pydantic import BaseModel, Field
7
-
8
- from intentkit.skills.carv.base import CarvBaseTool
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- class TokenInfoAndPriceInput(BaseModel):
14
- ticker: str = Field(
15
- description="The token's ticker symbol (e.g., 'eth', 'btc', 'sol', 'xrp')."
16
- )
17
- token_name: str = Field(
18
- description="The token name (e.g ethereum, bitcoin, solana, ripple)"
19
- )
20
- amount: Optional[float] = Field(
21
- description="(optional) amount of token, fill this if user asking for how much x amount of specific token worth"
22
- )
23
-
24
-
25
- class TokenInfoAndPriceTool(CarvBaseTool):
26
- """
27
- Fetches detailed information and the current USD price of a cryptocurrency token from the CARV API,
28
- given its ticker symbol (e.g., 'eth', 'btc', 'aave').
29
- Returns metadata including the token's name, symbol, platform, category tags, and contract addresses
30
- Useful for understanding a token's identity, ecosystem, and market valu
31
- Use this tool when you need comprehensive token data and live pricing from CARV
32
- """
33
-
34
- name: str = "carv_token_info_and_price"
35
- description: str = (
36
- "Fetches detailed information and the current USD price of a cryptocurrency token from the CARV API, "
37
- "given its ticker symbol (e.g., 'eth', 'btc', 'aave'). or token name"
38
- "Returns metadata including the token's name, symbol, platform, category tags, and contract addresses "
39
- "Useful for understanding a token's identity, ecosystem, and market value"
40
- "Use this tool when you need comprehensive token data and live pricing from CARV."
41
- )
42
- args_schema: Type[BaseModel] = TokenInfoAndPriceInput
43
-
44
- async def _arun(
45
- self,
46
- ticker: str,
47
- token_name: str,
48
- amount: Optional[float] = 1,
49
- config: RunnableConfig = None, # type: ignore
50
- **kwargs: Any,
51
- ) -> Dict[str, Any]:
52
- if not ticker:
53
- return {
54
- "error": True,
55
- "message": "ticker is null",
56
- "suggestion": "ask the user for the specific ticker, and fill the `ticker` field when calling this tool",
57
- }
58
-
59
- context = self.context_from_config(config)
60
- params = {"ticker": ticker}
61
- path = "/ai-agent-backend/token_info"
62
- method = "GET"
63
-
64
- result, error = await self._call_carv_api(
65
- context=context,
66
- endpoint=path,
67
- params=params,
68
- method=method,
69
- )
70
-
71
- if error is not None or result is None:
72
- logger.error(f"Error returned from CARV API: {error}")
73
- return {
74
- "error": True,
75
- "error_type": "APIError",
76
- "message": "Failed to fetch token info from CARV API.",
77
- "details": error,
78
- }
79
-
80
- # retry with token_name if price is 0 or missing
81
- if "price" not in result or result["price"] == 0:
82
- fallback_ticker = re.sub(r"\s+", "-", token_name.strip().lower())
83
- logger.info(
84
- f"Fallback triggered. Trying with fallback ticker: {fallback_ticker}"
85
- )
86
-
87
- fallback_params = {"ticker": fallback_ticker}
88
- result, error = await self._call_carv_api(
89
- context=context,
90
- endpoint=path,
91
- params=fallback_params,
92
- method=method,
93
- )
94
-
95
- if error is not None or result is None or result.get("price") == 0:
96
- logger.error(f"Fallback error returned from CARV API: {error}")
97
- return {
98
- "error": True,
99
- "error_type": "APIError",
100
- "message": "Failed to fetch token info from CARV API with fallback.",
101
- "details": error,
102
- }
103
-
104
- if "price" in result and amount is not None:
105
- return {
106
- "additional_info": f"{amount} {ticker.upper()} is worth ${round(amount * result['price'], 2)}",
107
- **result,
108
- }
109
-
110
- return result
1
+ import logging
2
+ import re
3
+ from typing import Any, Dict, Optional, Type
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from intentkit.skills.carv.base import CarvBaseTool
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class TokenInfoAndPriceInput(BaseModel):
13
+ ticker: str = Field(
14
+ description="The token's ticker symbol (e.g., 'eth', 'btc', 'sol', 'xrp')."
15
+ )
16
+ token_name: str = Field(
17
+ description="The token name (e.g ethereum, bitcoin, solana, ripple)"
18
+ )
19
+ amount: Optional[float] = Field(
20
+ description="(optional) amount of token, fill this if user asking for how much x amount of specific token worth"
21
+ )
22
+
23
+
24
+ class TokenInfoAndPriceTool(CarvBaseTool):
25
+ """
26
+ Fetches detailed information and the current USD price of a cryptocurrency token from the CARV API,
27
+ given its ticker symbol (e.g., 'eth', 'btc', 'aave').
28
+ Returns metadata including the token's name, symbol, platform, category tags, and contract addresses
29
+ Useful for understanding a token's identity, ecosystem, and market valu
30
+ Use this tool when you need comprehensive token data and live pricing from CARV
31
+ """
32
+
33
+ name: str = "carv_token_info_and_price"
34
+ description: str = (
35
+ "Fetches detailed information and the current USD price of a cryptocurrency token from the CARV API, "
36
+ "given its ticker symbol (e.g., 'eth', 'btc', 'aave'). or token name"
37
+ "Returns metadata including the token's name, symbol, platform, category tags, and contract addresses "
38
+ "Useful for understanding a token's identity, ecosystem, and market value"
39
+ "Use this tool when you need comprehensive token data and live pricing from CARV."
40
+ )
41
+ args_schema: Type[BaseModel] = TokenInfoAndPriceInput
42
+
43
+ async def _arun(
44
+ self,
45
+ ticker: str,
46
+ token_name: str,
47
+ amount: Optional[float] = 1, # type: ignore
48
+ **kwargs: Any,
49
+ ) -> Dict[str, Any]:
50
+ if not ticker:
51
+ return {
52
+ "error": True,
53
+ "message": "ticker is null",
54
+ "suggestion": "ask the user for the specific ticker, and fill the `ticker` field when calling this tool",
55
+ }
56
+
57
+ context = self.get_context()
58
+ params = {"ticker": ticker}
59
+ path = "/ai-agent-backend/token_info"
60
+ method = "GET"
61
+
62
+ result, error = await self._call_carv_api(
63
+ context=context,
64
+ endpoint=path,
65
+ params=params,
66
+ method=method,
67
+ )
68
+
69
+ if error is not None or result is None:
70
+ logger.error(f"Error returned from CARV API: {error}")
71
+ return {
72
+ "error": True,
73
+ "error_type": "APIError",
74
+ "message": "Failed to fetch token info from CARV API.",
75
+ "details": error,
76
+ }
77
+
78
+ # retry with token_name if price is 0 or missing
79
+ if "price" not in result or result["price"] == 0:
80
+ fallback_ticker = re.sub(r"\s+", "-", token_name.strip().lower())
81
+ logger.info(
82
+ f"Fallback triggered. Trying with fallback ticker: {fallback_ticker}"
83
+ )
84
+
85
+ fallback_params = {"ticker": fallback_ticker}
86
+ result, error = await self._call_carv_api(
87
+ context=context,
88
+ endpoint=path,
89
+ params=fallback_params,
90
+ method=method,
91
+ )
92
+
93
+ if error is not None or result is None or result.get("price") == 0:
94
+ logger.error(f"Fallback error returned from CARV API: {error}")
95
+ return {
96
+ "error": True,
97
+ "error_type": "APIError",
98
+ "message": "Failed to fetch token info from CARV API with fallback.",
99
+ "details": error,
100
+ }
101
+
102
+ if "price" in result and amount is not None:
103
+ return {
104
+ "additional_info": f"{amount} {ticker.upper()} is worth ${round(amount * result['price'], 2)}",
105
+ **result,
106
+ }
107
+
108
+ return result
@@ -2,7 +2,6 @@ import logging
2
2
  from typing import Any, Dict, List, Optional, Type
3
3
 
4
4
  import httpx
5
- from langchain_core.runnables import RunnableConfig
6
5
  from pydantic import BaseModel, Field
7
6
 
8
7
  from intentkit.skills.chainlist.base import ChainlistBaseTool
@@ -160,7 +159,7 @@ class ChainLookup(ChainlistBaseTool):
160
159
  chain_id: Optional[int] = None,
161
160
  no_tracking: Optional[bool] = False,
162
161
  limit: Optional[int] = 5,
163
- config: Optional[RunnableConfig] = None,
162
+ config: Optional[Any] = None,
164
163
  **kwargs,
165
164
  ) -> Dict:
166
165
  """Lookup blockchain RPC endpoints from Chainlist."""
@@ -3,7 +3,6 @@ from datetime import datetime
3
3
  from typing import Type
4
4
 
5
5
  import pytz
6
- from langchain_core.runnables import RunnableConfig
7
6
  from pydantic import BaseModel, Field
8
7
 
9
8
  from intentkit.skills.common.base import CommonBaseTool
@@ -39,7 +38,7 @@ class CurrentTime(CommonBaseTool):
39
38
  )
40
39
  args_schema: Type[BaseModel] = CurrentTimeInput
41
40
 
42
- async def _arun(self, timezone: str, config: RunnableConfig, **kwargs) -> str:
41
+ async def _arun(self, timezone: str, **kwargs) -> str:
43
42
  """Implementation of the tool to get the current time.
44
43
 
45
44
  Args:
@@ -1,7 +1,7 @@
1
1
  import logging
2
- from typing import Optional, Type
2
+ from typing import Type
3
3
 
4
- from langchain_core.runnables import RunnableConfig
4
+ from langchain.tools.base import ToolException
5
5
  from pydantic import BaseModel, Field
6
6
 
7
7
  from intentkit.abstracts.skill import SkillStoreABC
@@ -24,18 +24,26 @@ class CookieFunBaseTool(IntentKitSkill):
24
24
  def category(self) -> str:
25
25
  return "cookiefun"
26
26
 
27
- def get_api_key(self, config: RunnableConfig) -> Optional[str]:
27
+ def get_api_key(self) -> str:
28
28
  """
29
29
  Get the API key from configuration.
30
30
 
31
- Args:
32
- config: The runnable configuration containing context
33
-
34
31
  Returns:
35
- The API key or None if not configured
32
+ The API key
33
+
34
+ Raises:
35
+ ToolException: If the API key is not found or provider is invalid.
36
36
  """
37
- context = self.context_from_config(config)
38
- skill_config = context.config
39
- if skill_config.get("api_key_provider") == "agent_owner":
40
- return skill_config.get("api_key")
41
- return self.skill_store.get_system_config("cookiefun_api_key")
37
+ context = self.get_context()
38
+ skill_config = context.agent.skill_config(self.category)
39
+ api_key_provider = skill_config.get("api_key_provider")
40
+ if api_key_provider == "agent_owner":
41
+ api_key = skill_config.get("api_key")
42
+ if api_key:
43
+ return api_key
44
+ else:
45
+ raise ToolException("No api_key found in agent_owner configuration")
46
+ else:
47
+ raise ToolException(
48
+ f"Invalid API key provider: {api_key_provider}. Only 'agent_owner' is supported for CookieFun."
49
+ )