intentkit 0.5.2__py3-none-any.whl → 0.6.0__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.
- intentkit/__init__.py +1 -1
- intentkit/abstracts/skill.py +12 -0
- intentkit/clients/cdp.py +114 -16
- intentkit/config/config.py +12 -4
- intentkit/core/engine.py +39 -31
- intentkit/core/node.py +8 -4
- intentkit/core/prompt.py +5 -6
- intentkit/core/skill.py +11 -0
- intentkit/models/agent.py +2 -9
- intentkit/models/agent_data.py +18 -0
- intentkit/models/agent_schema.json +12 -0
- intentkit/models/chat.py +50 -0
- intentkit/models/skill.py +19 -0
- intentkit/skills/base.py +37 -17
- intentkit/skills/cdp/__init__.py +6 -14
- intentkit/skills/cdp/get_balance.py +77 -25
- intentkit/skills/cdp/schema.json +0 -64
- intentkit/skills/cryptocompare/fetch_news.py +2 -2
- intentkit/skills/cryptocompare/fetch_price.py +2 -2
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +2 -2
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +2 -2
- intentkit/skills/cryptocompare/fetch_top_volume.py +2 -2
- intentkit/skills/cryptocompare/fetch_trading_signals.py +2 -2
- intentkit/skills/defillama/base.py +3 -3
- intentkit/skills/enso/base.py +27 -4
- intentkit/skills/enso/networks.py +1 -1
- intentkit/skills/enso/route.py +24 -23
- intentkit/skills/enso/tokens.py +1 -1
- intentkit/skills/enso/wallet.py +27 -23
- intentkit/skills/firecrawl/README.md +211 -0
- intentkit/skills/firecrawl/__init__.py +107 -0
- intentkit/skills/firecrawl/base.py +28 -0
- intentkit/skills/firecrawl/clear.py +87 -0
- intentkit/skills/firecrawl/crawl.py +399 -0
- intentkit/skills/firecrawl/firecrawl.png +0 -0
- intentkit/skills/firecrawl/query.py +123 -0
- intentkit/skills/firecrawl/schema.json +153 -0
- intentkit/skills/firecrawl/scrape.py +318 -0
- intentkit/skills/firecrawl/utils.py +306 -0
- intentkit/skills/heurist/image_generation_animagine_xl.py +1 -1
- intentkit/skills/heurist/image_generation_arthemy_comics.py +1 -1
- intentkit/skills/heurist/image_generation_arthemy_real.py +1 -1
- intentkit/skills/heurist/image_generation_braindance.py +1 -1
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +1 -1
- intentkit/skills/heurist/image_generation_flux_1_dev.py +1 -1
- intentkit/skills/heurist/image_generation_sdxl.py +1 -1
- intentkit/skills/http/README.md +78 -0
- intentkit/skills/http/__init__.py +100 -0
- intentkit/skills/http/base.py +21 -0
- intentkit/skills/http/get.py +96 -0
- intentkit/skills/http/http.svg +15 -0
- intentkit/skills/http/post.py +113 -0
- intentkit/skills/http/put.py +113 -0
- intentkit/skills/http/schema.json +80 -0
- intentkit/skills/lifi/token_execute.py +1 -1
- intentkit/skills/openai/dalle_image_generation.py +1 -1
- intentkit/skills/openai/gpt_image_generation.py +1 -1
- intentkit/skills/openai/gpt_image_to_image.py +1 -1
- intentkit/skills/supabase/__init__.py +116 -0
- intentkit/skills/supabase/base.py +72 -0
- intentkit/skills/supabase/delete_data.py +102 -0
- intentkit/skills/supabase/fetch_data.py +120 -0
- intentkit/skills/supabase/insert_data.py +70 -0
- intentkit/skills/supabase/invoke_function.py +74 -0
- intentkit/skills/supabase/schema.json +170 -0
- intentkit/skills/supabase/supabase.svg +15 -0
- intentkit/skills/supabase/update_data.py +105 -0
- intentkit/skills/supabase/upsert_data.py +77 -0
- intentkit/skills/system/read_agent_api_key.py +1 -1
- intentkit/skills/system/regenerate_agent_api_key.py +1 -1
- intentkit/skills/token/base.py +1 -39
- intentkit/skills/twitter/follow_user.py +3 -3
- intentkit/skills/twitter/get_mentions.py +6 -6
- intentkit/skills/twitter/get_timeline.py +5 -5
- intentkit/skills/twitter/get_user_by_username.py +3 -3
- intentkit/skills/twitter/get_user_tweets.py +5 -5
- intentkit/skills/twitter/like_tweet.py +3 -3
- intentkit/skills/twitter/post_tweet.py +4 -4
- intentkit/skills/twitter/reply_tweet.py +4 -4
- intentkit/skills/twitter/retweet.py +3 -3
- intentkit/skills/twitter/search_tweets.py +5 -5
- intentkit/skills/unrealspeech/text_to_speech.py +1 -1
- intentkit/skills/web_scraper/README.md +35 -4
- intentkit/skills/web_scraper/__init__.py +16 -0
- intentkit/skills/web_scraper/document_indexer.py +143 -0
- intentkit/skills/web_scraper/schema.json +28 -0
- intentkit/skills/web_scraper/scrape_and_index.py +135 -200
- intentkit/skills/web_scraper/utils.py +684 -0
- intentkit/skills/web_scraper/website_indexer.py +456 -0
- intentkit/utils/logging.py +1 -1
- {intentkit-0.5.2.dist-info → intentkit-0.6.0.dist-info}/METADATA +1 -1
- {intentkit-0.5.2.dist-info → intentkit-0.6.0.dist-info}/RECORD +94 -63
- {intentkit-0.5.2.dist-info → intentkit-0.6.0.dist-info}/WHEEL +0 -0
- {intentkit-0.5.2.dist-info → intentkit-0.6.0.dist-info}/licenses/LICENSE +0 -0
intentkit/skills/base.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import logging
|
|
2
3
|
from typing import Any, Callable, Dict, Literal, NotRequired, Optional, TypedDict, Union
|
|
3
4
|
|
|
@@ -30,10 +31,33 @@ class SkillConfig(TypedDict):
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class SkillContext(BaseModel):
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
user_id: Optional[str]
|
|
34
|
+
skill_category: str
|
|
35
|
+
agent_id: str
|
|
36
|
+
user_id: Optional[str] = None
|
|
37
|
+
chat_id: Optional[str] = None
|
|
38
|
+
app_id: Optional[str] = None
|
|
36
39
|
entrypoint: Literal["web", "twitter", "telegram", "trigger", "api"]
|
|
40
|
+
is_private: bool
|
|
41
|
+
payer: Optional[str] = None
|
|
42
|
+
_agent: Optional[Agent] = None
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def agent(self) -> Agent:
|
|
46
|
+
if self._agent is None:
|
|
47
|
+
self._agent = asyncio.run(Agent.get(self.agent_id))
|
|
48
|
+
return self._agent
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def config(self) -> Dict[str, Any]:
|
|
52
|
+
agent = self.agent
|
|
53
|
+
config = None
|
|
54
|
+
if agent.skills:
|
|
55
|
+
config = agent.skills.get(self.skill_category)
|
|
56
|
+
if not config:
|
|
57
|
+
raise ValueError(
|
|
58
|
+
f"Skill {self.skill_category} not found in agent {self.agent_id}"
|
|
59
|
+
)
|
|
60
|
+
return config
|
|
37
61
|
|
|
38
62
|
|
|
39
63
|
class IntentKitSkill(BaseTool):
|
|
@@ -156,19 +180,15 @@ class IntentKitSkill(BaseTool):
|
|
|
156
180
|
def context_from_config(self, runner_config: RunnableConfig) -> SkillContext:
|
|
157
181
|
if "configurable" not in runner_config:
|
|
158
182
|
raise ValueError("configurable not in runner_config")
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
config = None
|
|
163
|
-
if agent.skills:
|
|
164
|
-
config = agent.skills.get(self.category)
|
|
165
|
-
if not config:
|
|
166
|
-
config = getattr(agent, self.category + "_config", {})
|
|
167
|
-
if not config:
|
|
168
|
-
config = {}
|
|
183
|
+
configurable = runner_config["configurable"]
|
|
184
|
+
if not configurable:
|
|
185
|
+
raise ValueError("configurable in runnable config is empty")
|
|
169
186
|
return SkillContext(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
user_id=
|
|
173
|
-
|
|
187
|
+
skill_category=self.category,
|
|
188
|
+
agent_id=configurable.get("agent_id"),
|
|
189
|
+
user_id=configurable.get("user_id"),
|
|
190
|
+
app_id=configurable.get("app_id"),
|
|
191
|
+
chat_id=configurable.get("chat_id"),
|
|
192
|
+
entrypoint=configurable.get("entrypoint"),
|
|
193
|
+
is_private=configurable.get("is_private"),
|
|
174
194
|
)
|
intentkit/skills/cdp/__init__.py
CHANGED
|
@@ -5,10 +5,9 @@ from typing import TypedDict
|
|
|
5
5
|
from coinbase_agentkit import (
|
|
6
6
|
AgentKit,
|
|
7
7
|
AgentKitConfig,
|
|
8
|
-
|
|
8
|
+
CdpEvmServerWalletProvider,
|
|
9
9
|
basename_action_provider,
|
|
10
10
|
cdp_api_action_provider,
|
|
11
|
-
cdp_wallet_action_provider,
|
|
12
11
|
erc20_action_provider,
|
|
13
12
|
morpho_action_provider,
|
|
14
13
|
pyth_action_provider,
|
|
@@ -26,9 +25,6 @@ from intentkit.skills.base import SkillConfig, SkillState
|
|
|
26
25
|
from intentkit.skills.cdp.base import CDPBaseTool
|
|
27
26
|
from intentkit.skills.cdp.get_balance import GetBalance
|
|
28
27
|
|
|
29
|
-
# Cache skills at the system level, because they are stateless
|
|
30
|
-
_cache: dict[str, CDPBaseTool] = {}
|
|
31
|
-
|
|
32
28
|
|
|
33
29
|
class SkillStates(TypedDict):
|
|
34
30
|
get_balance: SkillState
|
|
@@ -37,10 +33,6 @@ class SkillStates(TypedDict):
|
|
|
37
33
|
WalletActionProvider_native_transfer: SkillState
|
|
38
34
|
CdpApiActionProvider_address_reputation: SkillState
|
|
39
35
|
CdpApiActionProvider_request_faucet_funds: SkillState
|
|
40
|
-
CdpWalletActionProvider_deploy_contract: SkillState
|
|
41
|
-
CdpWalletActionProvider_deploy_nft: SkillState
|
|
42
|
-
CdpWalletActionProvider_deploy_token: SkillState
|
|
43
|
-
CdpWalletActionProvider_trade: SkillState
|
|
44
36
|
PythActionProvider_fetch_price: SkillState
|
|
45
37
|
PythActionProvider_fetch_price_feed_id: SkillState
|
|
46
38
|
BasenameActionProvider_register_basename: SkillState
|
|
@@ -97,15 +89,15 @@ async def get_skills(
|
|
|
97
89
|
|
|
98
90
|
# Initialize CDP client
|
|
99
91
|
cdp_client: CdpClient = await get_cdp_client(agent_id, store)
|
|
100
|
-
cdp_wallet_provider:
|
|
101
|
-
|
|
92
|
+
cdp_wallet_provider: CdpEvmServerWalletProvider = (
|
|
93
|
+
await cdp_client.get_wallet_provider()
|
|
94
|
+
)
|
|
102
95
|
agent_kit = AgentKit(
|
|
103
96
|
AgentKitConfig(
|
|
104
97
|
wallet_provider=cdp_wallet_provider,
|
|
105
98
|
action_providers=[
|
|
106
99
|
wallet_action_provider(),
|
|
107
|
-
cdp_api_action_provider(
|
|
108
|
-
cdp_wallet_action_provider(cdp_provider_config),
|
|
100
|
+
cdp_api_action_provider(),
|
|
109
101
|
pyth_action_provider(),
|
|
110
102
|
basename_action_provider(),
|
|
111
103
|
erc20_action_provider(),
|
|
@@ -121,9 +113,9 @@ async def get_skills(
|
|
|
121
113
|
tools = []
|
|
122
114
|
for skill in available_skills:
|
|
123
115
|
if skill == "get_balance":
|
|
116
|
+
# Get the account object for the custom GetBalance skill
|
|
124
117
|
tools.append(
|
|
125
118
|
GetBalance(
|
|
126
|
-
wallet=cdp_wallet_provider._wallet,
|
|
127
119
|
agent_id=agent_id,
|
|
128
120
|
skill_store=store,
|
|
129
121
|
)
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
from typing import Type
|
|
1
|
+
from typing import Optional, Type
|
|
2
2
|
|
|
3
|
-
from cdp import
|
|
3
|
+
from cdp import EvmServerAccount
|
|
4
4
|
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
from intentkit.abstracts.skill import SkillStoreABC
|
|
7
|
+
from intentkit.clients import get_cdp_client
|
|
7
8
|
from intentkit.skills.cdp.base import CDPBaseTool
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class GetBalanceInput(BaseModel):
|
|
11
12
|
"""Input for GetBalance tool."""
|
|
12
13
|
|
|
13
|
-
asset_id: str = Field(
|
|
14
|
-
|
|
14
|
+
asset_id: Optional[str] = Field(
|
|
15
|
+
default=None,
|
|
16
|
+
description="The asset ID to get the balance for (e.g., 'eth', 'usdc', or a valid contract address). If not provided, returns all token balances.",
|
|
15
17
|
)
|
|
16
18
|
|
|
17
19
|
|
|
@@ -28,50 +30,100 @@ class GetBalance(CDPBaseTool):
|
|
|
28
30
|
|
|
29
31
|
agent_id: str
|
|
30
32
|
skill_store: SkillStoreABC
|
|
31
|
-
wallet: Wallet | None = None
|
|
32
33
|
|
|
33
34
|
name: str = "cdp_get_balance"
|
|
34
35
|
description: str = (
|
|
35
|
-
"This tool will get the balance of all the addresses in the wallet
|
|
36
|
+
"This tool will get the balance of all the addresses in the wallet. If asset_id is provided, it returns the balance for that specific asset. "
|
|
37
|
+
"If no asset_id is provided, it returns all token balances. "
|
|
36
38
|
"Always use 'eth' for the native asset ETH and 'usdc' for USDC. "
|
|
37
39
|
"Other valid asset IDs are: weth,dai,reth,brett,w,cbeth,axl,iotx,prime,aero,rsr,mog,tbtc,npc,yfi"
|
|
38
40
|
)
|
|
39
41
|
args_schema: Type[BaseModel] = GetBalanceInput
|
|
40
42
|
|
|
41
|
-
async def _arun(self, asset_id: str) -> str:
|
|
43
|
+
async def _arun(self, asset_id: Optional[str] = None) -> str:
|
|
42
44
|
"""Async implementation of the tool to get balance.
|
|
43
45
|
|
|
44
46
|
Args:
|
|
45
|
-
asset_id (str): The asset ID to get the balance for.
|
|
47
|
+
asset_id (Optional[str]): The asset ID to get the balance for. If None, returns all token balances.
|
|
46
48
|
|
|
47
49
|
Returns:
|
|
48
50
|
str: A message containing the balance information or error message.
|
|
49
51
|
"""
|
|
50
52
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
# Get network information from CDP client
|
|
54
|
+
cdp_client = await get_cdp_client(self.agent_id, self.skill_store)
|
|
55
|
+
provider = await cdp_client.get_wallet_provider()
|
|
56
|
+
account: EvmServerAccount = provider._account
|
|
57
|
+
provider_config = await cdp_client.get_provider_config()
|
|
58
|
+
network_id = provider_config.network_id
|
|
59
|
+
|
|
60
|
+
# Map network_id to the format expected by the API
|
|
61
|
+
network_mapping = {
|
|
62
|
+
"base-mainnet": "base",
|
|
63
|
+
"ethereum-mainnet": "ethereum",
|
|
64
|
+
}
|
|
65
|
+
api_network = network_mapping.get(network_id, network_id)
|
|
66
|
+
|
|
67
|
+
# If no asset_id provided, return all token balances
|
|
68
|
+
if asset_id is None:
|
|
69
|
+
try:
|
|
70
|
+
# Get native ETH balance
|
|
71
|
+
balance_wei = provider.get_balance()
|
|
72
|
+
balance_eth = balance_wei / (10**18) # Convert from wei to ETH
|
|
73
|
+
|
|
74
|
+
# Get all token balances
|
|
75
|
+
token_balances = await account.list_token_balances(api_network)
|
|
76
|
+
|
|
77
|
+
result = [f"ETH balance: {balance_eth} ETH"]
|
|
78
|
+
|
|
79
|
+
for balance in token_balances.balances:
|
|
80
|
+
result.append(
|
|
81
|
+
f"{balance.token.symbol} balance: {balance.amount.decimals} {balance.token.name}"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return f"All balances for account {account.address}:\n" + "\n".join(
|
|
85
|
+
result
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
return f"Error getting all balances: {e!s}"
|
|
90
|
+
|
|
91
|
+
# For native ETH balance, use the account's balance directly
|
|
92
|
+
if asset_id.lower() == "eth":
|
|
93
|
+
try:
|
|
94
|
+
# Get native balance using Web3
|
|
95
|
+
balance_wei = provider.get_balance()
|
|
96
|
+
balance_eth = balance_wei / (10**18) # Convert from wei to ETH
|
|
97
|
+
return (
|
|
98
|
+
f"ETH balance for account {account.address}: {balance_eth} ETH"
|
|
99
|
+
)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
return f"Error getting ETH balance: {e!s}"
|
|
102
|
+
|
|
103
|
+
# For other tokens, try the list_token_balances API
|
|
104
|
+
try:
|
|
105
|
+
# list_token_balances returns all token balances for the account
|
|
106
|
+
token_balances = await account.list_token_balances(api_network)
|
|
53
107
|
|
|
54
|
-
|
|
55
|
-
|
|
108
|
+
# Find the balance for the specific asset
|
|
109
|
+
target_balance = None
|
|
110
|
+
for balance in token_balances.balances:
|
|
111
|
+
if balance.token.symbol.lower() == asset_id.lower():
|
|
112
|
+
target_balance = balance
|
|
113
|
+
break
|
|
56
114
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
except Exception as e:
|
|
62
|
-
return f"Error getting balance for all addresses in the wallet: {e!s}"
|
|
115
|
+
if target_balance:
|
|
116
|
+
return f"Balance for {asset_id} in account {account.address}: {target_balance.amount.decimals} {target_balance.token.name}"
|
|
117
|
+
else:
|
|
118
|
+
return f"No balance found for asset {asset_id} in account {account.address}"
|
|
63
119
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
f" {addr}: {balance}" for addr, balance in balances.items()
|
|
67
|
-
]
|
|
68
|
-
formatted_balances = "\n".join(balance_lines)
|
|
69
|
-
return f"Balances for wallet {self.wallet.id}:\n{formatted_balances}"
|
|
120
|
+
except Exception as e:
|
|
121
|
+
return f"Error getting balance for account: {e!s}"
|
|
70
122
|
|
|
71
123
|
except Exception as e:
|
|
72
124
|
return f"Error getting balance: {str(e)}"
|
|
73
125
|
|
|
74
|
-
def _run(self, asset_id: str) -> str:
|
|
126
|
+
def _run(self, asset_id: Optional[str] = None) -> str:
|
|
75
127
|
"""Sync implementation of the tool.
|
|
76
128
|
|
|
77
129
|
This method is deprecated since we now have native async implementation in _arun.
|
intentkit/skills/cdp/schema.json
CHANGED
|
@@ -193,70 +193,6 @@
|
|
|
193
193
|
"description": "State for WalletActionProvider_native_transfer",
|
|
194
194
|
"default": "private"
|
|
195
195
|
},
|
|
196
|
-
"CdpWalletActionProvider_trade": {
|
|
197
|
-
"type": "string",
|
|
198
|
-
"title": "CDP Wallet Trade",
|
|
199
|
-
"enum": [
|
|
200
|
-
"disabled",
|
|
201
|
-
"public",
|
|
202
|
-
"private"
|
|
203
|
-
],
|
|
204
|
-
"x-enum-title": [
|
|
205
|
-
"Disabled",
|
|
206
|
-
"Agent Owner + All Users",
|
|
207
|
-
"Agent Owner Only"
|
|
208
|
-
],
|
|
209
|
-
"description": "State for CdpWalletActionProvider_trade",
|
|
210
|
-
"default": "private"
|
|
211
|
-
},
|
|
212
|
-
"CdpWalletActionProvider_deploy_nft": {
|
|
213
|
-
"type": "string",
|
|
214
|
-
"title": "Cdp Wallet Deploy Nft",
|
|
215
|
-
"enum": [
|
|
216
|
-
"disabled",
|
|
217
|
-
"public",
|
|
218
|
-
"private"
|
|
219
|
-
],
|
|
220
|
-
"x-enum-title": [
|
|
221
|
-
"Disabled",
|
|
222
|
-
"Agent Owner + All Users",
|
|
223
|
-
"Agent Owner Only"
|
|
224
|
-
],
|
|
225
|
-
"description": "State for CdpWalletActionProvider_deploy_nft",
|
|
226
|
-
"default": "disabled"
|
|
227
|
-
},
|
|
228
|
-
"CdpWalletActionProvider_deploy_token": {
|
|
229
|
-
"type": "string",
|
|
230
|
-
"title": "CDP Wallet Deploy Token",
|
|
231
|
-
"enum": [
|
|
232
|
-
"disabled",
|
|
233
|
-
"public",
|
|
234
|
-
"private"
|
|
235
|
-
],
|
|
236
|
-
"x-enum-title": [
|
|
237
|
-
"Disabled",
|
|
238
|
-
"Agent Owner + All Users",
|
|
239
|
-
"Agent Owner Only"
|
|
240
|
-
],
|
|
241
|
-
"description": "State for CdpWalletActionProvider_deploy_token",
|
|
242
|
-
"default": "disabled"
|
|
243
|
-
},
|
|
244
|
-
"CdpWalletActionProvider_deploy_contract": {
|
|
245
|
-
"type": "string",
|
|
246
|
-
"title": "CDP Wallet Deploy Contract",
|
|
247
|
-
"enum": [
|
|
248
|
-
"disabled",
|
|
249
|
-
"public",
|
|
250
|
-
"private"
|
|
251
|
-
],
|
|
252
|
-
"x-enum-title": [
|
|
253
|
-
"Disabled",
|
|
254
|
-
"Agent Owner + All Users",
|
|
255
|
-
"Agent Owner Only"
|
|
256
|
-
],
|
|
257
|
-
"description": "State for CdpWalletActionProvider_deploy_contract",
|
|
258
|
-
"default": "disabled"
|
|
259
|
-
},
|
|
260
196
|
"CdpApiActionProvider_request_faucet_funds": {
|
|
261
197
|
"type": "string",
|
|
262
198
|
"title": "CDP Request Faucet Funds",
|
|
@@ -57,7 +57,7 @@ class CryptoCompareFetchNews(CryptoCompareBaseTool):
|
|
|
57
57
|
context = self.context_from_config(config)
|
|
58
58
|
|
|
59
59
|
# Check rate limit
|
|
60
|
-
await self.check_rate_limit(context.
|
|
60
|
+
await self.check_rate_limit(context.agent_id, max_requests=5, interval=60)
|
|
61
61
|
|
|
62
62
|
# Get API key from context
|
|
63
63
|
api_key = context.config.get("api_key")
|
|
@@ -93,4 +93,4 @@ class CryptoCompareFetchNews(CryptoCompareBaseTool):
|
|
|
93
93
|
|
|
94
94
|
except Exception as e:
|
|
95
95
|
logger.error("Error fetching news: %s", str(e))
|
|
96
|
-
raise type(e)(f"[agent:{context.
|
|
96
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -67,7 +67,7 @@ class CryptoCompareFetchPrice(CryptoCompareBaseTool):
|
|
|
67
67
|
context = self.context_from_config(config)
|
|
68
68
|
|
|
69
69
|
# Check rate limit
|
|
70
|
-
await self.check_rate_limit(context.
|
|
70
|
+
await self.check_rate_limit(context.agent_id, max_requests=10, interval=60)
|
|
71
71
|
|
|
72
72
|
# Get API key from context
|
|
73
73
|
api_key = context.config.get("api_key")
|
|
@@ -96,4 +96,4 @@ class CryptoCompareFetchPrice(CryptoCompareBaseTool):
|
|
|
96
96
|
|
|
97
97
|
except Exception as e:
|
|
98
98
|
logger.error("Error fetching price: %s", str(e))
|
|
99
|
-
raise type(e)(f"[agent:{context.
|
|
99
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -73,7 +73,7 @@ class CryptoCompareFetchTopExchanges(CryptoCompareBaseTool):
|
|
|
73
73
|
context = self.context_from_config(config)
|
|
74
74
|
|
|
75
75
|
# Check rate limit
|
|
76
|
-
await self.check_rate_limit(context.
|
|
76
|
+
await self.check_rate_limit(context.agent_id, max_requests=5, interval=60)
|
|
77
77
|
|
|
78
78
|
# Get API key from context
|
|
79
79
|
api_key = context.config.get("api_key")
|
|
@@ -110,4 +110,4 @@ class CryptoCompareFetchTopExchanges(CryptoCompareBaseTool):
|
|
|
110
110
|
|
|
111
111
|
except Exception as e:
|
|
112
112
|
logger.error("Error fetching top exchanges: %s", str(e))
|
|
113
|
-
raise type(e)(f"[agent:{context.
|
|
113
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -66,7 +66,7 @@ class CryptoCompareFetchTopMarketCap(CryptoCompareBaseTool):
|
|
|
66
66
|
context = self.context_from_config(config)
|
|
67
67
|
|
|
68
68
|
# Check rate limit
|
|
69
|
-
await self.check_rate_limit(context.
|
|
69
|
+
await self.check_rate_limit(context.agent_id, max_requests=5, interval=60)
|
|
70
70
|
|
|
71
71
|
# Get API key from context
|
|
72
72
|
api_key = context.config.get("api_key")
|
|
@@ -106,4 +106,4 @@ class CryptoCompareFetchTopMarketCap(CryptoCompareBaseTool):
|
|
|
106
106
|
|
|
107
107
|
except Exception as e:
|
|
108
108
|
logger.error("Error fetching top market cap: %s", str(e))
|
|
109
|
-
raise type(e)(f"[agent:{context.
|
|
109
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -65,7 +65,7 @@ class CryptoCompareFetchTopVolume(CryptoCompareBaseTool):
|
|
|
65
65
|
context = self.context_from_config(config)
|
|
66
66
|
|
|
67
67
|
# Check rate limit
|
|
68
|
-
await self.check_rate_limit(context.
|
|
68
|
+
await self.check_rate_limit(context.agent_id, max_requests=5, interval=60)
|
|
69
69
|
|
|
70
70
|
# Get API key from context
|
|
71
71
|
api_key = context.config.get("api_key")
|
|
@@ -105,4 +105,4 @@ class CryptoCompareFetchTopVolume(CryptoCompareBaseTool):
|
|
|
105
105
|
|
|
106
106
|
except Exception as e:
|
|
107
107
|
logger.error("Error fetching top volume: %s", str(e))
|
|
108
|
-
raise type(e)(f"[agent:{context.
|
|
108
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -68,7 +68,7 @@ class CryptoCompareFetchTradingSignals(CryptoCompareBaseTool):
|
|
|
68
68
|
context = self.context_from_config(config)
|
|
69
69
|
|
|
70
70
|
# Check rate limit
|
|
71
|
-
await self.check_rate_limit(context.
|
|
71
|
+
await self.check_rate_limit(context.agent_id, max_requests=5, interval=60)
|
|
72
72
|
|
|
73
73
|
# Get API key from context
|
|
74
74
|
api_key = context.config.get("api_key")
|
|
@@ -104,4 +104,4 @@ class CryptoCompareFetchTradingSignals(CryptoCompareBaseTool):
|
|
|
104
104
|
|
|
105
105
|
except Exception as e:
|
|
106
106
|
logger.error("Error fetching trading signals: %s", str(e))
|
|
107
|
-
raise type(e)(f"[agent:{context.
|
|
107
|
+
raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
|
|
@@ -52,7 +52,7 @@ class DefiLlamaBaseTool(IntentKitSkill):
|
|
|
52
52
|
Rate limit status and error message if limited
|
|
53
53
|
"""
|
|
54
54
|
rate_limit = await self.skill_store.get_agent_skill_data(
|
|
55
|
-
context.
|
|
55
|
+
context.agent_id, self.name, "rate_limit"
|
|
56
56
|
)
|
|
57
57
|
current_time = datetime.now(tz=timezone.utc)
|
|
58
58
|
|
|
@@ -67,7 +67,7 @@ class DefiLlamaBaseTool(IntentKitSkill):
|
|
|
67
67
|
|
|
68
68
|
rate_limit["count"] += 1
|
|
69
69
|
await self.skill_store.save_agent_skill_data(
|
|
70
|
-
context.
|
|
70
|
+
context.agent_id, self.name, "rate_limit", rate_limit
|
|
71
71
|
)
|
|
72
72
|
return False, None
|
|
73
73
|
|
|
@@ -76,7 +76,7 @@ class DefiLlamaBaseTool(IntentKitSkill):
|
|
|
76
76
|
"reset_time": (current_time + timedelta(minutes=interval)).isoformat(),
|
|
77
77
|
}
|
|
78
78
|
await self.skill_store.save_agent_skill_data(
|
|
79
|
-
context.
|
|
79
|
+
context.agent_id, self.name, "rate_limit", new_rate_limit
|
|
80
80
|
)
|
|
81
81
|
return False, None
|
|
82
82
|
|
intentkit/skills/enso/base.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Optional, Type
|
|
2
2
|
|
|
3
|
-
from cdp import
|
|
3
|
+
from cdp import EvmServerAccount
|
|
4
|
+
from coinbase_agentkit import CdpEvmServerWalletProvider
|
|
4
5
|
from pydantic import BaseModel, Field
|
|
5
6
|
|
|
6
7
|
from intentkit.abstracts.skill import SkillStoreABC
|
|
@@ -22,9 +23,31 @@ class EnsoBaseTool(IntentKitSkill):
|
|
|
22
23
|
description="The skill store for persisting data"
|
|
23
24
|
)
|
|
24
25
|
|
|
25
|
-
async def
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
async def get_account(self, context: SkillContext) -> Optional[EvmServerAccount]:
|
|
27
|
+
"""Get the account object from the CDP client.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
context: The skill context containing agent information.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Optional[EvmServerAccount]: The account object if available.
|
|
34
|
+
"""
|
|
35
|
+
client: CdpClient = await get_cdp_client(context.agent_id, self.skill_store)
|
|
36
|
+
return await client.get_account()
|
|
37
|
+
|
|
38
|
+
async def get_wallet_provider(
|
|
39
|
+
self, context: SkillContext
|
|
40
|
+
) -> Optional[CdpEvmServerWalletProvider]:
|
|
41
|
+
"""Get the wallet provider from the CDP client.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
context: The skill context containing agent information.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Optional[CdpEvmServerWalletProvider]: The wallet provider if available.
|
|
48
|
+
"""
|
|
49
|
+
client: CdpClient = await get_cdp_client(context.agent_id, self.skill_store)
|
|
50
|
+
return await client.get_wallet_provider()
|
|
28
51
|
|
|
29
52
|
def get_chain_provider(self, context: SkillContext) -> Optional[ChainProvider]:
|
|
30
53
|
return self.skill_store.get_system_config("chain_provider")
|
intentkit/skills/enso/route.py
CHANGED
|
@@ -6,9 +6,7 @@ from langchain_core.runnables import RunnableConfig
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
8
|
from intentkit.skills.base import SkillContext
|
|
9
|
-
from intentkit.skills.enso.abi.route import ABI_ROUTE
|
|
10
9
|
from intentkit.skills.enso.networks import EnsoGetNetworks
|
|
11
|
-
from intentkit.utils.tx import EvmContractWrapper
|
|
12
10
|
|
|
13
11
|
from .base import EnsoBaseTool, base_url, default_chain_id
|
|
14
12
|
|
|
@@ -186,10 +184,9 @@ class EnsoRouteShortcut(EnsoBaseTool):
|
|
|
186
184
|
"""
|
|
187
185
|
|
|
188
186
|
context: SkillContext = self.context_from_config(config)
|
|
189
|
-
agent_id = context.
|
|
187
|
+
agent_id = context.agent_id
|
|
190
188
|
api_token = self.get_api_token(context)
|
|
191
|
-
|
|
192
|
-
wallet = await self.get_wallet(context)
|
|
189
|
+
account = await self.get_account(context)
|
|
193
190
|
|
|
194
191
|
async with httpx.AsyncClient() as client:
|
|
195
192
|
try:
|
|
@@ -254,7 +251,7 @@ class EnsoRouteShortcut(EnsoBaseTool):
|
|
|
254
251
|
tokenOut=tokenOut,
|
|
255
252
|
).model_dump(exclude_none=True)
|
|
256
253
|
|
|
257
|
-
params["fromAddress"] =
|
|
254
|
+
params["fromAddress"] = account.address
|
|
258
255
|
|
|
259
256
|
response = await client.get(url, headers=headers, params=params)
|
|
260
257
|
response.raise_for_status() # Raise HTTPError for non-2xx responses
|
|
@@ -268,23 +265,27 @@ class EnsoRouteShortcut(EnsoBaseTool):
|
|
|
268
265
|
)
|
|
269
266
|
|
|
270
267
|
if broadcast_requested:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
268
|
+
# Use the wallet provider to send the transaction
|
|
269
|
+
wallet_provider = await self.get_wallet_provider(context)
|
|
270
|
+
|
|
271
|
+
# Extract transaction data from the Enso API response
|
|
272
|
+
tx_data = json_dict.get("tx", {})
|
|
273
|
+
if tx_data:
|
|
274
|
+
# Send the transaction using the wallet provider
|
|
275
|
+
tx_hash = wallet_provider.send_transaction(
|
|
276
|
+
{
|
|
277
|
+
"to": tx_data.get("to"),
|
|
278
|
+
"data": tx_data.get("data", "0x"),
|
|
279
|
+
"value": tx_data.get("value", 0),
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# Wait for transaction confirmation
|
|
284
|
+
wallet_provider.wait_for_transaction_receipt(tx_hash)
|
|
285
|
+
res.txHash = tx_hash
|
|
286
|
+
else:
|
|
287
|
+
# For now, return a placeholder transaction hash if no tx data
|
|
288
|
+
res.txHash = "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
288
289
|
|
|
289
290
|
return res
|
|
290
291
|
|
intentkit/skills/enso/tokens.py
CHANGED
|
@@ -158,7 +158,7 @@ class EnsoGetTokens(EnsoBaseTool):
|
|
|
158
158
|
url = f"{base_url}/api/v1/tokens"
|
|
159
159
|
|
|
160
160
|
context: SkillContext = self.context_from_config(config)
|
|
161
|
-
agent_id = context.
|
|
161
|
+
agent_id = context.agent_id
|
|
162
162
|
api_token = self.get_api_token(context)
|
|
163
163
|
main_tokens = self.get_main_tokens(context)
|
|
164
164
|
headers = {
|