intentkit 0.8.12.dev2__py3-none-any.whl → 0.8.12.dev4__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 +2 -59
- intentkit/clients/twitter.py +35 -28
- intentkit/core/agent.py +2 -279
- intentkit/core/engine.py +6 -4
- intentkit/models/agent.py +109 -89
- intentkit/models/agent_schema.json +4 -2
- intentkit/skills/acolyt/__init__.py +2 -9
- intentkit/skills/acolyt/base.py +2 -5
- intentkit/skills/aixbt/__init__.py +2 -13
- intentkit/skills/aixbt/base.py +0 -4
- intentkit/skills/aixbt/projects.py +1 -2
- intentkit/skills/allora/__init__.py +2 -9
- intentkit/skills/allora/base.py +2 -5
- intentkit/skills/base.py +101 -27
- intentkit/skills/basename/__init__.py +1 -3
- intentkit/skills/carv/__init__.py +116 -121
- intentkit/skills/carv/base.py +184 -185
- intentkit/skills/casino/__init__.py +4 -15
- intentkit/skills/casino/base.py +0 -4
- intentkit/skills/casino/deck_draw.py +1 -2
- intentkit/skills/casino/deck_shuffle.py +1 -2
- intentkit/skills/casino/dice_roll.py +1 -2
- intentkit/skills/cdp/__init__.py +0 -4
- intentkit/skills/cdp/base.py +0 -4
- intentkit/skills/chainlist/__init__.py +2 -7
- intentkit/skills/chainlist/base.py +0 -4
- intentkit/skills/common/__init__.py +2 -9
- intentkit/skills/common/base.py +0 -4
- intentkit/skills/cookiefun/__init__.py +6 -9
- intentkit/skills/cookiefun/base.py +0 -4
- intentkit/skills/cryptocompare/__init__.py +7 -24
- intentkit/skills/cryptocompare/base.py +0 -5
- intentkit/skills/cryptopanic/__init__.py +3 -6
- intentkit/skills/cryptopanic/base.py +53 -55
- intentkit/skills/cryptopanic/fetch_crypto_news.py +0 -2
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +1 -3
- intentkit/skills/dapplooker/__init__.py +2 -9
- intentkit/skills/dapplooker/base.py +2 -5
- intentkit/skills/defillama/__init__.py +24 -74
- intentkit/skills/defillama/base.py +0 -4
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +2 -2
- intentkit/skills/defillama/coins/fetch_block.py +2 -2
- intentkit/skills/defillama/coins/fetch_current_prices.py +2 -2
- intentkit/skills/defillama/coins/fetch_first_price.py +2 -2
- intentkit/skills/defillama/coins/fetch_historical_prices.py +2 -2
- intentkit/skills/defillama/coins/fetch_price_chart.py +2 -2
- intentkit/skills/defillama/coins/fetch_price_percentage.py +2 -2
- intentkit/skills/defillama/fees/fetch_fees_overview.py +2 -2
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +2 -2
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +2 -2
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +2 -2
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +2 -2
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +2 -2
- intentkit/skills/defillama/tvl/fetch_chains.py +2 -2
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +2 -2
- intentkit/skills/defillama/tvl/fetch_protocol.py +2 -2
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +2 -2
- intentkit/skills/defillama/tvl/fetch_protocols.py +2 -2
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +2 -2
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +2 -2
- intentkit/skills/defillama/volumes/fetch_options_overview.py +2 -2
- intentkit/skills/defillama/yields/fetch_pool_chart.py +2 -2
- intentkit/skills/defillama/yields/fetch_pools.py +2 -2
- intentkit/skills/dexscreener/__init__.py +97 -102
- intentkit/skills/dexscreener/base.py +125 -130
- intentkit/skills/dexscreener/get_pair_info.py +2 -3
- intentkit/skills/dexscreener/get_token_pairs.py +2 -3
- intentkit/skills/dexscreener/get_tokens_info.py +2 -3
- intentkit/skills/dexscreener/search_token.py +2 -4
- intentkit/skills/dune_analytics/__init__.py +4 -6
- intentkit/skills/dune_analytics/base.py +50 -52
- intentkit/skills/dune_analytics/fetch_kol_buys.py +0 -2
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +0 -2
- intentkit/skills/elfa/__init__.py +5 -18
- intentkit/skills/elfa/base.py +8 -10
- intentkit/skills/enso/__init__.py +9 -29
- intentkit/skills/enso/base.py +3 -6
- intentkit/skills/enso/route.py +1 -3
- intentkit/skills/erc20/__init__.py +1 -5
- intentkit/skills/erc721/__init__.py +1 -3
- intentkit/skills/firecrawl/__init__.py +5 -18
- intentkit/skills/firecrawl/base.py +2 -5
- intentkit/skills/firecrawl/crawl.py +10 -9
- intentkit/skills/firecrawl/query.py +3 -1
- intentkit/skills/firecrawl/scrape.py +8 -10
- intentkit/skills/firecrawl/utils.py +25 -26
- intentkit/skills/github/__init__.py +2 -7
- intentkit/skills/github/base.py +0 -4
- intentkit/skills/heurist/__init__.py +8 -27
- intentkit/skills/heurist/base.py +2 -5
- intentkit/skills/heurist/image_generation_animagine_xl.py +5 -5
- intentkit/skills/heurist/image_generation_arthemy_comics.py +5 -5
- intentkit/skills/heurist/image_generation_arthemy_real.py +5 -5
- intentkit/skills/heurist/image_generation_braindance.py +5 -5
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +5 -5
- intentkit/skills/heurist/image_generation_flux_1_dev.py +5 -5
- intentkit/skills/heurist/image_generation_sdxl.py +5 -5
- intentkit/skills/http/__init__.py +4 -15
- intentkit/skills/http/base.py +0 -4
- intentkit/skills/lifi/__init__.py +1 -6
- intentkit/skills/lifi/base.py +0 -4
- intentkit/skills/lifi/token_execute.py +1 -4
- intentkit/skills/lifi/token_quote.py +1 -3
- intentkit/skills/moralis/__init__.py +3 -7
- intentkit/skills/moralis/base.py +2 -5
- intentkit/skills/morpho/__init__.py +1 -3
- intentkit/skills/nation/__init__.py +2 -7
- intentkit/skills/nation/base.py +4 -7
- intentkit/skills/openai/__init__.py +5 -18
- intentkit/skills/openai/base.py +8 -10
- intentkit/skills/openai/dalle_image_generation.py +2 -5
- intentkit/skills/openai/gpt_image_generation.py +2 -5
- intentkit/skills/openai/gpt_image_to_image.py +2 -5
- intentkit/skills/openai/image_to_text.py +2 -5
- intentkit/skills/portfolio/__init__.py +11 -35
- intentkit/skills/portfolio/base.py +2 -5
- intentkit/skills/pyth/__init__.py +1 -5
- intentkit/skills/slack/__init__.py +5 -17
- intentkit/skills/slack/base.py +0 -4
- intentkit/skills/supabase/__init__.py +7 -23
- intentkit/skills/supabase/base.py +0 -4
- intentkit/skills/superfluid/__init__.py +1 -3
- intentkit/skills/system/__init__.py +7 -24
- intentkit/skills/system/add_autonomous_task.py +2 -2
- intentkit/skills/system/delete_autonomous_task.py +2 -2
- intentkit/skills/system/edit_autonomous_task.py +2 -4
- intentkit/skills/system/list_autonomous_tasks.py +2 -2
- intentkit/skills/system/read_agent_api_key.py +6 -4
- intentkit/skills/system/regenerate_agent_api_key.py +6 -4
- intentkit/skills/tavily/__init__.py +3 -12
- intentkit/skills/tavily/base.py +2 -5
- intentkit/skills/tavily/tavily_extract.py +1 -2
- intentkit/skills/tavily/tavily_search.py +3 -3
- intentkit/skills/token/__init__.py +5 -10
- intentkit/skills/token/base.py +2 -6
- intentkit/skills/twitter/__init__.py +11 -35
- intentkit/skills/twitter/base.py +14 -16
- intentkit/skills/twitter/follow_user.py +0 -1
- intentkit/skills/twitter/get_mentions.py +0 -1
- intentkit/skills/twitter/get_timeline.py +0 -1
- intentkit/skills/twitter/get_user_by_username.py +0 -1
- intentkit/skills/twitter/get_user_tweets.py +0 -1
- intentkit/skills/twitter/like_tweet.py +0 -1
- intentkit/skills/twitter/post_tweet.py +2 -2
- intentkit/skills/twitter/reply_tweet.py +2 -2
- intentkit/skills/twitter/retweet.py +0 -1
- intentkit/skills/twitter/search_tweets.py +0 -1
- intentkit/skills/unrealspeech/__init__.py +2 -7
- intentkit/skills/unrealspeech/base.py +0 -4
- intentkit/skills/venice_audio/__init__.py +99 -106
- intentkit/skills/venice_audio/base.py +118 -121
- intentkit/skills/venice_audio/venice_audio.py +1 -5
- intentkit/skills/venice_image/__init__.py +147 -154
- intentkit/skills/venice_image/base.py +185 -192
- intentkit/skills/web_scraper/__init__.py +5 -18
- intentkit/skills/web_scraper/base.py +20 -4
- intentkit/skills/web_scraper/document_indexer.py +6 -4
- intentkit/skills/web_scraper/scrape_and_index.py +11 -8
- intentkit/skills/web_scraper/utils.py +31 -27
- intentkit/skills/web_scraper/website_indexer.py +7 -8
- intentkit/skills/weth/__init__.py +1 -5
- intentkit/skills/wow/__init__.py +1 -5
- intentkit/skills/xmtp/__init__.py +4 -15
- {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev4.dist-info}/METADATA +1 -1
- {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev4.dist-info}/RECORD +168 -168
- {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev4.dist-info}/WHEEL +0 -0
- {intentkit-0.8.12.dev2.dist-info → intentkit-0.8.12.dev4.dist-info}/licenses/LICENSE +0 -0
intentkit/__init__.py
CHANGED
intentkit/abstracts/skill.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Any, Dict,
|
|
2
|
+
from typing import Any, Dict, Optional
|
|
3
3
|
|
|
4
|
-
from intentkit.models.agent import Agent
|
|
4
|
+
from intentkit.models.agent import Agent
|
|
5
5
|
from intentkit.models.agent_data import AgentData, AgentQuota
|
|
6
6
|
|
|
7
7
|
|
|
@@ -58,60 +58,3 @@ class SkillStoreABC(ABC):
|
|
|
58
58
|
Agent quota if found, None otherwise
|
|
59
59
|
"""
|
|
60
60
|
pass
|
|
61
|
-
|
|
62
|
-
@staticmethod
|
|
63
|
-
@abstractmethod
|
|
64
|
-
async def list_autonomous_tasks(agent_id: str) -> List[AgentAutonomous]:
|
|
65
|
-
"""List all autonomous tasks for an agent.
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
agent_id: ID of the agent
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
List[AgentAutonomous]: List of autonomous task configurations
|
|
72
|
-
"""
|
|
73
|
-
pass
|
|
74
|
-
|
|
75
|
-
@staticmethod
|
|
76
|
-
@abstractmethod
|
|
77
|
-
async def add_autonomous_task(
|
|
78
|
-
agent_id: str, task: AgentAutonomous
|
|
79
|
-
) -> AgentAutonomous:
|
|
80
|
-
"""Add a new autonomous task to an agent.
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
agent_id: ID of the agent
|
|
84
|
-
task: Autonomous task configuration
|
|
85
|
-
|
|
86
|
-
Returns:
|
|
87
|
-
AgentAutonomous: The created task
|
|
88
|
-
"""
|
|
89
|
-
pass
|
|
90
|
-
|
|
91
|
-
@staticmethod
|
|
92
|
-
@abstractmethod
|
|
93
|
-
async def delete_autonomous_task(agent_id: str, task_id: str) -> None:
|
|
94
|
-
"""Delete an autonomous task from an agent.
|
|
95
|
-
|
|
96
|
-
Args:
|
|
97
|
-
agent_id: ID of the agent
|
|
98
|
-
task_id: ID of the task to delete
|
|
99
|
-
"""
|
|
100
|
-
pass
|
|
101
|
-
|
|
102
|
-
@staticmethod
|
|
103
|
-
@abstractmethod
|
|
104
|
-
async def update_autonomous_task(
|
|
105
|
-
agent_id: str, task_id: str, task_updates: dict
|
|
106
|
-
) -> AgentAutonomous:
|
|
107
|
-
"""Update an autonomous task for an agent.
|
|
108
|
-
|
|
109
|
-
Args:
|
|
110
|
-
agent_id: ID of the agent
|
|
111
|
-
task_id: ID of the task to update
|
|
112
|
-
task_updates: Dictionary containing fields to update
|
|
113
|
-
|
|
114
|
-
Returns:
|
|
115
|
-
AgentAutonomous: The updated task
|
|
116
|
-
"""
|
|
117
|
-
pass
|
intentkit/clients/twitter.py
CHANGED
|
@@ -11,7 +11,6 @@ from requests.auth import HTTPBasicAuth
|
|
|
11
11
|
from requests_oauthlib import OAuth2Session
|
|
12
12
|
from tweepy.asynchronous import AsyncClient
|
|
13
13
|
|
|
14
|
-
from intentkit.abstracts.skill import SkillStoreABC
|
|
15
14
|
from intentkit.abstracts.twitter import TwitterABC
|
|
16
15
|
from intentkit.models.agent_data import AgentData
|
|
17
16
|
from intentkit.models.redis import get_redis
|
|
@@ -80,33 +79,44 @@ class TwitterClient(TwitterABC):
|
|
|
80
79
|
|
|
81
80
|
Args:
|
|
82
81
|
agent_id: The ID of the agent
|
|
83
|
-
skill_store: The skill store for retrieving data
|
|
84
82
|
config: Configuration dictionary that may contain API keys
|
|
85
83
|
"""
|
|
86
84
|
|
|
87
|
-
def __init__(self, agent_id: str,
|
|
85
|
+
def __init__(self, agent_id: str, config: Dict) -> None:
|
|
88
86
|
"""Initialize the Twitter client.
|
|
89
87
|
|
|
90
88
|
Args:
|
|
91
89
|
agent_id: The ID of the agent
|
|
92
|
-
skill_store: The skill store for retrieving data
|
|
93
90
|
config: Configuration dictionary that may contain API keys
|
|
94
91
|
"""
|
|
95
92
|
self.agent_id = agent_id
|
|
96
93
|
self._client: Optional[AsyncClient] = None
|
|
97
|
-
self._skill_store = skill_store
|
|
98
94
|
self._agent_data: Optional[AgentData] = None
|
|
99
95
|
self.use_key = _is_self_key(config)
|
|
100
96
|
self._config = config
|
|
101
97
|
|
|
98
|
+
async def _get_agent_data(self) -> AgentData:
|
|
99
|
+
"""Retrieve cached agent data, loading from the database if needed."""
|
|
100
|
+
|
|
101
|
+
if not self._agent_data:
|
|
102
|
+
self._agent_data = await AgentData.get(self.agent_id)
|
|
103
|
+
return self._agent_data
|
|
104
|
+
|
|
105
|
+
async def _refresh_agent_data(self) -> AgentData:
|
|
106
|
+
"""Reload agent data from the database."""
|
|
107
|
+
|
|
108
|
+
self._agent_data = await AgentData.get(self.agent_id)
|
|
109
|
+
return self._agent_data
|
|
110
|
+
|
|
102
111
|
async def get_client(self) -> AsyncClient:
|
|
103
112
|
"""Get the initialized Twitter client.
|
|
104
113
|
|
|
105
114
|
Returns:
|
|
106
115
|
AsyncClient: The Twitter client if initialized
|
|
107
116
|
"""
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
|
|
118
|
+
agent_data = await self._get_agent_data()
|
|
119
|
+
|
|
110
120
|
if not self._client:
|
|
111
121
|
# Check if we have API keys in config
|
|
112
122
|
if self.use_key:
|
|
@@ -118,8 +128,8 @@ class TwitterClient(TwitterABC):
|
|
|
118
128
|
return_type=dict,
|
|
119
129
|
)
|
|
120
130
|
# refresh userinfo if needed
|
|
121
|
-
if not
|
|
122
|
-
|
|
131
|
+
if not agent_data.twitter_self_key_refreshed_at or (
|
|
132
|
+
agent_data.twitter_self_key_refreshed_at
|
|
123
133
|
< datetime.now(tz=timezone.utc) - timedelta(days=1)
|
|
124
134
|
):
|
|
125
135
|
me = await self._client.get_me(
|
|
@@ -127,7 +137,7 @@ class TwitterClient(TwitterABC):
|
|
|
127
137
|
user_fields="id,username,name,verified",
|
|
128
138
|
)
|
|
129
139
|
if me and "data" in me and "id" in me["data"]:
|
|
130
|
-
await
|
|
140
|
+
await AgentData.patch(
|
|
131
141
|
self.agent_id,
|
|
132
142
|
{
|
|
133
143
|
"twitter_id": me["data"]["id"],
|
|
@@ -139,9 +149,7 @@ class TwitterClient(TwitterABC):
|
|
|
139
149
|
),
|
|
140
150
|
},
|
|
141
151
|
)
|
|
142
|
-
|
|
143
|
-
self.agent_id
|
|
144
|
-
)
|
|
152
|
+
agent_data = await self._refresh_agent_data()
|
|
145
153
|
logger.info(
|
|
146
154
|
f"Twitter self key client initialized. "
|
|
147
155
|
f"Use API key: {self.use_key}, "
|
|
@@ -152,39 +160,40 @@ class TwitterClient(TwitterABC):
|
|
|
152
160
|
)
|
|
153
161
|
return self._client
|
|
154
162
|
# Otherwise try to get OAuth2 tokens from agent data
|
|
155
|
-
if not
|
|
163
|
+
if not agent_data.twitter_access_token:
|
|
156
164
|
raise Exception(f"[{self.agent_id}] Twitter access token not found")
|
|
157
|
-
if not
|
|
165
|
+
if not agent_data.twitter_access_token_expires_at:
|
|
158
166
|
raise Exception(
|
|
159
167
|
f"[{self.agent_id}] Twitter access token expiration not found"
|
|
160
168
|
)
|
|
161
|
-
if
|
|
169
|
+
if agent_data.twitter_access_token_expires_at <= datetime.now(
|
|
162
170
|
tz=timezone.utc
|
|
163
171
|
):
|
|
164
172
|
raise Exception(f"[{self.agent_id}] Twitter access token has expired")
|
|
165
173
|
self._client = AsyncClient(
|
|
166
|
-
bearer_token=
|
|
174
|
+
bearer_token=agent_data.twitter_access_token,
|
|
167
175
|
return_type=dict,
|
|
168
176
|
)
|
|
169
177
|
return self._client
|
|
178
|
+
|
|
170
179
|
if not self.use_key:
|
|
171
180
|
# check if access token has expired
|
|
172
|
-
if
|
|
181
|
+
if agent_data.twitter_access_token_expires_at <= datetime.now(
|
|
173
182
|
tz=timezone.utc
|
|
174
183
|
):
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if self._agent_data.twitter_access_token_expires_at <= datetime.now(
|
|
184
|
+
agent_data = await self._refresh_agent_data()
|
|
185
|
+
if agent_data.twitter_access_token_expires_at <= datetime.now(
|
|
178
186
|
tz=timezone.utc
|
|
179
187
|
):
|
|
180
188
|
raise Exception(
|
|
181
189
|
f"[{self.agent_id}] Twitter access token has expired"
|
|
182
190
|
)
|
|
183
191
|
self._client = AsyncClient(
|
|
184
|
-
bearer_token=
|
|
192
|
+
bearer_token=agent_data.twitter_access_token,
|
|
185
193
|
return_type=dict,
|
|
186
194
|
)
|
|
187
195
|
return self._client
|
|
196
|
+
|
|
188
197
|
return self._client
|
|
189
198
|
|
|
190
199
|
@property
|
|
@@ -352,7 +361,7 @@ class TwitterClient(TwitterABC):
|
|
|
352
361
|
ValueError: If there's an error uploading the media.
|
|
353
362
|
"""
|
|
354
363
|
# Get agent data to access the token
|
|
355
|
-
agent_data = await
|
|
364
|
+
agent_data = await AgentData.get(agent_id)
|
|
356
365
|
if not agent_data.twitter_access_token:
|
|
357
366
|
raise ValueError("Only linked X account can post media")
|
|
358
367
|
|
|
@@ -423,15 +432,13 @@ def _is_self_key(config: Dict) -> bool:
|
|
|
423
432
|
return config.get("api_key_provider") == "agent_owner"
|
|
424
433
|
|
|
425
434
|
|
|
426
|
-
def get_twitter_client(
|
|
427
|
-
agent_id: str, skill_store: SkillStoreABC, config: Dict
|
|
428
|
-
) -> "TwitterClient":
|
|
435
|
+
def get_twitter_client(agent_id: str, config: Dict) -> "TwitterClient":
|
|
429
436
|
if _is_self_key(config):
|
|
430
437
|
if agent_id not in _clients_self_key:
|
|
431
|
-
_clients_self_key[agent_id] = TwitterClient(agent_id,
|
|
438
|
+
_clients_self_key[agent_id] = TwitterClient(agent_id, config)
|
|
432
439
|
return _clients_self_key[agent_id]
|
|
433
440
|
if agent_id not in _clients_linked:
|
|
434
|
-
_clients_linked[agent_id] = TwitterClient(agent_id,
|
|
441
|
+
_clients_linked[agent_id] = TwitterClient(agent_id, config)
|
|
435
442
|
return _clients_linked[agent_id]
|
|
436
443
|
|
|
437
444
|
|
intentkit/core/agent.py
CHANGED
|
@@ -2,21 +2,19 @@ import logging
|
|
|
2
2
|
import time
|
|
3
3
|
from datetime import datetime, timedelta, timezone
|
|
4
4
|
from decimal import Decimal
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import AsyncGenerator, Dict, Optional, Tuple
|
|
6
6
|
|
|
7
7
|
from sqlalchemy import func, select, text, update
|
|
8
8
|
|
|
9
|
-
from intentkit.abstracts.skill import SkillStoreABC
|
|
10
9
|
from intentkit.clients.cdp import get_wallet_provider
|
|
11
10
|
from intentkit.config.config import config
|
|
12
11
|
from intentkit.models.agent import (
|
|
13
12
|
Agent,
|
|
14
|
-
AgentAutonomous,
|
|
15
13
|
AgentCreate,
|
|
16
14
|
AgentTable,
|
|
17
15
|
AgentUpdate,
|
|
18
16
|
)
|
|
19
|
-
from intentkit.models.agent_data import AgentData,
|
|
17
|
+
from intentkit.models.agent_data import AgentData, AgentQuotaTable
|
|
20
18
|
from intentkit.models.credit import (
|
|
21
19
|
CreditAccount,
|
|
22
20
|
CreditEventTable,
|
|
@@ -486,93 +484,6 @@ async def agent_action_cost(agent_id: str) -> Dict[str, Decimal]:
|
|
|
486
484
|
return result
|
|
487
485
|
|
|
488
486
|
|
|
489
|
-
class AgentStore(SkillStoreABC):
|
|
490
|
-
"""Implementation of skill data storage operations.
|
|
491
|
-
|
|
492
|
-
This class provides concrete implementations for storing and retrieving
|
|
493
|
-
skill-related data for both agents and threads.
|
|
494
|
-
"""
|
|
495
|
-
|
|
496
|
-
@staticmethod
|
|
497
|
-
def get_system_config(key: str) -> Any:
|
|
498
|
-
# TODO: maybe need a whitelist here
|
|
499
|
-
if hasattr(config, key):
|
|
500
|
-
return getattr(config, key)
|
|
501
|
-
return None
|
|
502
|
-
|
|
503
|
-
@staticmethod
|
|
504
|
-
async def get_agent_config(agent_id: str) -> Optional[Agent]:
|
|
505
|
-
return await Agent.get(agent_id)
|
|
506
|
-
|
|
507
|
-
@staticmethod
|
|
508
|
-
async def get_agent_data(agent_id: str) -> AgentData:
|
|
509
|
-
return await AgentData.get(agent_id)
|
|
510
|
-
|
|
511
|
-
@staticmethod
|
|
512
|
-
async def set_agent_data(agent_id: str, data: Dict) -> AgentData:
|
|
513
|
-
return await AgentData.patch(agent_id, data)
|
|
514
|
-
|
|
515
|
-
@staticmethod
|
|
516
|
-
async def get_agent_quota(agent_id: str) -> AgentQuota:
|
|
517
|
-
return await AgentQuota.get(agent_id)
|
|
518
|
-
|
|
519
|
-
@staticmethod
|
|
520
|
-
async def list_autonomous_tasks(agent_id: str) -> List[AgentAutonomous]:
|
|
521
|
-
"""List all autonomous tasks for an agent.
|
|
522
|
-
|
|
523
|
-
Args:
|
|
524
|
-
agent_id: ID of the agent
|
|
525
|
-
|
|
526
|
-
Returns:
|
|
527
|
-
List[AgentAutonomous]: List of autonomous task configurations
|
|
528
|
-
"""
|
|
529
|
-
return await list_autonomous_tasks(agent_id)
|
|
530
|
-
|
|
531
|
-
@staticmethod
|
|
532
|
-
async def add_autonomous_task(
|
|
533
|
-
agent_id: str, task: AgentAutonomous
|
|
534
|
-
) -> AgentAutonomous:
|
|
535
|
-
"""Add a new autonomous task to an agent.
|
|
536
|
-
|
|
537
|
-
Args:
|
|
538
|
-
agent_id: ID of the agent
|
|
539
|
-
task: Autonomous task configuration
|
|
540
|
-
|
|
541
|
-
Returns:
|
|
542
|
-
AgentAutonomous: The created task
|
|
543
|
-
"""
|
|
544
|
-
return await add_autonomous_task(agent_id, task)
|
|
545
|
-
|
|
546
|
-
@staticmethod
|
|
547
|
-
async def delete_autonomous_task(agent_id: str, task_id: str) -> None:
|
|
548
|
-
"""Delete an autonomous task from an agent.
|
|
549
|
-
|
|
550
|
-
Args:
|
|
551
|
-
agent_id: ID of the agent
|
|
552
|
-
task_id: ID of the task to delete
|
|
553
|
-
"""
|
|
554
|
-
await delete_autonomous_task(agent_id, task_id)
|
|
555
|
-
|
|
556
|
-
@staticmethod
|
|
557
|
-
async def update_autonomous_task(
|
|
558
|
-
agent_id: str, task_id: str, task_updates: dict
|
|
559
|
-
) -> AgentAutonomous:
|
|
560
|
-
"""Update an autonomous task for an agent.
|
|
561
|
-
|
|
562
|
-
Args:
|
|
563
|
-
agent_id: ID of the agent
|
|
564
|
-
task_id: ID of the task to update
|
|
565
|
-
task_updates: Dictionary containing fields to update
|
|
566
|
-
|
|
567
|
-
Returns:
|
|
568
|
-
AgentAutonomous: The updated task
|
|
569
|
-
"""
|
|
570
|
-
return await update_autonomous_task(agent_id, task_id, task_updates)
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
agent_store = AgentStore()
|
|
574
|
-
|
|
575
|
-
|
|
576
487
|
async def _iterate_agent_id_batches(
|
|
577
488
|
batch_size: int = 100,
|
|
578
489
|
) -> AsyncGenerator[list[str], None]:
|
|
@@ -828,191 +739,3 @@ async def update_agents_statistics(
|
|
|
828
739
|
total_updated,
|
|
829
740
|
total_time,
|
|
830
741
|
)
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
async def list_autonomous_tasks(agent_id: str) -> List[AgentAutonomous]:
|
|
834
|
-
"""
|
|
835
|
-
List all autonomous tasks for an agent.
|
|
836
|
-
|
|
837
|
-
Args:
|
|
838
|
-
agent_id: ID of the agent
|
|
839
|
-
|
|
840
|
-
Returns:
|
|
841
|
-
List[AgentAutonomous]: List of autonomous task configurations
|
|
842
|
-
|
|
843
|
-
Raises:
|
|
844
|
-
IntentKitAPIError: If agent is not found
|
|
845
|
-
"""
|
|
846
|
-
agent = await Agent.get(agent_id)
|
|
847
|
-
if not agent:
|
|
848
|
-
raise IntentKitAPIError(
|
|
849
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
850
|
-
)
|
|
851
|
-
|
|
852
|
-
if not agent.autonomous:
|
|
853
|
-
return []
|
|
854
|
-
|
|
855
|
-
return agent.autonomous
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
async def add_autonomous_task(agent_id: str, task: AgentAutonomous) -> AgentAutonomous:
|
|
859
|
-
"""
|
|
860
|
-
Add a new autonomous task to an agent.
|
|
861
|
-
|
|
862
|
-
Args:
|
|
863
|
-
agent_id: ID of the agent
|
|
864
|
-
task: Autonomous task configuration (id will be generated if not provided)
|
|
865
|
-
|
|
866
|
-
Returns:
|
|
867
|
-
AgentAutonomous: The created task with generated ID
|
|
868
|
-
|
|
869
|
-
Raises:
|
|
870
|
-
IntentKitAPIError: If agent is not found
|
|
871
|
-
"""
|
|
872
|
-
agent = await Agent.get(agent_id)
|
|
873
|
-
if not agent:
|
|
874
|
-
raise IntentKitAPIError(
|
|
875
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
876
|
-
)
|
|
877
|
-
|
|
878
|
-
# Get current autonomous tasks
|
|
879
|
-
current_tasks = agent.autonomous or []
|
|
880
|
-
if not isinstance(current_tasks, list):
|
|
881
|
-
current_tasks = []
|
|
882
|
-
|
|
883
|
-
# Add the new task
|
|
884
|
-
current_tasks.append(task)
|
|
885
|
-
|
|
886
|
-
# Convert all AgentAutonomous objects to dictionaries for JSON serialization
|
|
887
|
-
serializable_tasks = [task_item.model_dump() for task_item in current_tasks]
|
|
888
|
-
|
|
889
|
-
# Update the agent in the database
|
|
890
|
-
async with get_session() as session:
|
|
891
|
-
update_stmt = (
|
|
892
|
-
update(AgentTable)
|
|
893
|
-
.where(AgentTable.id == agent_id)
|
|
894
|
-
.values(autonomous=serializable_tasks)
|
|
895
|
-
)
|
|
896
|
-
await session.execute(update_stmt)
|
|
897
|
-
await session.commit()
|
|
898
|
-
|
|
899
|
-
logger.info(f"Added autonomous task {task.id} to agent {agent_id}")
|
|
900
|
-
return task
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
async def delete_autonomous_task(agent_id: str, task_id: str) -> None:
|
|
904
|
-
"""
|
|
905
|
-
Delete an autonomous task from an agent.
|
|
906
|
-
|
|
907
|
-
Args:
|
|
908
|
-
agent_id: ID of the agent
|
|
909
|
-
task_id: ID of the task to delete
|
|
910
|
-
|
|
911
|
-
Raises:
|
|
912
|
-
IntentKitAPIError: If agent is not found or task is not found
|
|
913
|
-
"""
|
|
914
|
-
agent = await Agent.get(agent_id)
|
|
915
|
-
if not agent:
|
|
916
|
-
raise IntentKitAPIError(
|
|
917
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
918
|
-
)
|
|
919
|
-
|
|
920
|
-
# Get current autonomous tasks
|
|
921
|
-
current_tasks = agent.autonomous or []
|
|
922
|
-
if not isinstance(current_tasks, list):
|
|
923
|
-
current_tasks = []
|
|
924
|
-
|
|
925
|
-
# Find and remove the task
|
|
926
|
-
task_found = False
|
|
927
|
-
updated_tasks = []
|
|
928
|
-
for task_data in current_tasks:
|
|
929
|
-
if task_data.id == task_id:
|
|
930
|
-
task_found = True
|
|
931
|
-
continue
|
|
932
|
-
updated_tasks.append(task_data)
|
|
933
|
-
|
|
934
|
-
if not task_found:
|
|
935
|
-
raise IntentKitAPIError(
|
|
936
|
-
404, "TaskNotFound", f"Autonomous task with ID {task_id} not found."
|
|
937
|
-
)
|
|
938
|
-
|
|
939
|
-
# Convert remaining AgentAutonomous objects to dictionaries for JSON serialization
|
|
940
|
-
serializable_tasks = [task_item.model_dump() for task_item in updated_tasks]
|
|
941
|
-
|
|
942
|
-
# Update the agent in the database
|
|
943
|
-
async with get_session() as session:
|
|
944
|
-
update_stmt = (
|
|
945
|
-
update(AgentTable)
|
|
946
|
-
.where(AgentTable.id == agent_id)
|
|
947
|
-
.values(autonomous=serializable_tasks)
|
|
948
|
-
)
|
|
949
|
-
await session.execute(update_stmt)
|
|
950
|
-
await session.commit()
|
|
951
|
-
|
|
952
|
-
logger.info(f"Deleted autonomous task {task_id} from agent {agent_id}")
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
async def update_autonomous_task(
|
|
956
|
-
agent_id: str, task_id: str, task_updates: dict
|
|
957
|
-
) -> AgentAutonomous:
|
|
958
|
-
"""
|
|
959
|
-
Update an autonomous task for an agent.
|
|
960
|
-
|
|
961
|
-
Args:
|
|
962
|
-
agent_id: ID of the agent
|
|
963
|
-
task_id: ID of the task to update
|
|
964
|
-
task_updates: Dictionary containing fields to update
|
|
965
|
-
|
|
966
|
-
Returns:
|
|
967
|
-
AgentAutonomous: The updated task
|
|
968
|
-
|
|
969
|
-
Raises:
|
|
970
|
-
IntentKitAPIError: If agent is not found or task is not found
|
|
971
|
-
"""
|
|
972
|
-
agent = await Agent.get(agent_id)
|
|
973
|
-
if not agent:
|
|
974
|
-
raise IntentKitAPIError(
|
|
975
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
976
|
-
)
|
|
977
|
-
|
|
978
|
-
# Get current autonomous tasks
|
|
979
|
-
current_tasks: List[AgentAutonomous] = agent.autonomous or []
|
|
980
|
-
|
|
981
|
-
# Find and update the task
|
|
982
|
-
task_found = False
|
|
983
|
-
updated_tasks: List[AgentAutonomous] = []
|
|
984
|
-
updated_task = None
|
|
985
|
-
|
|
986
|
-
for task_data in current_tasks:
|
|
987
|
-
if task_data.id == task_id:
|
|
988
|
-
task_found = True
|
|
989
|
-
# Create a dictionary with current task data
|
|
990
|
-
task_dict = task_data.model_dump()
|
|
991
|
-
# Update with provided fields
|
|
992
|
-
task_dict.update(task_updates)
|
|
993
|
-
# Create new AgentAutonomous instance
|
|
994
|
-
updated_task = AgentAutonomous.model_validate(task_dict)
|
|
995
|
-
updated_tasks.append(updated_task)
|
|
996
|
-
else:
|
|
997
|
-
updated_tasks.append(task_data)
|
|
998
|
-
|
|
999
|
-
if not task_found:
|
|
1000
|
-
raise IntentKitAPIError(
|
|
1001
|
-
404, "TaskNotFound", f"Autonomous task with ID {task_id} not found."
|
|
1002
|
-
)
|
|
1003
|
-
|
|
1004
|
-
# Convert all AgentAutonomous objects to dictionaries for JSON serialization
|
|
1005
|
-
serializable_tasks = [task_item.model_dump() for task_item in updated_tasks]
|
|
1006
|
-
|
|
1007
|
-
# Update the agent in the database
|
|
1008
|
-
async with get_session() as session:
|
|
1009
|
-
update_stmt = (
|
|
1010
|
-
update(AgentTable)
|
|
1011
|
-
.where(AgentTable.id == agent_id)
|
|
1012
|
-
.values(autonomous=serializable_tasks)
|
|
1013
|
-
)
|
|
1014
|
-
await session.execute(update_stmt)
|
|
1015
|
-
await session.commit()
|
|
1016
|
-
|
|
1017
|
-
logger.info(f"Updated autonomous task {task_id} for agent {agent_id}")
|
|
1018
|
-
return updated_task
|
intentkit/core/engine.py
CHANGED
|
@@ -36,7 +36,6 @@ from sqlalchemy.exc import SQLAlchemyError
|
|
|
36
36
|
|
|
37
37
|
from intentkit.abstracts.graph import AgentContext, AgentError, AgentState
|
|
38
38
|
from intentkit.config.config import config
|
|
39
|
-
from intentkit.core.agent import agent_store
|
|
40
39
|
from intentkit.core.chat import clear_thread_memory
|
|
41
40
|
from intentkit.core.credit import expense_message, expense_skill
|
|
42
41
|
from intentkit.core.node import PreModelNode, post_model_node
|
|
@@ -56,7 +55,7 @@ from intentkit.models.chat import (
|
|
|
56
55
|
from intentkit.models.credit import CreditAccount, OwnerType
|
|
57
56
|
from intentkit.models.db import get_langgraph_checkpointer, get_session
|
|
58
57
|
from intentkit.models.llm import LLMModelInfo, LLMProvider, create_llm_model
|
|
59
|
-
from intentkit.models.skill import AgentSkillData, ChatSkillData
|
|
58
|
+
from intentkit.models.skill import AgentSkillData, ChatSkillData, Skill
|
|
60
59
|
from intentkit.models.user import User
|
|
61
60
|
from intentkit.utils.error import IntentKitAPIError
|
|
62
61
|
|
|
@@ -115,13 +114,13 @@ async def build_agent(
|
|
|
115
114
|
if hasattr(skill_module, "get_skills"):
|
|
116
115
|
# all
|
|
117
116
|
skill_tools = await skill_module.get_skills(
|
|
118
|
-
v, False,
|
|
117
|
+
v, False, agent_id=agent.id, agent=agent
|
|
119
118
|
)
|
|
120
119
|
if skill_tools and len(skill_tools) > 0:
|
|
121
120
|
tools.extend(skill_tools)
|
|
122
121
|
# private
|
|
123
122
|
skill_private_tools = await skill_module.get_skills(
|
|
124
|
-
v, True,
|
|
123
|
+
v, True, agent_id=agent.id, agent=agent
|
|
125
124
|
)
|
|
126
125
|
if skill_private_tools and len(skill_private_tools) > 0:
|
|
127
126
|
private_tools.extend(skill_private_tools)
|
|
@@ -703,6 +702,9 @@ async def stream_agent_raw(
|
|
|
703
702
|
for skill_call in skill_calls:
|
|
704
703
|
if not skill_call["success"]:
|
|
705
704
|
continue
|
|
705
|
+
skill = await Skill.get(skill_call["name"])
|
|
706
|
+
if not skill:
|
|
707
|
+
continue
|
|
706
708
|
payment_event = await expense_skill(
|
|
707
709
|
session,
|
|
708
710
|
payer,
|