intentkit 0.6.13.dev2__py3-none-any.whl → 0.8.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +1 -1
- intentkit/abstracts/agent.py +4 -5
- intentkit/abstracts/engine.py +5 -5
- intentkit/abstracts/graph.py +14 -7
- intentkit/abstracts/skill.py +6 -144
- intentkit/abstracts/twitter.py +4 -5
- intentkit/clients/__init__.py +5 -2
- intentkit/clients/cdp.py +101 -141
- intentkit/clients/twitter.py +83 -62
- intentkit/clients/web3.py +29 -0
- intentkit/config/config.py +8 -5
- intentkit/core/agent.py +472 -195
- intentkit/core/asset.py +253 -0
- intentkit/core/chat.py +51 -0
- intentkit/core/client.py +1 -1
- intentkit/core/credit.py +460 -130
- intentkit/core/engine.py +262 -233
- intentkit/core/node.py +15 -16
- intentkit/core/prompt.py +62 -28
- intentkit/core/scheduler.py +92 -0
- intentkit/core/statistics.py +168 -0
- intentkit/models/agent.py +1096 -949
- intentkit/models/agent_data.py +68 -38
- intentkit/models/agent_public.json +98 -0
- intentkit/models/agent_schema.json +54 -439
- intentkit/models/app_setting.py +96 -33
- intentkit/models/chat.py +74 -27
- intentkit/models/conversation.py +8 -8
- intentkit/models/credit.py +362 -74
- intentkit/models/db.py +26 -8
- intentkit/models/db_mig.py +2 -2
- intentkit/models/llm.csv +28 -0
- intentkit/models/llm.py +185 -350
- intentkit/models/redis.py +6 -4
- intentkit/models/skill.py +186 -72
- intentkit/models/skills.csv +174 -0
- intentkit/models/user.py +82 -24
- intentkit/skills/acolyt/__init__.py +2 -9
- intentkit/skills/acolyt/ask.py +3 -4
- intentkit/skills/acolyt/base.py +4 -9
- intentkit/skills/acolyt/schema.json +4 -3
- intentkit/skills/aixbt/__init__.py +2 -13
- intentkit/skills/aixbt/base.py +1 -7
- intentkit/skills/aixbt/projects.py +14 -15
- intentkit/skills/aixbt/schema.json +4 -4
- intentkit/skills/allora/__init__.py +2 -9
- intentkit/skills/allora/base.py +4 -9
- intentkit/skills/allora/price.py +3 -4
- intentkit/skills/allora/schema.json +3 -2
- intentkit/skills/base.py +248 -85
- intentkit/skills/basename/__init__.py +51 -0
- intentkit/skills/basename/base.py +11 -0
- intentkit/skills/basename/basename.svg +11 -0
- intentkit/skills/basename/schema.json +58 -0
- intentkit/skills/carv/__init__.py +115 -121
- intentkit/skills/carv/base.py +184 -185
- intentkit/skills/carv/fetch_news.py +3 -3
- intentkit/skills/carv/onchain_query.py +4 -4
- intentkit/skills/carv/schema.json +134 -137
- intentkit/skills/carv/token_info_and_price.py +5 -5
- intentkit/skills/casino/README.md +254 -0
- intentkit/skills/casino/__init__.py +86 -0
- intentkit/skills/casino/base.py +17 -0
- intentkit/skills/casino/casino.png +0 -0
- intentkit/skills/casino/deck_draw.py +127 -0
- intentkit/skills/casino/deck_shuffle.py +118 -0
- intentkit/skills/casino/dice_roll.py +100 -0
- intentkit/skills/casino/schema.json +77 -0
- intentkit/skills/casino/utils.py +107 -0
- intentkit/skills/cdp/__init__.py +22 -84
- intentkit/skills/cdp/base.py +1 -7
- intentkit/skills/cdp/schema.json +11 -314
- intentkit/skills/chainlist/__init__.py +2 -7
- intentkit/skills/chainlist/base.py +1 -7
- intentkit/skills/chainlist/chain_lookup.py +18 -18
- intentkit/skills/chainlist/schema.json +3 -5
- intentkit/skills/common/__init__.py +2 -9
- intentkit/skills/common/base.py +1 -7
- intentkit/skills/common/current_time.py +1 -2
- intentkit/skills/common/schema.json +2 -2
- intentkit/skills/cookiefun/__init__.py +6 -9
- intentkit/skills/cookiefun/base.py +2 -7
- intentkit/skills/cookiefun/get_account_details.py +7 -7
- intentkit/skills/cookiefun/get_account_feed.py +19 -19
- intentkit/skills/cookiefun/get_account_smart_followers.py +7 -7
- intentkit/skills/cookiefun/get_sectors.py +3 -3
- intentkit/skills/cookiefun/schema.json +1 -3
- intentkit/skills/cookiefun/search_accounts.py +9 -9
- intentkit/skills/cryptocompare/__init__.py +7 -24
- intentkit/skills/cryptocompare/api.py +2 -3
- intentkit/skills/cryptocompare/base.py +11 -25
- intentkit/skills/cryptocompare/fetch_news.py +4 -5
- intentkit/skills/cryptocompare/fetch_price.py +6 -7
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +4 -5
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +4 -5
- intentkit/skills/cryptocompare/fetch_top_volume.py +4 -5
- intentkit/skills/cryptocompare/fetch_trading_signals.py +5 -6
- intentkit/skills/cryptocompare/schema.json +3 -3
- intentkit/skills/cryptopanic/__init__.py +7 -10
- intentkit/skills/cryptopanic/base.py +51 -55
- intentkit/skills/cryptopanic/fetch_crypto_news.py +4 -8
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +5 -7
- intentkit/skills/cryptopanic/schema.json +105 -103
- intentkit/skills/dapplooker/__init__.py +2 -9
- intentkit/skills/dapplooker/base.py +4 -9
- intentkit/skills/dapplooker/dapplooker_token_data.py +7 -7
- intentkit/skills/dapplooker/schema.json +3 -5
- intentkit/skills/defillama/__init__.py +24 -74
- intentkit/skills/defillama/api.py +6 -9
- intentkit/skills/defillama/base.py +11 -21
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +8 -10
- intentkit/skills/defillama/coins/fetch_block.py +6 -8
- intentkit/skills/defillama/coins/fetch_current_prices.py +8 -10
- intentkit/skills/defillama/coins/fetch_first_price.py +7 -9
- intentkit/skills/defillama/coins/fetch_historical_prices.py +9 -11
- intentkit/skills/defillama/coins/fetch_price_chart.py +9 -11
- intentkit/skills/defillama/coins/fetch_price_percentage.py +7 -9
- intentkit/skills/defillama/config/chains.py +1 -3
- intentkit/skills/defillama/fees/fetch_fees_overview.py +24 -26
- intentkit/skills/defillama/schema.json +5 -1
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +16 -18
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +8 -10
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +5 -7
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +7 -9
- intentkit/skills/defillama/tests/api_integration.test.py +1 -1
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +4 -6
- intentkit/skills/defillama/tvl/fetch_chains.py +9 -11
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +4 -6
- intentkit/skills/defillama/tvl/fetch_protocol.py +32 -38
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +3 -5
- intentkit/skills/defillama/tvl/fetch_protocols.py +37 -45
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +42 -48
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +35 -37
- intentkit/skills/defillama/volumes/fetch_options_overview.py +24 -28
- intentkit/skills/defillama/yields/fetch_pool_chart.py +10 -12
- intentkit/skills/defillama/yields/fetch_pools.py +26 -30
- intentkit/skills/dexscreener/README.md +154 -0
- intentkit/skills/dexscreener/__init__.py +97 -93
- intentkit/skills/dexscreener/base.py +125 -133
- intentkit/skills/dexscreener/get_pair_info.py +158 -0
- intentkit/skills/dexscreener/get_token_pairs.py +165 -0
- intentkit/skills/dexscreener/get_tokens_info.py +212 -0
- intentkit/skills/dexscreener/model/search_token_response.py +80 -82
- intentkit/skills/dexscreener/schema.json +91 -48
- intentkit/skills/dexscreener/search_token.py +182 -321
- intentkit/skills/dexscreener/utils.py +420 -0
- intentkit/skills/dune_analytics/__init__.py +7 -9
- intentkit/skills/dune_analytics/base.py +48 -52
- intentkit/skills/dune_analytics/fetch_kol_buys.py +5 -7
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +6 -8
- intentkit/skills/dune_analytics/schema.json +104 -99
- intentkit/skills/elfa/__init__.py +5 -18
- intentkit/skills/elfa/base.py +10 -14
- intentkit/skills/elfa/mention.py +19 -21
- intentkit/skills/elfa/schema.json +3 -2
- intentkit/skills/elfa/stats.py +4 -4
- intentkit/skills/elfa/tokens.py +12 -12
- intentkit/skills/elfa/utils.py +26 -28
- intentkit/skills/enso/__init__.py +11 -31
- intentkit/skills/enso/base.py +50 -35
- intentkit/skills/enso/best_yield.py +16 -24
- intentkit/skills/enso/networks.py +6 -11
- intentkit/skills/enso/prices.py +11 -13
- intentkit/skills/enso/route.py +34 -38
- intentkit/skills/enso/schema.json +3 -2
- intentkit/skills/enso/tokens.py +29 -38
- intentkit/skills/enso/wallet.py +76 -191
- intentkit/skills/erc20/__init__.py +50 -0
- intentkit/skills/erc20/base.py +11 -0
- intentkit/skills/erc20/erc20.svg +5 -0
- intentkit/skills/erc20/schema.json +74 -0
- intentkit/skills/erc721/__init__.py +53 -0
- intentkit/skills/erc721/base.py +11 -0
- intentkit/skills/erc721/erc721.svg +5 -0
- intentkit/skills/erc721/schema.json +90 -0
- intentkit/skills/firecrawl/README.md +11 -5
- intentkit/skills/firecrawl/__init__.py +5 -18
- intentkit/skills/firecrawl/base.py +4 -11
- intentkit/skills/firecrawl/clear.py +4 -8
- intentkit/skills/firecrawl/crawl.py +19 -19
- intentkit/skills/firecrawl/query.py +4 -3
- intentkit/skills/firecrawl/schema.json +6 -8
- intentkit/skills/firecrawl/scrape.py +150 -40
- intentkit/skills/firecrawl/utils.py +50 -42
- intentkit/skills/github/__init__.py +2 -7
- intentkit/skills/github/base.py +1 -7
- intentkit/skills/github/github_search.py +1 -2
- intentkit/skills/github/schema.json +3 -4
- intentkit/skills/heurist/__init__.py +8 -27
- intentkit/skills/heurist/base.py +4 -9
- intentkit/skills/heurist/image_generation_animagine_xl.py +12 -13
- intentkit/skills/heurist/image_generation_arthemy_comics.py +12 -13
- intentkit/skills/heurist/image_generation_arthemy_real.py +12 -13
- intentkit/skills/heurist/image_generation_braindance.py +12 -13
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +12 -13
- intentkit/skills/heurist/image_generation_flux_1_dev.py +12 -13
- intentkit/skills/heurist/image_generation_sdxl.py +12 -13
- intentkit/skills/heurist/schema.json +2 -2
- intentkit/skills/http/__init__.py +4 -15
- intentkit/skills/http/base.py +1 -7
- intentkit/skills/http/get.py +21 -16
- intentkit/skills/http/post.py +23 -18
- intentkit/skills/http/put.py +23 -18
- intentkit/skills/http/schema.json +4 -5
- intentkit/skills/lifi/__init__.py +8 -13
- intentkit/skills/lifi/base.py +1 -7
- intentkit/skills/lifi/schema.json +17 -8
- intentkit/skills/lifi/token_execute.py +36 -30
- intentkit/skills/lifi/token_quote.py +8 -10
- intentkit/skills/lifi/utils.py +104 -51
- intentkit/skills/moralis/__init__.py +6 -10
- intentkit/skills/moralis/api.py +6 -7
- intentkit/skills/moralis/base.py +5 -10
- intentkit/skills/moralis/fetch_chain_portfolio.py +10 -11
- intentkit/skills/moralis/fetch_nft_portfolio.py +22 -22
- intentkit/skills/moralis/fetch_solana_portfolio.py +11 -12
- intentkit/skills/moralis/fetch_wallet_portfolio.py +8 -9
- intentkit/skills/moralis/schema.json +7 -2
- intentkit/skills/morpho/__init__.py +52 -0
- intentkit/skills/morpho/base.py +11 -0
- intentkit/skills/morpho/morpho.svg +12 -0
- intentkit/skills/morpho/schema.json +73 -0
- intentkit/skills/nation/__init__.py +4 -9
- intentkit/skills/nation/base.py +5 -10
- intentkit/skills/nation/nft_check.py +3 -4
- intentkit/skills/nation/schema.json +4 -3
- intentkit/skills/onchain.py +23 -0
- intentkit/skills/openai/__init__.py +17 -18
- intentkit/skills/openai/base.py +10 -14
- intentkit/skills/openai/dalle_image_generation.py +3 -8
- intentkit/skills/openai/gpt_avatar_generator.py +102 -0
- intentkit/skills/openai/gpt_image_generation.py +4 -8
- intentkit/skills/openai/gpt_image_mini_generator.py +91 -0
- intentkit/skills/openai/gpt_image_to_image.py +4 -8
- intentkit/skills/openai/image_to_text.py +3 -7
- intentkit/skills/openai/schema.json +34 -3
- intentkit/skills/portfolio/__init__.py +11 -35
- intentkit/skills/portfolio/base.py +33 -19
- intentkit/skills/portfolio/schema.json +3 -5
- intentkit/skills/portfolio/token_balances.py +21 -21
- intentkit/skills/portfolio/wallet_approvals.py +17 -18
- intentkit/skills/portfolio/wallet_defi_positions.py +3 -3
- intentkit/skills/portfolio/wallet_history.py +31 -31
- intentkit/skills/portfolio/wallet_net_worth.py +13 -13
- intentkit/skills/portfolio/wallet_nfts.py +19 -19
- intentkit/skills/portfolio/wallet_profitability.py +18 -18
- intentkit/skills/portfolio/wallet_profitability_summary.py +5 -5
- intentkit/skills/portfolio/wallet_stats.py +3 -3
- intentkit/skills/portfolio/wallet_swaps.py +19 -19
- intentkit/skills/pyth/__init__.py +50 -0
- intentkit/skills/pyth/base.py +11 -0
- intentkit/skills/pyth/pyth.svg +6 -0
- intentkit/skills/pyth/schema.json +75 -0
- intentkit/skills/skills.toml +40 -0
- intentkit/skills/slack/__init__.py +5 -17
- intentkit/skills/slack/base.py +3 -9
- intentkit/skills/slack/get_channel.py +8 -8
- intentkit/skills/slack/get_message.py +9 -9
- intentkit/skills/slack/schedule_message.py +5 -5
- intentkit/skills/slack/schema.json +2 -2
- intentkit/skills/slack/send_message.py +3 -5
- intentkit/skills/supabase/__init__.py +7 -23
- intentkit/skills/supabase/base.py +9 -13
- intentkit/skills/supabase/delete_data.py +5 -6
- intentkit/skills/supabase/fetch_data.py +13 -14
- intentkit/skills/supabase/insert_data.py +5 -6
- intentkit/skills/supabase/invoke_function.py +7 -8
- intentkit/skills/supabase/schema.json +2 -3
- intentkit/skills/supabase/update_data.py +7 -8
- intentkit/skills/supabase/upsert_data.py +5 -6
- intentkit/skills/superfluid/__init__.py +53 -0
- intentkit/skills/superfluid/base.py +11 -0
- intentkit/skills/superfluid/schema.json +89 -0
- intentkit/skills/superfluid/superfluid.svg +6 -0
- intentkit/skills/system/__init__.py +7 -24
- intentkit/skills/system/add_autonomous_task.py +10 -12
- intentkit/skills/system/delete_autonomous_task.py +2 -2
- intentkit/skills/system/edit_autonomous_task.py +14 -18
- intentkit/skills/system/list_autonomous_tasks.py +3 -5
- intentkit/skills/system/read_agent_api_key.py +6 -4
- intentkit/skills/system/regenerate_agent_api_key.py +6 -4
- intentkit/skills/system/schema.json +6 -8
- intentkit/skills/tavily/__init__.py +3 -12
- intentkit/skills/tavily/base.py +4 -9
- intentkit/skills/tavily/schema.json +3 -5
- intentkit/skills/tavily/tavily_extract.py +2 -4
- intentkit/skills/tavily/tavily_search.py +4 -6
- intentkit/skills/token/__init__.py +5 -10
- intentkit/skills/token/base.py +7 -11
- intentkit/skills/token/erc20_transfers.py +19 -19
- intentkit/skills/token/schema.json +3 -6
- intentkit/skills/token/token_analytics.py +3 -3
- intentkit/skills/token/token_price.py +13 -13
- intentkit/skills/token/token_search.py +9 -9
- intentkit/skills/twitter/__init__.py +11 -35
- intentkit/skills/twitter/base.py +23 -35
- intentkit/skills/twitter/follow_user.py +3 -7
- intentkit/skills/twitter/get_mentions.py +6 -13
- intentkit/skills/twitter/get_timeline.py +5 -13
- intentkit/skills/twitter/get_user_by_username.py +3 -7
- intentkit/skills/twitter/get_user_tweets.py +6 -14
- intentkit/skills/twitter/like_tweet.py +3 -7
- intentkit/skills/twitter/post_tweet.py +23 -12
- intentkit/skills/twitter/reply_tweet.py +21 -12
- intentkit/skills/twitter/retweet.py +3 -7
- intentkit/skills/twitter/schema.json +1 -0
- intentkit/skills/twitter/search_tweets.py +5 -13
- intentkit/skills/unrealspeech/__init__.py +2 -7
- intentkit/skills/unrealspeech/base.py +2 -8
- intentkit/skills/unrealspeech/schema.json +2 -5
- intentkit/skills/unrealspeech/text_to_speech.py +8 -8
- intentkit/skills/venice_audio/__init__.py +98 -106
- intentkit/skills/venice_audio/base.py +117 -121
- intentkit/skills/venice_audio/input.py +41 -41
- intentkit/skills/venice_audio/schema.json +151 -152
- intentkit/skills/venice_audio/venice_audio.py +38 -21
- intentkit/skills/venice_image/__init__.py +147 -154
- intentkit/skills/venice_image/api.py +138 -138
- intentkit/skills/venice_image/base.py +185 -192
- intentkit/skills/venice_image/config.py +33 -35
- intentkit/skills/venice_image/image_enhance/image_enhance.py +2 -3
- intentkit/skills/venice_image/image_enhance/image_enhance_base.py +21 -23
- intentkit/skills/venice_image/image_enhance/image_enhance_input.py +38 -40
- intentkit/skills/venice_image/image_generation/image_generation_base.py +9 -9
- intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -27
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -158
- intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -26
- intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -28
- intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -28
- intentkit/skills/venice_image/image_upscale/image_upscale.py +3 -3
- intentkit/skills/venice_image/image_upscale/image_upscale_base.py +21 -23
- intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -22
- intentkit/skills/venice_image/image_vision/image_vision.py +2 -2
- intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -17
- intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -9
- intentkit/skills/venice_image/schema.json +267 -267
- intentkit/skills/venice_image/utils.py +77 -78
- intentkit/skills/web_scraper/__init__.py +5 -18
- intentkit/skills/web_scraper/base.py +21 -7
- intentkit/skills/web_scraper/document_indexer.py +7 -6
- intentkit/skills/web_scraper/schema.json +2 -6
- intentkit/skills/web_scraper/scrape_and_index.py +15 -15
- intentkit/skills/web_scraper/utils.py +62 -63
- intentkit/skills/web_scraper/website_indexer.py +17 -19
- intentkit/skills/weth/__init__.py +49 -0
- intentkit/skills/weth/base.py +11 -0
- intentkit/skills/weth/schema.json +58 -0
- intentkit/skills/weth/weth.svg +6 -0
- intentkit/skills/wow/__init__.py +51 -0
- intentkit/skills/wow/base.py +11 -0
- intentkit/skills/wow/schema.json +89 -0
- intentkit/skills/wow/wow.svg +7 -0
- intentkit/skills/x402/__init__.py +61 -0
- intentkit/skills/x402/ask_agent.py +98 -0
- intentkit/skills/x402/base.py +99 -0
- intentkit/skills/x402/http_request.py +117 -0
- intentkit/skills/x402/schema.json +45 -0
- intentkit/skills/x402/x402.webp +0 -0
- intentkit/skills/xmtp/__init__.py +4 -15
- intentkit/skills/xmtp/base.py +61 -2
- intentkit/skills/xmtp/price.py +18 -13
- intentkit/skills/xmtp/schema.json +69 -71
- intentkit/skills/xmtp/swap.py +22 -25
- intentkit/skills/xmtp/transfer.py +71 -32
- intentkit/utils/chain.py +3 -3
- intentkit/utils/error.py +14 -1
- intentkit/utils/logging.py +2 -4
- intentkit/utils/s3.py +59 -7
- intentkit/utils/schema.py +100 -0
- intentkit/utils/slack_alert.py +7 -8
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/METADATA +14 -16
- intentkit-0.8.17.dist-info/RECORD +466 -0
- intentkit/abstracts/exception.py +0 -9
- intentkit/core/skill.py +0 -200
- intentkit/models/generator.py +0 -347
- intentkit/skills/cdp/get_balance.py +0 -110
- intentkit/skills/cdp/swap.py +0 -121
- intentkit/skills/moralis/tests/__init__.py +0 -0
- intentkit/skills/moralis/tests/test_wallet.py +0 -511
- intentkit-0.6.13.dev2.dist-info/RECORD +0 -409
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/WHEEL +0 -0
- {intentkit-0.6.13.dev2.dist-info → intentkit-0.8.17.dist-info}/licenses/LICENSE +0 -0
intentkit/core/agent.py
CHANGED
|
@@ -1,21 +1,313 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import AsyncGenerator
|
|
4
|
+
from datetime import UTC, datetime, timedelta
|
|
4
5
|
from decimal import Decimal
|
|
5
|
-
from typing import Dict, List
|
|
6
6
|
|
|
7
7
|
from sqlalchemy import func, select, text, update
|
|
8
8
|
|
|
9
|
-
from intentkit.
|
|
10
|
-
from intentkit.
|
|
11
|
-
from intentkit.models.
|
|
9
|
+
from intentkit.clients.cdp import get_wallet_provider
|
|
10
|
+
from intentkit.config.config import config
|
|
11
|
+
from intentkit.models.agent import (
|
|
12
|
+
Agent,
|
|
13
|
+
AgentCreate,
|
|
14
|
+
AgentTable,
|
|
15
|
+
AgentUpdate,
|
|
16
|
+
)
|
|
17
|
+
from intentkit.models.agent_data import AgentData, AgentQuotaTable
|
|
18
|
+
from intentkit.models.credit import (
|
|
19
|
+
CreditAccount,
|
|
20
|
+
CreditEventTable,
|
|
21
|
+
EventType,
|
|
22
|
+
OwnerType,
|
|
23
|
+
UpstreamType,
|
|
24
|
+
)
|
|
12
25
|
from intentkit.models.db import get_session
|
|
13
26
|
from intentkit.utils.error import IntentKitAPIError
|
|
27
|
+
from intentkit.utils.slack_alert import send_slack_message
|
|
14
28
|
|
|
15
29
|
logger = logging.getLogger(__name__)
|
|
16
30
|
|
|
17
31
|
|
|
18
|
-
async def
|
|
32
|
+
async def process_agent_wallet(
|
|
33
|
+
agent: Agent, old_wallet_provider: str | None = None
|
|
34
|
+
) -> AgentData:
|
|
35
|
+
"""Process agent wallet initialization and validation.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
agent: The agent that was created or updated
|
|
39
|
+
old_wallet_provider: Previous wallet provider (None, "cdp", or "readonly")
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
AgentData: The processed agent data
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
IntentKitAPIError: If attempting to change between cdp and readonly providers
|
|
46
|
+
"""
|
|
47
|
+
current_wallet_provider = agent.wallet_provider
|
|
48
|
+
|
|
49
|
+
# 1. Check if changing between cdp and readonly (not allowed)
|
|
50
|
+
if (
|
|
51
|
+
old_wallet_provider is not None
|
|
52
|
+
and old_wallet_provider != "none"
|
|
53
|
+
and old_wallet_provider != current_wallet_provider
|
|
54
|
+
):
|
|
55
|
+
raise IntentKitAPIError(
|
|
56
|
+
400,
|
|
57
|
+
"WalletProviderChangeNotAllowed",
|
|
58
|
+
"Cannot change wallet provider between cdp and readonly",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# 2. If wallet provider hasn't changed, return existing agent data
|
|
62
|
+
if (
|
|
63
|
+
old_wallet_provider is not None
|
|
64
|
+
and old_wallet_provider != "none"
|
|
65
|
+
and old_wallet_provider == current_wallet_provider
|
|
66
|
+
):
|
|
67
|
+
return await AgentData.get(agent.id)
|
|
68
|
+
|
|
69
|
+
# 3. For new agents (old_wallet_provider is None), check if wallet already exists
|
|
70
|
+
agent_data = await AgentData.get(agent.id)
|
|
71
|
+
if agent_data.evm_wallet_address:
|
|
72
|
+
return agent_data
|
|
73
|
+
|
|
74
|
+
# 4. Initialize wallet based on provider type
|
|
75
|
+
if config.cdp_api_key_id and current_wallet_provider == "cdp":
|
|
76
|
+
await get_wallet_provider(agent)
|
|
77
|
+
agent_data = await AgentData.get(agent.id)
|
|
78
|
+
elif current_wallet_provider == "readonly":
|
|
79
|
+
agent_data = await AgentData.patch(
|
|
80
|
+
agent.id,
|
|
81
|
+
{
|
|
82
|
+
"evm_wallet_address": agent.readonly_wallet_address,
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return agent_data
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def send_agent_notification(agent: Agent, agent_data: AgentData, message: str) -> None:
|
|
90
|
+
"""Send a notification about agent creation or update.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
agent: The agent that was created or updated
|
|
94
|
+
agent_data: The agent data to update
|
|
95
|
+
message: The notification message
|
|
96
|
+
"""
|
|
97
|
+
# Format autonomous configurations - show only enabled ones with their id, name, and schedule
|
|
98
|
+
autonomous_formatted = ""
|
|
99
|
+
if agent.autonomous:
|
|
100
|
+
enabled_autonomous = [auto for auto in agent.autonomous if auto.enabled]
|
|
101
|
+
if enabled_autonomous:
|
|
102
|
+
autonomous_items = []
|
|
103
|
+
for auto in enabled_autonomous:
|
|
104
|
+
schedule = (
|
|
105
|
+
f"cron: {auto.cron}" if auto.cron else f"minutes: {auto.minutes}"
|
|
106
|
+
)
|
|
107
|
+
autonomous_items.append(
|
|
108
|
+
f"• {auto.id}: {auto.name or 'Unnamed'} ({schedule})"
|
|
109
|
+
)
|
|
110
|
+
autonomous_formatted = "\n".join(autonomous_items)
|
|
111
|
+
else:
|
|
112
|
+
autonomous_formatted = "No enabled autonomous configurations"
|
|
113
|
+
else:
|
|
114
|
+
autonomous_formatted = "None"
|
|
115
|
+
|
|
116
|
+
# Format skills - find categories with enabled: true and list skills in public/private states
|
|
117
|
+
skills_formatted = ""
|
|
118
|
+
if agent.skills:
|
|
119
|
+
enabled_categories = []
|
|
120
|
+
for category, skill_config in agent.skills.items():
|
|
121
|
+
if skill_config and skill_config.get("enabled") is True:
|
|
122
|
+
skills_list = []
|
|
123
|
+
states = skill_config.get("states", {})
|
|
124
|
+
public_skills = [
|
|
125
|
+
skill for skill, state in states.items() if state == "public"
|
|
126
|
+
]
|
|
127
|
+
private_skills = [
|
|
128
|
+
skill for skill, state in states.items() if state == "private"
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
if public_skills:
|
|
132
|
+
skills_list.append(f" Public: {', '.join(public_skills)}")
|
|
133
|
+
if private_skills:
|
|
134
|
+
skills_list.append(f" Private: {', '.join(private_skills)}")
|
|
135
|
+
|
|
136
|
+
if skills_list:
|
|
137
|
+
enabled_categories.append(
|
|
138
|
+
f"• {category}:\n{chr(10).join(skills_list)}"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if enabled_categories:
|
|
142
|
+
skills_formatted = "\n".join(enabled_categories)
|
|
143
|
+
else:
|
|
144
|
+
skills_formatted = "No enabled skills"
|
|
145
|
+
else:
|
|
146
|
+
skills_formatted = "None"
|
|
147
|
+
|
|
148
|
+
send_slack_message(
|
|
149
|
+
message,
|
|
150
|
+
attachments=[
|
|
151
|
+
{
|
|
152
|
+
"color": "good",
|
|
153
|
+
"fields": [
|
|
154
|
+
{"title": "ID", "short": True, "value": agent.id},
|
|
155
|
+
{"title": "Name", "short": True, "value": agent.name},
|
|
156
|
+
{"title": "Model", "short": True, "value": agent.model},
|
|
157
|
+
{
|
|
158
|
+
"title": "Network",
|
|
159
|
+
"short": True,
|
|
160
|
+
"value": agent.network_id or "Not Set",
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"title": "X Username",
|
|
164
|
+
"short": True,
|
|
165
|
+
"value": agent_data.twitter_username,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"title": "Telegram Enabled",
|
|
169
|
+
"short": True,
|
|
170
|
+
"value": str(agent.telegram_entrypoint_enabled),
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"title": "Telegram Username",
|
|
174
|
+
"short": True,
|
|
175
|
+
"value": agent_data.telegram_username,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"title": "Wallet Address",
|
|
179
|
+
"value": agent_data.evm_wallet_address,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"title": "Autonomous",
|
|
183
|
+
"value": autonomous_formatted,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"title": "Skills",
|
|
187
|
+
"value": skills_formatted,
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def override_agent(
|
|
196
|
+
agent_id: str, agent: AgentUpdate, owner: str | None = None
|
|
197
|
+
) -> tuple[Agent, AgentData]:
|
|
198
|
+
"""Override an existing agent with new configuration.
|
|
199
|
+
|
|
200
|
+
This function updates an existing agent with the provided configuration.
|
|
201
|
+
If some fields are not provided, they will be reset to default values.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
agent_id: ID of the agent to override
|
|
205
|
+
agent: Agent update configuration containing the new settings
|
|
206
|
+
owner: Optional owner for permission validation
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
tuple[Agent, AgentData]: Updated agent configuration and processed agent data
|
|
210
|
+
|
|
211
|
+
Raises:
|
|
212
|
+
IntentKitAPIError:
|
|
213
|
+
- 404: Agent not found
|
|
214
|
+
- 403: Permission denied (if owner mismatch)
|
|
215
|
+
- 400: Invalid configuration or wallet provider change
|
|
216
|
+
"""
|
|
217
|
+
existing_agent = await Agent.get(agent_id)
|
|
218
|
+
if not existing_agent:
|
|
219
|
+
raise IntentKitAPIError(
|
|
220
|
+
status_code=404,
|
|
221
|
+
key="AgentNotFound",
|
|
222
|
+
message=f"Agent with ID '{agent_id}' not found",
|
|
223
|
+
)
|
|
224
|
+
if owner and owner != existing_agent.owner:
|
|
225
|
+
raise IntentKitAPIError(403, "Forbidden", "forbidden")
|
|
226
|
+
|
|
227
|
+
# Update agent
|
|
228
|
+
latest_agent = await agent.override(agent_id)
|
|
229
|
+
agent_data = await process_agent_wallet(
|
|
230
|
+
latest_agent, existing_agent.wallet_provider
|
|
231
|
+
)
|
|
232
|
+
send_agent_notification(latest_agent, agent_data, "Agent Overridden Deployed")
|
|
233
|
+
|
|
234
|
+
return latest_agent, agent_data
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
async def create_agent(agent: AgentCreate) -> tuple[Agent, AgentData]:
|
|
238
|
+
"""Create a new agent with the provided configuration.
|
|
239
|
+
|
|
240
|
+
This function creates a new agent instance with the given configuration,
|
|
241
|
+
initializes its wallet, and sends a notification about the creation.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
agent: Agent creation configuration containing all necessary settings
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
tuple[Agent, AgentData]: Created agent configuration and processed agent data
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
IntentKitAPIError:
|
|
251
|
+
- 400: Agent with upstream ID already exists or invalid configuration
|
|
252
|
+
- 500: Database error or wallet initialization failure
|
|
253
|
+
"""
|
|
254
|
+
if not agent.owner:
|
|
255
|
+
agent.owner = "system"
|
|
256
|
+
# Check for existing agent by upstream_id, forward compatibility, raise error after 3.0
|
|
257
|
+
existing = await agent.get_by_upstream_id()
|
|
258
|
+
if existing:
|
|
259
|
+
raise IntentKitAPIError(
|
|
260
|
+
status_code=400,
|
|
261
|
+
key="BadRequest",
|
|
262
|
+
message="Agent with this upstream ID already exists",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Create new agent
|
|
266
|
+
latest_agent = await agent.create()
|
|
267
|
+
agent_data = await process_agent_wallet(latest_agent)
|
|
268
|
+
send_agent_notification(latest_agent, agent_data, "Agent Deployed")
|
|
269
|
+
|
|
270
|
+
return latest_agent, agent_data
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
async def deploy_agent(
|
|
274
|
+
agent_id: str, agent: AgentUpdate, owner: str | None = None
|
|
275
|
+
) -> tuple[Agent, AgentData]:
|
|
276
|
+
"""Deploy an agent by first attempting to override, then creating if not found.
|
|
277
|
+
|
|
278
|
+
This function first tries to override an existing agent. If the agent is not found
|
|
279
|
+
(404 error), it will create a new agent instead.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
agent_id: ID of the agent to deploy
|
|
283
|
+
agent: Agent configuration data
|
|
284
|
+
owner: Optional owner for the agent
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
tuple[Agent, AgentData]: Deployed agent configuration and processed agent data
|
|
288
|
+
|
|
289
|
+
Raises:
|
|
290
|
+
IntentKitAPIError:
|
|
291
|
+
- 400: Invalid agent configuration or upstream ID conflict
|
|
292
|
+
- 403: Permission denied (if owner mismatch)
|
|
293
|
+
- 500: Database error
|
|
294
|
+
"""
|
|
295
|
+
try:
|
|
296
|
+
# First try to override the existing agent
|
|
297
|
+
return await override_agent(agent_id, agent, owner)
|
|
298
|
+
except IntentKitAPIError as e:
|
|
299
|
+
# If agent not found (404), create a new one
|
|
300
|
+
if e.status_code == 404:
|
|
301
|
+
new_agent = AgentCreate.model_validate(agent)
|
|
302
|
+
new_agent.id = agent_id
|
|
303
|
+
new_agent.owner = owner
|
|
304
|
+
return await create_agent(new_agent)
|
|
305
|
+
else:
|
|
306
|
+
# Re-raise other errors
|
|
307
|
+
raise
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
async def agent_action_cost(agent_id: str) -> dict[str, Decimal]:
|
|
19
311
|
"""
|
|
20
312
|
Calculate various action cost metrics for an agent based on past three days of credit events.
|
|
21
313
|
|
|
@@ -31,7 +323,7 @@ async def agent_action_cost(agent_id: str) -> Dict[str, Decimal]:
|
|
|
31
323
|
agent_id: ID of the agent
|
|
32
324
|
|
|
33
325
|
Returns:
|
|
34
|
-
|
|
326
|
+
dict[str, Decimal]: Dictionary containing all calculated cost metrics
|
|
35
327
|
"""
|
|
36
328
|
start_time = time.time()
|
|
37
329
|
default_value = Decimal("0")
|
|
@@ -44,7 +336,7 @@ async def agent_action_cost(agent_id: str) -> Dict[str, Decimal]:
|
|
|
44
336
|
|
|
45
337
|
async with get_session() as session:
|
|
46
338
|
# Calculate the date 3 days ago from now
|
|
47
|
-
three_days_ago = datetime.now(
|
|
339
|
+
three_days_ago = datetime.now(UTC) - timedelta(days=3)
|
|
48
340
|
|
|
49
341
|
# First, count the number of distinct start_message_ids to determine if we have enough data
|
|
50
342
|
count_query = select(
|
|
@@ -192,7 +484,31 @@ async def agent_action_cost(agent_id: str) -> Dict[str, Decimal]:
|
|
|
192
484
|
return result
|
|
193
485
|
|
|
194
486
|
|
|
195
|
-
async def
|
|
487
|
+
async def _iterate_agent_id_batches(
|
|
488
|
+
batch_size: int = 100,
|
|
489
|
+
) -> AsyncGenerator[list[str], None]:
|
|
490
|
+
"""Yield agent IDs in ascending batches to limit memory usage."""
|
|
491
|
+
|
|
492
|
+
last_id: str | None = None
|
|
493
|
+
while True:
|
|
494
|
+
async with get_session() as session:
|
|
495
|
+
query = select(AgentTable.id).order_by(AgentTable.id)
|
|
496
|
+
|
|
497
|
+
if last_id:
|
|
498
|
+
query = query.where(AgentTable.id > last_id)
|
|
499
|
+
|
|
500
|
+
query = query.limit(batch_size)
|
|
501
|
+
result = await session.execute(query)
|
|
502
|
+
agent_ids = [row[0] for row in result]
|
|
503
|
+
|
|
504
|
+
if not agent_ids:
|
|
505
|
+
break
|
|
506
|
+
|
|
507
|
+
yield agent_ids
|
|
508
|
+
last_id = agent_ids[-1]
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
async def update_agent_action_cost(batch_size: int = 100) -> None:
|
|
196
512
|
"""
|
|
197
513
|
Update action costs for all agents.
|
|
198
514
|
|
|
@@ -209,42 +525,20 @@ async def update_agent_action_cost():
|
|
|
209
525
|
"""
|
|
210
526
|
logger.info("Starting update of agent average action costs")
|
|
211
527
|
start_time = time.time()
|
|
212
|
-
batch_size = 100
|
|
213
|
-
last_id = None
|
|
214
528
|
total_updated = 0
|
|
215
529
|
|
|
216
|
-
|
|
217
|
-
# Get a batch of agent IDs ordered by ID
|
|
218
|
-
async with get_session() as session:
|
|
219
|
-
query = select(AgentTable.id).order_by(AgentTable.id)
|
|
220
|
-
|
|
221
|
-
# Apply pagination if we have a last_id from previous batch
|
|
222
|
-
if last_id:
|
|
223
|
-
query = query.where(AgentTable.id > last_id)
|
|
224
|
-
|
|
225
|
-
query = query.limit(batch_size)
|
|
226
|
-
result = await session.execute(query)
|
|
227
|
-
agent_ids = [row[0] for row in result]
|
|
228
|
-
|
|
229
|
-
# If no more agents, we're done
|
|
230
|
-
if not agent_ids:
|
|
231
|
-
break
|
|
232
|
-
|
|
233
|
-
# Update last_id for next batch
|
|
234
|
-
last_id = agent_ids[-1]
|
|
235
|
-
|
|
236
|
-
# Process this batch of agents
|
|
530
|
+
async for agent_ids in _iterate_agent_id_batches(batch_size):
|
|
237
531
|
logger.info(
|
|
238
|
-
|
|
532
|
+
"Processing batch of %s agents starting with ID %s",
|
|
533
|
+
len(agent_ids),
|
|
534
|
+
agent_ids[0],
|
|
239
535
|
)
|
|
240
536
|
batch_start_time = time.time()
|
|
241
537
|
|
|
242
538
|
for agent_id in agent_ids:
|
|
243
539
|
try:
|
|
244
|
-
# Calculate action costs for this agent
|
|
245
540
|
costs = await agent_action_cost(agent_id)
|
|
246
541
|
|
|
247
|
-
# Update the agent's quota record
|
|
248
542
|
async with get_session() as session:
|
|
249
543
|
update_stmt = (
|
|
250
544
|
update(AgentQuotaTable)
|
|
@@ -262,203 +556,186 @@ async def update_agent_action_cost():
|
|
|
262
556
|
await session.commit()
|
|
263
557
|
|
|
264
558
|
total_updated += 1
|
|
265
|
-
except Exception as e:
|
|
559
|
+
except Exception as e: # pragma: no cover - log path only
|
|
266
560
|
logger.error(
|
|
267
|
-
|
|
561
|
+
"Error updating action costs for agent %s: %s", agent_id, str(e)
|
|
268
562
|
)
|
|
269
563
|
|
|
270
564
|
batch_time = time.time() - batch_start_time
|
|
271
|
-
logger.info(
|
|
565
|
+
logger.info("Completed batch in %.3fs", batch_time)
|
|
272
566
|
|
|
273
567
|
total_time = time.time() - start_time
|
|
274
568
|
logger.info(
|
|
275
|
-
|
|
569
|
+
"Finished updating action costs for %s agents in %.3fs",
|
|
570
|
+
total_updated,
|
|
571
|
+
total_time,
|
|
276
572
|
)
|
|
277
573
|
|
|
278
574
|
|
|
279
|
-
async def
|
|
280
|
-
"""
|
|
281
|
-
List all autonomous tasks for an agent.
|
|
575
|
+
async def update_agents_account_snapshot(batch_size: int = 100) -> None:
|
|
576
|
+
"""Refresh the cached credit account snapshot for every agent."""
|
|
282
577
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Returns:
|
|
287
|
-
List[AgentAutonomous]: List of autonomous task configurations
|
|
578
|
+
logger.info("Starting update of agent account snapshots")
|
|
579
|
+
start_time = time.time()
|
|
580
|
+
total_updated = 0
|
|
288
581
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
raise IntentKitAPIError(
|
|
295
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
582
|
+
async for agent_ids in _iterate_agent_id_batches(batch_size):
|
|
583
|
+
logger.info(
|
|
584
|
+
"Processing snapshot batch of %s agents starting with ID %s",
|
|
585
|
+
len(agent_ids),
|
|
586
|
+
agent_ids[0],
|
|
296
587
|
)
|
|
588
|
+
batch_start_time = time.time()
|
|
297
589
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
590
|
+
for agent_id in agent_ids:
|
|
591
|
+
try:
|
|
592
|
+
async with get_session() as session:
|
|
593
|
+
account = await CreditAccount.get_or_create_in_session(
|
|
594
|
+
session, OwnerType.AGENT, agent_id
|
|
595
|
+
)
|
|
596
|
+
await session.execute(
|
|
597
|
+
update(AgentTable)
|
|
598
|
+
.where(AgentTable.id == agent_id)
|
|
599
|
+
.values(
|
|
600
|
+
account_snapshot=account.model_dump(mode="json"),
|
|
601
|
+
)
|
|
602
|
+
)
|
|
603
|
+
await session.commit()
|
|
303
604
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
605
|
+
total_updated += 1
|
|
606
|
+
except Exception as exc: # pragma: no cover - log path only
|
|
607
|
+
logger.error(
|
|
608
|
+
"Error updating account snapshot for agent %s: %s",
|
|
609
|
+
agent_id,
|
|
610
|
+
exc,
|
|
611
|
+
)
|
|
307
612
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
task: Autonomous task configuration (id will be generated if not provided)
|
|
613
|
+
batch_time = time.time() - batch_start_time
|
|
614
|
+
logger.info("Completed snapshot batch in %.3fs", batch_time)
|
|
311
615
|
|
|
312
|
-
|
|
313
|
-
|
|
616
|
+
total_time = time.time() - start_time
|
|
617
|
+
logger.info(
|
|
618
|
+
"Finished updating account snapshots for %s agents in %.3fs",
|
|
619
|
+
total_updated,
|
|
620
|
+
total_time,
|
|
621
|
+
)
|
|
314
622
|
|
|
315
|
-
Raises:
|
|
316
|
-
IntentKitAPIError: If agent is not found
|
|
317
|
-
"""
|
|
318
|
-
agent = await Agent.get(agent_id)
|
|
319
|
-
if not agent:
|
|
320
|
-
raise IntentKitAPIError(
|
|
321
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
322
|
-
)
|
|
323
623
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if not isinstance(current_tasks, list):
|
|
327
|
-
current_tasks = []
|
|
624
|
+
async def update_agents_assets(batch_size: int = 100) -> None:
|
|
625
|
+
"""Refresh cached asset information for all agents."""
|
|
328
626
|
|
|
329
|
-
|
|
330
|
-
current_tasks.append(task)
|
|
627
|
+
from intentkit.core.asset import agent_asset
|
|
331
628
|
|
|
332
|
-
|
|
333
|
-
|
|
629
|
+
logger.info("Starting update of agent assets")
|
|
630
|
+
start_time = time.time()
|
|
631
|
+
total_updated = 0
|
|
334
632
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.values(autonomous=serializable_tasks)
|
|
633
|
+
async for agent_ids in _iterate_agent_id_batches(batch_size):
|
|
634
|
+
logger.info(
|
|
635
|
+
"Processing asset batch of %s agents starting with ID %s",
|
|
636
|
+
len(agent_ids),
|
|
637
|
+
agent_ids[0],
|
|
341
638
|
)
|
|
342
|
-
|
|
343
|
-
await session.commit()
|
|
344
|
-
|
|
345
|
-
logger.info(f"Added autonomous task {task.id} to agent {agent_id}")
|
|
346
|
-
return task
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
async def delete_autonomous_task(agent_id: str, task_id: str) -> None:
|
|
350
|
-
"""
|
|
351
|
-
Delete an autonomous task from an agent.
|
|
639
|
+
batch_start_time = time.time()
|
|
352
640
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
641
|
+
for agent_id in agent_ids:
|
|
642
|
+
try:
|
|
643
|
+
assets = await agent_asset(agent_id)
|
|
644
|
+
except IntentKitAPIError as exc: # pragma: no cover - log path only
|
|
645
|
+
logger.warning(
|
|
646
|
+
"Skipping asset update for agent %s due to API error: %s",
|
|
647
|
+
agent_id,
|
|
648
|
+
exc,
|
|
649
|
+
)
|
|
650
|
+
continue
|
|
651
|
+
except Exception as exc: # pragma: no cover - log path only
|
|
652
|
+
logger.error("Error retrieving assets for agent %s: %s", agent_id, exc)
|
|
653
|
+
continue
|
|
356
654
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
655
|
+
try:
|
|
656
|
+
async with get_session() as session:
|
|
657
|
+
await session.execute(
|
|
658
|
+
update(AgentTable)
|
|
659
|
+
.where(AgentTable.id == agent_id)
|
|
660
|
+
.values(assets=assets.model_dump(mode="json"))
|
|
661
|
+
)
|
|
662
|
+
await session.commit()
|
|
365
663
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
# Find and remove the task
|
|
372
|
-
task_found = False
|
|
373
|
-
updated_tasks = []
|
|
374
|
-
for task_data in current_tasks:
|
|
375
|
-
if task_data.id == task_id:
|
|
376
|
-
task_found = True
|
|
377
|
-
continue
|
|
378
|
-
updated_tasks.append(task_data)
|
|
379
|
-
|
|
380
|
-
if not task_found:
|
|
381
|
-
raise IntentKitAPIError(
|
|
382
|
-
404, "TaskNotFound", f"Autonomous task with ID {task_id} not found."
|
|
383
|
-
)
|
|
664
|
+
total_updated += 1
|
|
665
|
+
except Exception as exc: # pragma: no cover - log path only
|
|
666
|
+
logger.error(
|
|
667
|
+
"Error updating asset cache for agent %s: %s", agent_id, exc
|
|
668
|
+
)
|
|
384
669
|
|
|
385
|
-
|
|
386
|
-
|
|
670
|
+
batch_time = time.time() - batch_start_time
|
|
671
|
+
logger.info("Completed asset batch in %.3fs", batch_time)
|
|
387
672
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
)
|
|
395
|
-
await session.execute(update_stmt)
|
|
396
|
-
await session.commit()
|
|
673
|
+
total_time = time.time() - start_time
|
|
674
|
+
logger.info(
|
|
675
|
+
"Finished updating assets for %s agents in %.3fs",
|
|
676
|
+
total_updated,
|
|
677
|
+
total_time,
|
|
678
|
+
)
|
|
397
679
|
|
|
398
|
-
logger.info(f"Deleted autonomous task {task_id} from agent {agent_id}")
|
|
399
680
|
|
|
681
|
+
async def update_agents_statistics(
|
|
682
|
+
*, end_time: datetime | None = None, batch_size: int = 100
|
|
683
|
+
) -> None:
|
|
684
|
+
"""Refresh cached statistics for every agent."""
|
|
400
685
|
|
|
401
|
-
|
|
402
|
-
agent_id: str, task_id: str, task_updates: dict
|
|
403
|
-
) -> AgentAutonomous:
|
|
404
|
-
"""
|
|
405
|
-
Update an autonomous task for an agent.
|
|
686
|
+
from intentkit.core.statistics import get_agent_statistics
|
|
406
687
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
688
|
+
if end_time is None:
|
|
689
|
+
end_time = datetime.now(UTC)
|
|
690
|
+
elif end_time.tzinfo is None:
|
|
691
|
+
end_time = end_time.replace(tzinfo=UTC)
|
|
692
|
+
else:
|
|
693
|
+
end_time = end_time.astimezone(UTC)
|
|
411
694
|
|
|
412
|
-
|
|
413
|
-
|
|
695
|
+
logger.info("Starting update of agent statistics using end_time %s", end_time)
|
|
696
|
+
start_time = time.time()
|
|
697
|
+
total_updated = 0
|
|
414
698
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
raise IntentKitAPIError(
|
|
421
|
-
400, "AgentNotFound", f"Agent with ID {agent_id} does not exist."
|
|
699
|
+
async for agent_ids in _iterate_agent_id_batches(batch_size):
|
|
700
|
+
logger.info(
|
|
701
|
+
"Processing statistics batch of %s agents starting with ID %s",
|
|
702
|
+
len(agent_ids),
|
|
703
|
+
agent_ids[0],
|
|
422
704
|
)
|
|
705
|
+
batch_start_time = time.time()
|
|
423
706
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
for task_data in current_tasks:
|
|
433
|
-
if task_data.id == task_id:
|
|
434
|
-
task_found = True
|
|
435
|
-
# Create a dictionary with current task data
|
|
436
|
-
task_dict = task_data.model_dump()
|
|
437
|
-
# Update with provided fields
|
|
438
|
-
task_dict.update(task_updates)
|
|
439
|
-
# Create new AgentAutonomous instance
|
|
440
|
-
updated_task = AgentAutonomous.model_validate(task_dict)
|
|
441
|
-
updated_tasks.append(updated_task)
|
|
442
|
-
else:
|
|
443
|
-
updated_tasks.append(task_data)
|
|
707
|
+
for agent_id in agent_ids:
|
|
708
|
+
try:
|
|
709
|
+
statistics = await get_agent_statistics(agent_id, end_time=end_time)
|
|
710
|
+
except Exception as exc: # pragma: no cover - log path only
|
|
711
|
+
logger.error(
|
|
712
|
+
"Error computing statistics for agent %s: %s", agent_id, exc
|
|
713
|
+
)
|
|
714
|
+
continue
|
|
444
715
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
716
|
+
try:
|
|
717
|
+
async with get_session() as session:
|
|
718
|
+
await session.execute(
|
|
719
|
+
update(AgentTable)
|
|
720
|
+
.where(AgentTable.id == agent_id)
|
|
721
|
+
.values(statistics=statistics.model_dump(mode="json"))
|
|
722
|
+
)
|
|
723
|
+
await session.commit()
|
|
449
724
|
|
|
450
|
-
|
|
451
|
-
|
|
725
|
+
total_updated += 1
|
|
726
|
+
except Exception as exc: # pragma: no cover - log path only
|
|
727
|
+
logger.error(
|
|
728
|
+
"Error updating statistics cache for agent %s: %s",
|
|
729
|
+
agent_id,
|
|
730
|
+
exc,
|
|
731
|
+
)
|
|
452
732
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
update_stmt = (
|
|
456
|
-
update(AgentTable)
|
|
457
|
-
.where(AgentTable.id == agent_id)
|
|
458
|
-
.values(autonomous=serializable_tasks)
|
|
459
|
-
)
|
|
460
|
-
await session.execute(update_stmt)
|
|
461
|
-
await session.commit()
|
|
733
|
+
batch_time = time.time() - batch_start_time
|
|
734
|
+
logger.info("Completed statistics batch in %.3fs", batch_time)
|
|
462
735
|
|
|
463
|
-
|
|
464
|
-
|
|
736
|
+
total_time = time.time() - start_time
|
|
737
|
+
logger.info(
|
|
738
|
+
"Finished updating statistics for %s agents in %.3fs",
|
|
739
|
+
total_updated,
|
|
740
|
+
total_time,
|
|
741
|
+
)
|