intentkit 0.7.5.dev3__py3-none-any.whl → 0.8.34.dev7__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.
- intentkit/MANIFEST.in +14 -0
- intentkit/README.md +88 -0
- intentkit/__init__.py +6 -4
- intentkit/abstracts/agent.py +4 -5
- intentkit/abstracts/engine.py +5 -5
- intentkit/abstracts/graph.py +15 -8
- intentkit/abstracts/skill.py +6 -144
- intentkit/abstracts/twitter.py +4 -5
- intentkit/clients/__init__.py +9 -2
- intentkit/clients/cdp.py +129 -153
- intentkit/{utils → clients}/s3.py +109 -34
- intentkit/clients/twitter.py +83 -62
- intentkit/clients/web3.py +4 -7
- intentkit/config/config.py +123 -90
- intentkit/core/account_checking.py +802 -0
- intentkit/core/agent.py +313 -498
- intentkit/core/asset.py +267 -0
- intentkit/core/chat.py +5 -3
- intentkit/core/client.py +1 -1
- intentkit/core/credit.py +49 -41
- intentkit/core/draft.py +201 -0
- intentkit/core/draft_chat.py +118 -0
- intentkit/core/engine.py +378 -287
- intentkit/core/manager/__init__.py +25 -0
- intentkit/core/manager/engine.py +220 -0
- intentkit/core/manager/service.py +172 -0
- intentkit/core/manager/skills.py +178 -0
- intentkit/core/middleware.py +231 -0
- intentkit/core/prompt.py +74 -114
- intentkit/core/scheduler.py +143 -0
- intentkit/core/statistics.py +168 -0
- intentkit/models/agent.py +931 -518
- intentkit/models/agent_data.py +165 -106
- intentkit/models/agent_schema.json +38 -251
- intentkit/models/app_setting.py +15 -13
- intentkit/models/chat.py +86 -140
- intentkit/models/credit.py +182 -162
- intentkit/models/db.py +42 -23
- intentkit/models/db_mig.py +120 -3
- intentkit/models/draft.py +222 -0
- intentkit/models/llm.csv +31 -0
- intentkit/models/llm.py +262 -370
- intentkit/models/redis.py +6 -4
- intentkit/models/skill.py +222 -101
- intentkit/models/skills.csv +173 -0
- intentkit/models/team.py +189 -0
- intentkit/models/user.py +103 -31
- 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 +241 -41
- 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 +6 -6
- intentkit/skills/casino/__init__.py +4 -15
- intentkit/skills/casino/base.py +1 -7
- intentkit/skills/casino/deck_draw.py +5 -8
- intentkit/skills/casino/deck_shuffle.py +6 -6
- intentkit/skills/casino/dice_roll.py +2 -4
- intentkit/skills/casino/schema.json +0 -1
- 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 +10 -24
- 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 +8 -19
- 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/__init__.py +97 -102
- intentkit/skills/dexscreener/base.py +125 -130
- intentkit/skills/dexscreener/get_pair_info.py +4 -5
- intentkit/skills/dexscreener/get_token_pairs.py +4 -5
- intentkit/skills/dexscreener/get_tokens_info.py +7 -8
- intentkit/skills/dexscreener/model/search_token_response.py +80 -82
- intentkit/skills/dexscreener/schema.json +91 -93
- intentkit/skills/dexscreener/search_token.py +182 -184
- intentkit/skills/dexscreener/utils.py +15 -14
- 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 +54 -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/__init__.py +5 -18
- intentkit/skills/firecrawl/base.py +4 -9
- 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 +2 -6
- intentkit/skills/firecrawl/scrape.py +17 -22
- 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 +13 -15
- intentkit/skills/heurist/image_generation_arthemy_comics.py +13 -15
- intentkit/skills/heurist/image_generation_arthemy_real.py +13 -15
- intentkit/skills/heurist/image_generation_braindance.py +13 -15
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +13 -15
- intentkit/skills/heurist/image_generation_flux_1_dev.py +13 -15
- intentkit/skills/heurist/image_generation_sdxl.py +13 -15
- 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 +3 -9
- intentkit/skills/lifi/schema.json +17 -8
- intentkit/skills/lifi/token_execute.py +150 -60
- 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 +30 -0
- intentkit/skills/openai/__init__.py +17 -18
- intentkit/skills/openai/base.py +10 -14
- intentkit/skills/openai/dalle_image_generation.py +4 -9
- intentkit/skills/openai/gpt_avatar_generator.py +102 -0
- intentkit/skills/openai/gpt_image_generation.py +5 -9
- intentkit/skills/openai/gpt_image_mini_generator.py +92 -0
- intentkit/skills/openai/gpt_image_to_image.py +5 -9
- 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 +36 -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 +1 -7
- intentkit/skills/supabase/delete_data.py +4 -4
- intentkit/skills/supabase/fetch_data.py +12 -12
- intentkit/skills/supabase/insert_data.py +4 -4
- intentkit/skills/supabase/invoke_function.py +6 -6
- intentkit/skills/supabase/schema.json +2 -3
- intentkit/skills/supabase/update_data.py +6 -6
- intentkit/skills/supabase/upsert_data.py +4 -4
- 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 +22 -34
- intentkit/skills/twitter/follow_user.py +2 -6
- intentkit/skills/twitter/get_mentions.py +5 -12
- intentkit/skills/twitter/get_timeline.py +4 -12
- intentkit/skills/twitter/get_user_by_username.py +2 -6
- intentkit/skills/twitter/get_user_tweets.py +5 -13
- intentkit/skills/twitter/like_tweet.py +2 -6
- intentkit/skills/twitter/post_tweet.py +6 -9
- intentkit/skills/twitter/reply_tweet.py +6 -9
- intentkit/skills/twitter/retweet.py +2 -6
- intentkit/skills/twitter/schema.json +1 -0
- intentkit/skills/twitter/search_tweets.py +4 -12
- 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 +11 -10
- 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 +58 -0
- intentkit/skills/x402/base.py +99 -0
- intentkit/skills/x402/http_request.py +117 -0
- intentkit/skills/x402/schema.json +40 -0
- intentkit/skills/x402/x402.webp +0 -0
- intentkit/skills/xmtp/__init__.py +4 -15
- intentkit/skills/xmtp/base.py +5 -5
- intentkit/skills/xmtp/price.py +7 -6
- intentkit/skills/xmtp/schema.json +69 -71
- intentkit/skills/xmtp/swap.py +6 -8
- intentkit/skills/xmtp/transfer.py +4 -6
- intentkit/utils/__init__.py +4 -0
- intentkit/utils/chain.py +198 -96
- intentkit/utils/ens.py +135 -0
- intentkit/utils/error.py +5 -2
- intentkit/utils/logging.py +9 -11
- intentkit/utils/schema.py +100 -0
- intentkit/utils/slack_alert.py +8 -8
- intentkit/utils/tx.py +16 -8
- intentkit/uv.lock +3377 -0
- {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/METADATA +13 -15
- intentkit-0.8.34.dev7.dist-info/RECORD +478 -0
- intentkit-0.8.34.dev7.dist-info/licenses/LICENSE +21 -0
- intentkit/core/node.py +0 -215
- intentkit/models/conversation.py +0 -286
- 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.7.5.dev3.dist-info/RECORD +0 -424
- {intentkit-0.7.5.dev3.dist-info/licenses → intentkit}/LICENSE +0 -0
- {intentkit-0.7.5.dev3.dist-info → intentkit-0.8.34.dev7.dist-info}/WHEEL +0 -0
intentkit/core/engine.py
CHANGED
|
@@ -17,32 +17,33 @@ import textwrap
|
|
|
17
17
|
import time
|
|
18
18
|
import traceback
|
|
19
19
|
from datetime import datetime
|
|
20
|
-
from typing import Optional
|
|
21
20
|
|
|
22
21
|
import sqlalchemy
|
|
23
22
|
from epyxid import XID
|
|
24
|
-
from
|
|
23
|
+
from langchain.agents import create_agent as create_langchain_agent
|
|
25
24
|
from langchain_core.messages import (
|
|
26
25
|
BaseMessage,
|
|
27
26
|
HumanMessage,
|
|
28
27
|
)
|
|
29
28
|
from langchain_core.tools import BaseTool
|
|
29
|
+
from langgraph.checkpoint.memory import InMemorySaver
|
|
30
30
|
from langgraph.errors import GraphRecursionError
|
|
31
31
|
from langgraph.graph.state import CompiledStateGraph
|
|
32
|
-
from langgraph.prebuilt import create_react_agent
|
|
33
32
|
from sqlalchemy import func, update
|
|
34
33
|
from sqlalchemy.exc import SQLAlchemyError
|
|
35
34
|
|
|
36
35
|
from intentkit.abstracts.graph import AgentContext, AgentError, AgentState
|
|
37
36
|
from intentkit.config.config import config
|
|
38
|
-
from intentkit.core.agent import agent_store
|
|
39
37
|
from intentkit.core.chat import clear_thread_memory
|
|
40
38
|
from intentkit.core.credit import expense_message, expense_skill
|
|
41
|
-
from intentkit.core.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
from intentkit.core.middleware import (
|
|
40
|
+
CreditCheckMiddleware,
|
|
41
|
+
DynamicPromptMiddleware,
|
|
42
|
+
SummarizationMiddleware,
|
|
43
|
+
ToolBindingMiddleware,
|
|
44
|
+
TrimMessagesMiddleware,
|
|
45
45
|
)
|
|
46
|
+
from intentkit.core.prompt import explain_prompt
|
|
46
47
|
from intentkit.models.agent import Agent, AgentTable
|
|
47
48
|
from intentkit.models.agent_data import AgentData, AgentQuota
|
|
48
49
|
from intentkit.models.app_setting import AppSetting, SystemMessageType
|
|
@@ -53,26 +54,51 @@ from intentkit.models.chat import (
|
|
|
53
54
|
ChatMessageSkillCall,
|
|
54
55
|
)
|
|
55
56
|
from intentkit.models.credit import CreditAccount, OwnerType
|
|
56
|
-
from intentkit.models.db import
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
from intentkit.models.db import (
|
|
58
|
+
get_checkpointer,
|
|
59
|
+
get_session,
|
|
60
|
+
)
|
|
61
|
+
from intentkit.models.llm import LLMModelInfo, create_llm_model
|
|
62
|
+
from intentkit.models.skill import AgentSkillData, ChatSkillData, Skill
|
|
59
63
|
from intentkit.models.user import User
|
|
60
64
|
from intentkit.utils.error import IntentKitAPIError
|
|
61
65
|
|
|
62
66
|
logger = logging.getLogger(__name__)
|
|
63
67
|
|
|
64
|
-
|
|
65
68
|
# Global variable to cache all agent executors
|
|
66
69
|
_agents: dict[str, CompiledStateGraph] = {}
|
|
67
|
-
_private_agents: dict[str, CompiledStateGraph] = {}
|
|
68
70
|
|
|
69
71
|
# Global dictionaries to cache agent update times
|
|
70
72
|
_agents_updated: dict[str, datetime] = {}
|
|
71
|
-
_private_agents_updated: dict[str, datetime] = {}
|
|
72
73
|
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
def _extract_text_content(content: object) -> str:
|
|
76
|
+
if isinstance(content, list):
|
|
77
|
+
texts: list[str] = []
|
|
78
|
+
for item in content:
|
|
79
|
+
if isinstance(item, dict):
|
|
80
|
+
t = item.get("text")
|
|
81
|
+
ty = item.get("type")
|
|
82
|
+
if t is not None and (ty == "text" or ty is None):
|
|
83
|
+
texts.append(t)
|
|
84
|
+
elif isinstance(item, str):
|
|
85
|
+
texts.append(item)
|
|
86
|
+
return "".join(texts)
|
|
87
|
+
if isinstance(content, dict):
|
|
88
|
+
if content.get("type") == "text" and "text" in content:
|
|
89
|
+
return content["text"]
|
|
90
|
+
if "text" in content:
|
|
91
|
+
return content["text"]
|
|
92
|
+
return ""
|
|
93
|
+
if isinstance(content, str):
|
|
94
|
+
return content
|
|
95
|
+
return ""
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
async def build_agent(
|
|
99
|
+
agent: Agent, agent_data: AgentData, custom_skills: list[BaseTool] = []
|
|
100
|
+
) -> CompiledStateGraph:
|
|
101
|
+
"""Build an AI agent with specified configuration and tools.
|
|
76
102
|
|
|
77
103
|
This function:
|
|
78
104
|
1. Initializes LLM with specified model
|
|
@@ -82,13 +108,13 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
|
|
|
82
108
|
|
|
83
109
|
Args:
|
|
84
110
|
agent (Agent): Agent configuration object
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
agent_data (AgentData): Agent data object
|
|
112
|
+
custom_skills (list[BaseTool], optional): Designed for advanced user who directly
|
|
113
|
+
call this function to inject custom skills into the agent tool node.
|
|
87
114
|
|
|
88
115
|
Returns:
|
|
89
116
|
CompiledStateGraph: Initialized LangChain agent
|
|
90
117
|
"""
|
|
91
|
-
agent_data = await AgentData.get(agent.id)
|
|
92
118
|
|
|
93
119
|
# Create the LLM model instance
|
|
94
120
|
llm_model = await create_llm_model(
|
|
@@ -98,17 +124,15 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
|
|
|
98
124
|
presence_penalty=agent.presence_penalty,
|
|
99
125
|
)
|
|
100
126
|
|
|
101
|
-
# Get the LLM instance
|
|
102
|
-
llm = await llm_model.create_instance(config)
|
|
103
|
-
|
|
104
|
-
# Get the token limit from the model info
|
|
105
|
-
input_token_limit = min(config.input_token_limit, llm_model.info.context_length)
|
|
106
|
-
|
|
107
127
|
# ==== Store buffered conversation history in memory.
|
|
108
|
-
|
|
128
|
+
try:
|
|
129
|
+
checkpointer = get_checkpointer()
|
|
130
|
+
except RuntimeError:
|
|
131
|
+
checkpointer = InMemorySaver()
|
|
109
132
|
|
|
110
133
|
# ==== Load skills
|
|
111
134
|
tools: list[BaseTool | dict] = []
|
|
135
|
+
private_tools: list[BaseTool | dict] = []
|
|
112
136
|
|
|
113
137
|
if agent.skills:
|
|
114
138
|
for k, v in agent.skills.items():
|
|
@@ -117,55 +141,65 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
|
|
|
117
141
|
try:
|
|
118
142
|
skill_module = importlib.import_module(f"intentkit.skills.{k}")
|
|
119
143
|
if hasattr(skill_module, "get_skills"):
|
|
144
|
+
# all
|
|
120
145
|
skill_tools = await skill_module.get_skills(
|
|
121
|
-
v,
|
|
146
|
+
v, False, agent_id=agent.id, agent=agent
|
|
122
147
|
)
|
|
123
148
|
if skill_tools and len(skill_tools) > 0:
|
|
124
149
|
tools.extend(skill_tools)
|
|
150
|
+
# private
|
|
151
|
+
skill_private_tools = await skill_module.get_skills(
|
|
152
|
+
v, True, agent_id=agent.id, agent=agent
|
|
153
|
+
)
|
|
154
|
+
if skill_private_tools and len(skill_private_tools) > 0:
|
|
155
|
+
private_tools.extend(skill_private_tools)
|
|
125
156
|
else:
|
|
126
157
|
logger.error(f"Skill {k} does not have get_skills function")
|
|
127
158
|
except ImportError as e:
|
|
128
159
|
logger.error(f"Could not import skill module: {k} ({e})")
|
|
129
160
|
|
|
161
|
+
# add custom skills to private tools
|
|
162
|
+
if custom_skills and len(custom_skills) > 0:
|
|
163
|
+
private_tools.extend(custom_skills)
|
|
164
|
+
|
|
130
165
|
# filter the duplicate tools
|
|
131
166
|
tools = list({tool.name: tool for tool in tools}.values())
|
|
167
|
+
private_tools = list({tool.name: tool for tool in private_tools}.values())
|
|
132
168
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
and not agent.model.startswith(
|
|
138
|
-
"gpt-5"
|
|
139
|
-
) # tmp disable gpt-5 search since package bugs
|
|
140
|
-
):
|
|
141
|
-
tools.append({"type": "web_search_preview"})
|
|
169
|
+
for tool in private_tools:
|
|
170
|
+
logger.info(
|
|
171
|
+
f"[{agent.id}] loaded tool: {tool.name if isinstance(tool, BaseTool) else tool}"
|
|
172
|
+
)
|
|
142
173
|
|
|
143
|
-
|
|
144
|
-
formatted_prompt = create_formatted_prompt_function(agent, agent_data)
|
|
174
|
+
base_model = await llm_model.create_instance()
|
|
145
175
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
176
|
+
middleware = [
|
|
177
|
+
ToolBindingMiddleware(llm_model, tools, private_tools),
|
|
178
|
+
DynamicPromptMiddleware(agent, agent_data),
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
if agent.short_term_memory_strategy == "trim":
|
|
182
|
+
middleware.append(TrimMessagesMiddleware(max_summary_tokens=2048))
|
|
183
|
+
elif agent.short_term_memory_strategy == "summarize":
|
|
184
|
+
summarize_llm = await create_llm_model(model_name="gpt-5-mini")
|
|
185
|
+
summarize_model = await summarize_llm.create_instance()
|
|
186
|
+
middleware.append(
|
|
187
|
+
SummarizationMiddleware(
|
|
188
|
+
model=summarize_model,
|
|
189
|
+
max_tokens_before_summary=llm_model.info.context_length // 2,
|
|
190
|
+
)
|
|
149
191
|
)
|
|
150
192
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
model=llm,
|
|
154
|
-
short_term_memory_strategy=agent.short_term_memory_strategy,
|
|
155
|
-
max_tokens=input_token_limit // 2,
|
|
156
|
-
max_summary_tokens=2048,
|
|
157
|
-
)
|
|
193
|
+
if config.payment_enabled:
|
|
194
|
+
middleware.append(CreditCheckMiddleware())
|
|
158
195
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
prompt=formatted_prompt,
|
|
164
|
-
pre_model_hook=pre_model_hook,
|
|
165
|
-
post_model_hook=post_model_node if config.payment_enabled else None,
|
|
196
|
+
executor = create_langchain_agent(
|
|
197
|
+
model=base_model,
|
|
198
|
+
tools=private_tools,
|
|
199
|
+
middleware=middleware,
|
|
166
200
|
state_schema=AgentState,
|
|
167
201
|
context_schema=AgentContext,
|
|
168
|
-
checkpointer=
|
|
202
|
+
checkpointer=checkpointer,
|
|
169
203
|
debug=config.debug_checkpoint,
|
|
170
204
|
name=agent.id,
|
|
171
205
|
)
|
|
@@ -173,7 +207,23 @@ async def create_agent(agent: Agent, is_private: bool = False) -> CompiledStateG
|
|
|
173
207
|
return executor
|
|
174
208
|
|
|
175
209
|
|
|
176
|
-
async def
|
|
210
|
+
async def create_agent(agent: Agent) -> CompiledStateGraph:
|
|
211
|
+
"""Create an AI agent with specified configuration and tools.
|
|
212
|
+
|
|
213
|
+
This function maintains backward compatibility by calling build_agent internally.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
agent (Agent): Agent configuration object
|
|
217
|
+
is_private (bool, optional): Flag indicating whether the agent is private. Defaults to False.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
CompiledStateGraph: Initialized LangChain agent
|
|
221
|
+
"""
|
|
222
|
+
agent_data = await AgentData.get(agent.id)
|
|
223
|
+
return await build_agent(agent, agent_data)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
async def initialize_agent(aid):
|
|
177
227
|
"""Initialize an AI agent with specified configuration and tools.
|
|
178
228
|
|
|
179
229
|
This function:
|
|
@@ -192,50 +242,41 @@ async def initialize_agent(aid, is_private=False):
|
|
|
192
242
|
HTTPException: If agent not found (404) or database error (500)
|
|
193
243
|
"""
|
|
194
244
|
# get the agent from the database
|
|
195
|
-
agent:
|
|
245
|
+
agent: Agent | None = await Agent.get(aid)
|
|
196
246
|
if not agent:
|
|
197
|
-
raise
|
|
247
|
+
raise IntentKitAPIError(
|
|
248
|
+
status_code=404, key="AgentNotFound", message="Agent not found"
|
|
249
|
+
)
|
|
198
250
|
|
|
199
251
|
# Create the agent using the new create_agent function
|
|
200
|
-
executor = await create_agent(agent
|
|
252
|
+
executor = await create_agent(agent)
|
|
201
253
|
|
|
202
254
|
# Cache the agent executor
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
_private_agents_updated[aid] = agent.updated_at
|
|
206
|
-
else:
|
|
207
|
-
_agents[aid] = executor
|
|
208
|
-
_agents_updated[aid] = agent.updated_at
|
|
255
|
+
_agents[aid] = executor
|
|
256
|
+
_agents_updated[aid] = agent.deployed_at if agent.deployed_at else agent.updated_at
|
|
209
257
|
|
|
210
258
|
|
|
211
|
-
async def agent_executor(
|
|
212
|
-
agent_id: str, is_private: bool
|
|
213
|
-
) -> (CompiledStateGraph, float):
|
|
259
|
+
async def agent_executor(agent_id: str) -> tuple[CompiledStateGraph, float]:
|
|
214
260
|
start = time.perf_counter()
|
|
215
261
|
agent = await Agent.get(agent_id)
|
|
216
262
|
if not agent:
|
|
217
|
-
raise
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
263
|
+
raise IntentKitAPIError(
|
|
264
|
+
status_code=404, key="AgentNotFound", message="Agent not found"
|
|
265
|
+
)
|
|
266
|
+
updated_at = agent.deployed_at if agent.deployed_at else agent.updated_at
|
|
221
267
|
# Check if agent needs reinitialization due to updates
|
|
222
268
|
needs_reinit = False
|
|
223
|
-
if agent_id in
|
|
224
|
-
if
|
|
225
|
-
agent_id not in agents_updated
|
|
226
|
-
or agent.updated_at != agents_updated[agent_id]
|
|
227
|
-
):
|
|
269
|
+
if agent_id in _agents:
|
|
270
|
+
if agent_id not in _agents_updated or updated_at != _agents_updated[agent_id]:
|
|
228
271
|
needs_reinit = True
|
|
229
|
-
logger.info(
|
|
230
|
-
f"Reinitializing agent {agent_id} due to updates, private mode: {is_private}"
|
|
231
|
-
)
|
|
272
|
+
logger.info(f"Reinitializing agent {agent_id} due to updates")
|
|
232
273
|
|
|
233
274
|
# cold start or needs reinitialization
|
|
234
275
|
cold_start_cost = 0.0
|
|
235
|
-
if (agent_id not in
|
|
236
|
-
await initialize_agent(agent_id
|
|
276
|
+
if (agent_id not in _agents) or needs_reinit:
|
|
277
|
+
await initialize_agent(agent_id)
|
|
237
278
|
cold_start_cost = time.perf_counter() - start
|
|
238
|
-
return
|
|
279
|
+
return _agents[agent_id], cold_start_cost
|
|
239
280
|
|
|
240
281
|
|
|
241
282
|
async def stream_agent(message: ChatMessageCreate):
|
|
@@ -254,24 +295,60 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
254
295
|
Yields:
|
|
255
296
|
ChatMessage: Individual response messages including timing information
|
|
256
297
|
"""
|
|
298
|
+
agent = await Agent.get(message.agent_id)
|
|
299
|
+
executor, cold_start_cost = await agent_executor(message.agent_id)
|
|
300
|
+
message.cold_start_cost = cold_start_cost
|
|
301
|
+
async for chat_message in stream_agent_raw(message, agent, executor):
|
|
302
|
+
yield chat_message
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
async def stream_agent_raw(
|
|
306
|
+
message: ChatMessageCreate, agent: Agent, executor: CompiledStateGraph
|
|
307
|
+
):
|
|
257
308
|
start = time.perf_counter()
|
|
258
309
|
# make sure reply_to is set
|
|
259
310
|
message.reply_to = message.id
|
|
260
311
|
|
|
261
312
|
# save input message first
|
|
262
|
-
|
|
313
|
+
user_message = await message.save()
|
|
263
314
|
|
|
264
|
-
#
|
|
265
|
-
|
|
315
|
+
# temporary debug logging for telegram messages
|
|
316
|
+
if user_message.author_type == AuthorType.TELEGRAM:
|
|
317
|
+
logger.info(
|
|
318
|
+
f"[TELEGRAM DEBUG] Agent: {user_message.agent_id} | Chat: {user_message.chat_id} | Message: {user_message.message}"
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if re.search(
|
|
322
|
+
r"(@clear|/clear)(?!\w)",
|
|
323
|
+
user_message.message.strip(),
|
|
324
|
+
re.IGNORECASE,
|
|
325
|
+
):
|
|
326
|
+
await clear_thread_memory(user_message.agent_id, user_message.chat_id)
|
|
327
|
+
|
|
328
|
+
confirmation_message = ChatMessageCreate(
|
|
329
|
+
id=str(XID()),
|
|
330
|
+
agent_id=user_message.agent_id,
|
|
331
|
+
chat_id=user_message.chat_id,
|
|
332
|
+
user_id=user_message.user_id,
|
|
333
|
+
author_id=user_message.agent_id,
|
|
334
|
+
author_type=AuthorType.AGENT,
|
|
335
|
+
model=agent.model,
|
|
336
|
+
thread_type=user_message.author_type,
|
|
337
|
+
reply_to=user_message.id,
|
|
338
|
+
message="Memory in context has been cleared.",
|
|
339
|
+
time_cost=time.perf_counter() - start,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
yield await confirmation_message.save()
|
|
343
|
+
return
|
|
266
344
|
|
|
267
|
-
# model
|
|
268
345
|
model = await LLMModelInfo.get(agent.model)
|
|
269
346
|
|
|
270
347
|
payment_enabled = config.payment_enabled
|
|
271
348
|
|
|
272
349
|
# check user balance
|
|
273
350
|
if payment_enabled:
|
|
274
|
-
if not
|
|
351
|
+
if not user_message.user_id or not agent.owner:
|
|
275
352
|
raise IntentKitAPIError(
|
|
276
353
|
500,
|
|
277
354
|
"PaymentError",
|
|
@@ -282,23 +359,25 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
282
359
|
if owner and agent.fee_percentage > 100 + owner.nft_count * 10:
|
|
283
360
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
284
361
|
SystemMessageType.SERVICE_FEE_ERROR,
|
|
285
|
-
agent_id=
|
|
286
|
-
chat_id=
|
|
287
|
-
user_id=
|
|
288
|
-
author_id=
|
|
289
|
-
thread_type=
|
|
290
|
-
reply_to=
|
|
362
|
+
agent_id=user_message.agent_id,
|
|
363
|
+
chat_id=user_message.chat_id,
|
|
364
|
+
user_id=user_message.user_id,
|
|
365
|
+
author_id=user_message.agent_id,
|
|
366
|
+
thread_type=user_message.author_type,
|
|
367
|
+
reply_to=user_message.id,
|
|
291
368
|
time_cost=time.perf_counter() - start,
|
|
292
369
|
)
|
|
293
370
|
error_message = await error_message_create.save()
|
|
294
371
|
yield error_message
|
|
295
372
|
return
|
|
296
373
|
# payer
|
|
297
|
-
payer =
|
|
298
|
-
if
|
|
374
|
+
payer = user_message.user_id
|
|
375
|
+
if user_message.author_type in [
|
|
299
376
|
AuthorType.TELEGRAM,
|
|
377
|
+
AuthorType.DISCORD,
|
|
300
378
|
AuthorType.TWITTER,
|
|
301
379
|
AuthorType.API,
|
|
380
|
+
AuthorType.X402,
|
|
302
381
|
]:
|
|
303
382
|
payer = agent.owner
|
|
304
383
|
# user account
|
|
@@ -318,12 +397,12 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
318
397
|
if quota and quota.free_income_daily > 24000:
|
|
319
398
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
320
399
|
SystemMessageType.DAILY_USAGE_LIMIT_EXCEEDED,
|
|
321
|
-
agent_id=
|
|
322
|
-
chat_id=
|
|
323
|
-
user_id=
|
|
324
|
-
author_id=
|
|
325
|
-
thread_type=
|
|
326
|
-
reply_to=
|
|
400
|
+
agent_id=user_message.agent_id,
|
|
401
|
+
chat_id=user_message.chat_id,
|
|
402
|
+
user_id=user_message.user_id,
|
|
403
|
+
author_id=user_message.agent_id,
|
|
404
|
+
thread_type=user_message.author_type,
|
|
405
|
+
reply_to=user_message.id,
|
|
327
406
|
time_cost=time.perf_counter() - start,
|
|
328
407
|
)
|
|
329
408
|
error_message = await error_message_create.save()
|
|
@@ -336,12 +415,12 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
336
415
|
if not user_account.has_sufficient_credits(avg_count):
|
|
337
416
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
338
417
|
SystemMessageType.INSUFFICIENT_BALANCE,
|
|
339
|
-
agent_id=
|
|
340
|
-
chat_id=
|
|
341
|
-
user_id=
|
|
342
|
-
author_id=
|
|
343
|
-
thread_type=
|
|
344
|
-
reply_to=
|
|
418
|
+
agent_id=user_message.agent_id,
|
|
419
|
+
chat_id=user_message.chat_id,
|
|
420
|
+
user_id=user_message.user_id,
|
|
421
|
+
author_id=user_message.agent_id,
|
|
422
|
+
thread_type=user_message.author_type,
|
|
423
|
+
reply_to=user_message.id,
|
|
345
424
|
time_cost=time.perf_counter() - start,
|
|
346
425
|
)
|
|
347
426
|
error_message = await error_message_create.save()
|
|
@@ -349,56 +428,41 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
349
428
|
return
|
|
350
429
|
|
|
351
430
|
is_private = False
|
|
352
|
-
if
|
|
431
|
+
if user_message.user_id == agent.owner:
|
|
353
432
|
is_private = True
|
|
354
433
|
|
|
355
|
-
|
|
356
|
-
last = start + cold_start_cost
|
|
434
|
+
last = start
|
|
357
435
|
|
|
358
436
|
# Extract images from attachments
|
|
359
437
|
image_urls = []
|
|
360
|
-
if
|
|
438
|
+
if user_message.attachments:
|
|
361
439
|
image_urls = [
|
|
362
440
|
att["url"]
|
|
363
|
-
for att in
|
|
441
|
+
for att in user_message.attachments
|
|
364
442
|
if "type" in att and att["type"] == "image" and "url" in att
|
|
365
443
|
]
|
|
366
444
|
|
|
367
445
|
# Process input message to handle @skill patterns
|
|
368
|
-
|
|
369
|
-
input_message = await explain_prompt(input.message)
|
|
370
|
-
else:
|
|
371
|
-
input_message = input.message
|
|
446
|
+
input_message = await explain_prompt(user_message.message)
|
|
372
447
|
|
|
373
448
|
# super mode
|
|
374
449
|
recursion_limit = 30
|
|
375
|
-
if
|
|
450
|
+
if (
|
|
451
|
+
re.search(r"@super\b", input_message)
|
|
452
|
+
or user_message.super_mode
|
|
453
|
+
or agent.has_super()
|
|
454
|
+
):
|
|
376
455
|
recursion_limit = 300
|
|
377
|
-
|
|
378
|
-
input_message = re.sub(r"\b@super\b", "", input_message).strip()
|
|
456
|
+
input_message = re.sub(r"@super\b", "", input_message).strip()
|
|
379
457
|
|
|
380
458
|
# llm native search
|
|
381
|
-
if
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if model.supports_search:
|
|
385
|
-
input_message = re.sub(
|
|
386
|
-
r"\b@search\b",
|
|
387
|
-
"(You have native search tool, you can use it to get more recent information)",
|
|
388
|
-
input_message,
|
|
389
|
-
).strip()
|
|
390
|
-
input_message = re.sub(
|
|
391
|
-
r"\b@web\b",
|
|
392
|
-
"(You have native search tool, you can use it to get more recent information)",
|
|
393
|
-
input_message,
|
|
394
|
-
).strip()
|
|
395
|
-
else:
|
|
396
|
-
input_message = re.sub(r"\b@search\b", "", input_message).strip()
|
|
397
|
-
input_message = re.sub(r"\b@web\b", "", input_message).strip()
|
|
459
|
+
search = user_message.search_mode if user_message.search_mode is not None else False
|
|
460
|
+
if re.search(r"@search\b", input_message) or re.search(r"@web\b", input_message):
|
|
461
|
+
search = True
|
|
398
462
|
|
|
399
463
|
# content to llm
|
|
400
|
-
|
|
401
|
-
|
|
464
|
+
messages = [
|
|
465
|
+
HumanMessage(content=input_message),
|
|
402
466
|
]
|
|
403
467
|
# if the model doesn't natively support image parsing, add the image URLs to the message
|
|
404
468
|
if image_urls:
|
|
@@ -406,25 +470,24 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
406
470
|
agent.has_image_parser_skill(is_private=is_private)
|
|
407
471
|
and not model.supports_image_input
|
|
408
472
|
):
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
473
|
+
image_urls_text = "\n".join(image_urls)
|
|
474
|
+
input_message += f"\n\nImages:\n{image_urls_text}"
|
|
475
|
+
messages = [
|
|
476
|
+
HumanMessage(content=input_message),
|
|
412
477
|
]
|
|
413
478
|
else:
|
|
414
479
|
# anyway, pass it directly to LLM
|
|
415
|
-
|
|
480
|
+
messages.extend(
|
|
416
481
|
[
|
|
417
|
-
|
|
482
|
+
HumanMessage(
|
|
483
|
+
content={"type": "image_url", "image_url": {"url": image_url}}
|
|
484
|
+
)
|
|
418
485
|
for image_url in image_urls
|
|
419
486
|
]
|
|
420
487
|
)
|
|
421
488
|
|
|
422
|
-
messages = [
|
|
423
|
-
HumanMessage(content=content),
|
|
424
|
-
]
|
|
425
|
-
|
|
426
489
|
# stream config
|
|
427
|
-
thread_id = f"{
|
|
490
|
+
thread_id = f"{user_message.agent_id}-{user_message.chat_id}"
|
|
428
491
|
stream_config = {
|
|
429
492
|
"configurable": {
|
|
430
493
|
"thread_id": thread_id,
|
|
@@ -432,13 +495,18 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
432
495
|
"recursion_limit": recursion_limit,
|
|
433
496
|
}
|
|
434
497
|
|
|
498
|
+
def get_agent() -> Agent:
|
|
499
|
+
return agent
|
|
500
|
+
|
|
435
501
|
context = AgentContext(
|
|
436
|
-
agent_id=
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
502
|
+
agent_id=user_message.agent_id,
|
|
503
|
+
get_agent=get_agent,
|
|
504
|
+
chat_id=user_message.chat_id,
|
|
505
|
+
user_id=user_message.user_id,
|
|
506
|
+
app_id=user_message.app_id,
|
|
507
|
+
entrypoint=user_message.author_type,
|
|
441
508
|
is_private=is_private,
|
|
509
|
+
search=search,
|
|
442
510
|
payer=payer if payment_enabled else None,
|
|
443
511
|
)
|
|
444
512
|
|
|
@@ -446,42 +514,84 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
446
514
|
cached_tool_step = None
|
|
447
515
|
try:
|
|
448
516
|
async for chunk in executor.astream(
|
|
449
|
-
{"messages": messages},
|
|
517
|
+
{"messages": messages},
|
|
518
|
+
context=context,
|
|
519
|
+
config=stream_config,
|
|
520
|
+
stream_mode=["updates", "custom"],
|
|
450
521
|
):
|
|
451
522
|
this_time = time.perf_counter()
|
|
452
523
|
logger.debug(f"stream chunk: {chunk}", extra={"thread_id": thread_id})
|
|
453
|
-
|
|
454
|
-
|
|
524
|
+
|
|
525
|
+
if isinstance(chunk, tuple) and len(chunk) == 2:
|
|
526
|
+
event_kind, payload = chunk
|
|
527
|
+
chunk = payload
|
|
528
|
+
|
|
529
|
+
if isinstance(chunk, dict) and "credit_check" in chunk:
|
|
530
|
+
credit_payload = chunk.get("credit_check", {})
|
|
531
|
+
content = credit_payload.get("message")
|
|
532
|
+
if content:
|
|
533
|
+
credit_message_create = ChatMessageCreate(
|
|
534
|
+
id=str(XID()),
|
|
535
|
+
agent_id=user_message.agent_id,
|
|
536
|
+
chat_id=user_message.chat_id,
|
|
537
|
+
user_id=user_message.user_id,
|
|
538
|
+
author_id=user_message.agent_id,
|
|
539
|
+
author_type=AuthorType.AGENT,
|
|
540
|
+
model=agent.model,
|
|
541
|
+
thread_type=user_message.author_type,
|
|
542
|
+
reply_to=user_message.id,
|
|
543
|
+
message=content,
|
|
544
|
+
input_tokens=0,
|
|
545
|
+
output_tokens=0,
|
|
546
|
+
time_cost=this_time - last,
|
|
547
|
+
)
|
|
548
|
+
last = this_time
|
|
549
|
+
credit_message = await credit_message_create.save()
|
|
550
|
+
yield credit_message
|
|
551
|
+
|
|
552
|
+
error_message_create = await ChatMessageCreate.from_system_message(
|
|
553
|
+
SystemMessageType.INSUFFICIENT_BALANCE,
|
|
554
|
+
agent_id=user_message.agent_id,
|
|
555
|
+
chat_id=user_message.chat_id,
|
|
556
|
+
user_id=user_message.user_id,
|
|
557
|
+
author_id=user_message.agent_id,
|
|
558
|
+
thread_type=user_message.author_type,
|
|
559
|
+
reply_to=user_message.id,
|
|
560
|
+
time_cost=0,
|
|
561
|
+
)
|
|
562
|
+
error_message = await error_message_create.save()
|
|
563
|
+
yield error_message
|
|
564
|
+
return
|
|
565
|
+
|
|
566
|
+
if not isinstance(chunk, dict):
|
|
567
|
+
continue
|
|
568
|
+
|
|
569
|
+
if "model" in chunk and "messages" in chunk["model"]:
|
|
570
|
+
if len(chunk["model"]["messages"]) != 1:
|
|
455
571
|
logger.error(
|
|
456
|
-
"unexpected
|
|
572
|
+
"unexpected model message: " + str(chunk["model"]["messages"]),
|
|
457
573
|
extra={"thread_id": thread_id},
|
|
458
574
|
)
|
|
459
|
-
msg = chunk["
|
|
460
|
-
|
|
461
|
-
|
|
575
|
+
msg = chunk["model"]["messages"][0]
|
|
576
|
+
has_tools = hasattr(msg, "tool_calls") and bool(msg.tool_calls)
|
|
577
|
+
if has_tools:
|
|
462
578
|
cached_tool_step = msg
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
if
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if "text" in content:
|
|
470
|
-
content = content["text"]
|
|
471
|
-
else:
|
|
472
|
-
content = str(content)
|
|
473
|
-
logger.error(f"unexpected content type: {content}")
|
|
474
|
-
# agent message
|
|
579
|
+
content = (
|
|
580
|
+
_extract_text_content(msg.content)
|
|
581
|
+
if hasattr(msg, "content")
|
|
582
|
+
else ""
|
|
583
|
+
)
|
|
584
|
+
if content and not has_tools:
|
|
475
585
|
chat_message_create = ChatMessageCreate(
|
|
476
586
|
id=str(XID()),
|
|
477
|
-
agent_id=
|
|
478
|
-
chat_id=
|
|
479
|
-
user_id=
|
|
480
|
-
author_id=
|
|
587
|
+
agent_id=user_message.agent_id,
|
|
588
|
+
chat_id=user_message.chat_id,
|
|
589
|
+
user_id=user_message.user_id,
|
|
590
|
+
author_id=user_message.agent_id,
|
|
481
591
|
author_type=AuthorType.AGENT,
|
|
482
592
|
model=agent.model,
|
|
483
|
-
thread_type=
|
|
484
|
-
reply_to=
|
|
593
|
+
thread_type=user_message.author_type,
|
|
594
|
+
reply_to=user_message.id,
|
|
485
595
|
message=content,
|
|
486
596
|
input_tokens=(
|
|
487
597
|
msg.usage_metadata.get("input_tokens", 0)
|
|
@@ -496,19 +606,13 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
496
606
|
time_cost=this_time - last,
|
|
497
607
|
)
|
|
498
608
|
last = this_time
|
|
499
|
-
if cold_start_cost > 0:
|
|
500
|
-
chat_message_create.cold_start_cost = cold_start_cost
|
|
501
|
-
cold_start_cost = 0
|
|
502
|
-
# handle message and payment in one transaction
|
|
503
609
|
async with get_session() as session:
|
|
504
|
-
# payment
|
|
505
610
|
if payment_enabled:
|
|
506
611
|
amount = await model.calculate_cost(
|
|
507
612
|
chat_message_create.input_tokens,
|
|
508
613
|
chat_message_create.output_tokens,
|
|
509
614
|
)
|
|
510
615
|
|
|
511
|
-
# Check for web_search_call in additional_kwargs
|
|
512
616
|
if (
|
|
513
617
|
hasattr(msg, "additional_kwargs")
|
|
514
618
|
and msg.additional_kwargs
|
|
@@ -519,7 +623,7 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
519
623
|
for tool_output in tool_outputs:
|
|
520
624
|
if tool_output.get("type") == "web_search_call":
|
|
521
625
|
logger.info(
|
|
522
|
-
f"[{
|
|
626
|
+
f"[{user_message.agent_id}] Found web_search_call in additional_kwargs"
|
|
523
627
|
)
|
|
524
628
|
amount += 35
|
|
525
629
|
break
|
|
@@ -527,11 +631,13 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
527
631
|
session,
|
|
528
632
|
payer,
|
|
529
633
|
chat_message_create.id,
|
|
530
|
-
|
|
634
|
+
user_message.id,
|
|
531
635
|
amount,
|
|
532
636
|
agent,
|
|
533
637
|
)
|
|
534
|
-
logger.info(
|
|
638
|
+
logger.info(
|
|
639
|
+
f"[{user_message.agent_id}] expense message: {amount}"
|
|
640
|
+
)
|
|
535
641
|
chat_message_create.credit_event_id = credit_event.id
|
|
536
642
|
chat_message_create.credit_cost = credit_event.total_amount
|
|
537
643
|
chat_message = await chat_message_create.save_in_session(
|
|
@@ -566,7 +672,8 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
566
672
|
"parameters": call["args"],
|
|
567
673
|
"success": True,
|
|
568
674
|
}
|
|
569
|
-
|
|
675
|
+
status = getattr(msg, "status", None)
|
|
676
|
+
if status == "error":
|
|
570
677
|
skill_call["success"] = False
|
|
571
678
|
skill_call["error_message"] = str(msg.content)
|
|
572
679
|
else:
|
|
@@ -576,20 +683,21 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
576
683
|
skill_call["response"] = textwrap.shorten(
|
|
577
684
|
str(msg.content), width=1000, placeholder="..."
|
|
578
685
|
)
|
|
579
|
-
|
|
580
|
-
|
|
686
|
+
artifact = getattr(msg, "artifact", None)
|
|
687
|
+
if artifact:
|
|
688
|
+
cached_attachments.extend(artifact)
|
|
581
689
|
skill_calls.append(skill_call)
|
|
582
690
|
break
|
|
583
691
|
skill_message_create = ChatMessageCreate(
|
|
584
692
|
id=str(XID()),
|
|
585
|
-
agent_id=
|
|
586
|
-
chat_id=
|
|
587
|
-
user_id=
|
|
588
|
-
author_id=
|
|
693
|
+
agent_id=user_message.agent_id,
|
|
694
|
+
chat_id=user_message.chat_id,
|
|
695
|
+
user_id=user_message.user_id,
|
|
696
|
+
author_id=user_message.agent_id,
|
|
589
697
|
author_type=AuthorType.SKILL,
|
|
590
698
|
model=agent.model,
|
|
591
|
-
thread_type=
|
|
592
|
-
reply_to=
|
|
699
|
+
thread_type=user_message.author_type,
|
|
700
|
+
reply_to=user_message.id,
|
|
593
701
|
message="",
|
|
594
702
|
skill_calls=skill_calls,
|
|
595
703
|
attachments=cached_attachments,
|
|
@@ -610,13 +718,8 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
610
718
|
time_cost=this_time - last,
|
|
611
719
|
)
|
|
612
720
|
last = this_time
|
|
613
|
-
if cold_start_cost > 0:
|
|
614
|
-
skill_message_create.cold_start_cost = cold_start_cost
|
|
615
|
-
cold_start_cost = 0
|
|
616
|
-
# save message and credit in one transaction
|
|
617
721
|
async with get_session() as session:
|
|
618
722
|
if payment_enabled:
|
|
619
|
-
# message payment, only first call in a group has message bill
|
|
620
723
|
if have_first_call_in_cache:
|
|
621
724
|
message_amount = await model.calculate_cost(
|
|
622
725
|
skill_message_create.input_tokens,
|
|
@@ -626,7 +729,7 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
626
729
|
session,
|
|
627
730
|
payer,
|
|
628
731
|
skill_message_create.id,
|
|
629
|
-
|
|
732
|
+
user_message.id,
|
|
630
733
|
message_amount,
|
|
631
734
|
agent,
|
|
632
735
|
)
|
|
@@ -636,15 +739,17 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
636
739
|
skill_message_create.credit_cost = (
|
|
637
740
|
message_payment_event.total_amount
|
|
638
741
|
)
|
|
639
|
-
# skill payment
|
|
640
742
|
for skill_call in skill_calls:
|
|
641
743
|
if not skill_call["success"]:
|
|
642
744
|
continue
|
|
745
|
+
skill = await Skill.get(skill_call["name"])
|
|
746
|
+
if not skill:
|
|
747
|
+
continue
|
|
643
748
|
payment_event = await expense_skill(
|
|
644
749
|
session,
|
|
645
750
|
payer,
|
|
646
751
|
skill_message_create.id,
|
|
647
|
-
|
|
752
|
+
user_message.id,
|
|
648
753
|
skill_call["id"],
|
|
649
754
|
skill_call["name"],
|
|
650
755
|
agent,
|
|
@@ -652,73 +757,61 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
652
757
|
skill_call["credit_event_id"] = payment_event.id
|
|
653
758
|
skill_call["credit_cost"] = payment_event.total_amount
|
|
654
759
|
logger.info(
|
|
655
|
-
f"[{
|
|
760
|
+
f"[{user_message.agent_id}] skill payment: {skill_call}"
|
|
656
761
|
)
|
|
657
762
|
skill_message_create.skill_calls = skill_calls
|
|
658
763
|
skill_message = await skill_message_create.save_in_session(session)
|
|
659
764
|
await session.commit()
|
|
660
765
|
yield skill_message
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
elif "post_model_hook" in chunk:
|
|
664
|
-
logger.debug(
|
|
665
|
-
f"post_model_hook: {chunk}",
|
|
666
|
-
extra={"thread_id": thread_id},
|
|
667
|
-
)
|
|
668
|
-
if chunk["post_model_hook"] and "error" in chunk["post_model_hook"]:
|
|
766
|
+
else:
|
|
767
|
+
for node_name, update in chunk.items():
|
|
669
768
|
if (
|
|
670
|
-
|
|
671
|
-
|
|
769
|
+
node_name.endswith("CreditCheckMiddleware.after_model")
|
|
770
|
+
and isinstance(update, dict)
|
|
771
|
+
and update.get("error") == AgentError.INSUFFICIENT_CREDITS
|
|
672
772
|
):
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
if isinstance(
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
post_model_message = await post_model_message_create.save()
|
|
701
|
-
yield post_model_message
|
|
773
|
+
ai_messages = [
|
|
774
|
+
message
|
|
775
|
+
for message in update.get("messages", [])
|
|
776
|
+
if isinstance(message, BaseMessage)
|
|
777
|
+
]
|
|
778
|
+
content = ""
|
|
779
|
+
if ai_messages:
|
|
780
|
+
content = _extract_text_content(ai_messages[-1].content)
|
|
781
|
+
post_model_message_create = ChatMessageCreate(
|
|
782
|
+
id=str(XID()),
|
|
783
|
+
agent_id=user_message.agent_id,
|
|
784
|
+
chat_id=user_message.chat_id,
|
|
785
|
+
user_id=user_message.user_id,
|
|
786
|
+
author_id=user_message.agent_id,
|
|
787
|
+
author_type=AuthorType.AGENT,
|
|
788
|
+
model=agent.model,
|
|
789
|
+
thread_type=user_message.author_type,
|
|
790
|
+
reply_to=user_message.id,
|
|
791
|
+
message=content,
|
|
792
|
+
input_tokens=0,
|
|
793
|
+
output_tokens=0,
|
|
794
|
+
time_cost=this_time - last,
|
|
795
|
+
)
|
|
796
|
+
last = this_time
|
|
797
|
+
post_model_message = await post_model_message_create.save()
|
|
798
|
+
yield post_model_message
|
|
799
|
+
|
|
702
800
|
error_message_create = (
|
|
703
801
|
await ChatMessageCreate.from_system_message(
|
|
704
802
|
SystemMessageType.INSUFFICIENT_BALANCE,
|
|
705
|
-
agent_id=
|
|
706
|
-
chat_id=
|
|
707
|
-
user_id=
|
|
708
|
-
author_id=
|
|
709
|
-
thread_type=
|
|
710
|
-
reply_to=
|
|
803
|
+
agent_id=user_message.agent_id,
|
|
804
|
+
chat_id=user_message.chat_id,
|
|
805
|
+
user_id=user_message.user_id,
|
|
806
|
+
author_id=user_message.agent_id,
|
|
807
|
+
thread_type=user_message.author_type,
|
|
808
|
+
reply_to=user_message.id,
|
|
711
809
|
time_cost=0,
|
|
712
810
|
)
|
|
713
811
|
)
|
|
714
812
|
error_message = await error_message_create.save()
|
|
715
813
|
yield error_message
|
|
716
|
-
|
|
717
|
-
error_traceback = traceback.format_exc()
|
|
718
|
-
logger.error(
|
|
719
|
-
f"unexpected message type: {str(chunk)}\n{error_traceback}",
|
|
720
|
-
extra={"thread_id": thread_id},
|
|
721
|
-
)
|
|
814
|
+
return
|
|
722
815
|
except SQLAlchemyError as e:
|
|
723
816
|
error_traceback = traceback.format_exc()
|
|
724
817
|
logger.error(
|
|
@@ -727,12 +820,12 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
727
820
|
)
|
|
728
821
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
729
822
|
SystemMessageType.AGENT_INTERNAL_ERROR,
|
|
730
|
-
agent_id=
|
|
731
|
-
chat_id=
|
|
732
|
-
user_id=
|
|
733
|
-
author_id=
|
|
734
|
-
thread_type=
|
|
735
|
-
reply_to=
|
|
823
|
+
agent_id=user_message.agent_id,
|
|
824
|
+
chat_id=user_message.chat_id,
|
|
825
|
+
user_id=user_message.user_id,
|
|
826
|
+
author_id=user_message.agent_id,
|
|
827
|
+
thread_type=user_message.author_type,
|
|
828
|
+
reply_to=user_message.id,
|
|
736
829
|
time_cost=time.perf_counter() - start,
|
|
737
830
|
)
|
|
738
831
|
error_message = await error_message_create.save()
|
|
@@ -742,16 +835,16 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
742
835
|
error_traceback = traceback.format_exc()
|
|
743
836
|
logger.error(
|
|
744
837
|
f"reached recursion limit: {str(e)}\n{error_traceback}",
|
|
745
|
-
extra={"thread_id": thread_id, "agent_id":
|
|
838
|
+
extra={"thread_id": thread_id, "agent_id": user_message.agent_id},
|
|
746
839
|
)
|
|
747
840
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
748
841
|
SystemMessageType.STEP_LIMIT_EXCEEDED,
|
|
749
|
-
agent_id=
|
|
750
|
-
chat_id=
|
|
751
|
-
user_id=
|
|
752
|
-
author_id=
|
|
753
|
-
thread_type=
|
|
754
|
-
reply_to=
|
|
842
|
+
agent_id=user_message.agent_id,
|
|
843
|
+
chat_id=user_message.chat_id,
|
|
844
|
+
user_id=user_message.user_id,
|
|
845
|
+
author_id=user_message.agent_id,
|
|
846
|
+
thread_type=user_message.author_type,
|
|
847
|
+
reply_to=user_message.id,
|
|
755
848
|
time_cost=time.perf_counter() - start,
|
|
756
849
|
)
|
|
757
850
|
error_message = await error_message_create.save()
|
|
@@ -761,21 +854,21 @@ async def stream_agent(message: ChatMessageCreate):
|
|
|
761
854
|
error_traceback = traceback.format_exc()
|
|
762
855
|
logger.error(
|
|
763
856
|
f"failed to execute agent: {str(e)}\n{error_traceback}",
|
|
764
|
-
extra={"thread_id": thread_id, "agent_id":
|
|
857
|
+
extra={"thread_id": thread_id, "agent_id": user_message.agent_id},
|
|
765
858
|
)
|
|
766
859
|
error_message_create = await ChatMessageCreate.from_system_message(
|
|
767
860
|
SystemMessageType.AGENT_INTERNAL_ERROR,
|
|
768
|
-
agent_id=
|
|
769
|
-
chat_id=
|
|
770
|
-
user_id=
|
|
771
|
-
author_id=
|
|
772
|
-
thread_type=
|
|
773
|
-
reply_to=
|
|
861
|
+
agent_id=user_message.agent_id,
|
|
862
|
+
chat_id=user_message.chat_id,
|
|
863
|
+
user_id=user_message.user_id,
|
|
864
|
+
author_id=user_message.agent_id,
|
|
865
|
+
thread_type=user_message.author_type,
|
|
866
|
+
reply_to=user_message.id,
|
|
774
867
|
time_cost=time.perf_counter() - start,
|
|
775
868
|
)
|
|
776
869
|
error_message = await error_message_create.save()
|
|
777
870
|
yield error_message
|
|
778
|
-
await clear_thread_memory(
|
|
871
|
+
await clear_thread_memory(user_message.agent_id, user_message.chat_id)
|
|
779
872
|
return
|
|
780
873
|
|
|
781
874
|
|
|
@@ -830,14 +923,15 @@ async def clean_agent_memory(
|
|
|
830
923
|
# get the agent from the database
|
|
831
924
|
try:
|
|
832
925
|
if not clean_skill and not clean_agent:
|
|
833
|
-
raise
|
|
926
|
+
raise IntentKitAPIError(
|
|
834
927
|
status_code=400,
|
|
835
|
-
|
|
928
|
+
key="InvalidCleanupParameters",
|
|
929
|
+
message="at least one of skills data or agent memory should be true",
|
|
836
930
|
)
|
|
837
931
|
|
|
838
932
|
if clean_skill:
|
|
839
933
|
await AgentSkillData.clean_data(agent_id)
|
|
840
|
-
await
|
|
934
|
+
await ChatSkillData.clean_data(agent_id, chat_id)
|
|
841
935
|
|
|
842
936
|
async with get_session() as db:
|
|
843
937
|
if clean_agent:
|
|
@@ -879,7 +973,7 @@ async def clean_agent_memory(
|
|
|
879
973
|
except SQLAlchemyError as e:
|
|
880
974
|
# Handle other SQLAlchemy-related errors
|
|
881
975
|
logger.error(e)
|
|
882
|
-
raise
|
|
976
|
+
raise IntentKitAPIError(status_code=500, key="DatabaseError", message=str(e))
|
|
883
977
|
except Exception as e:
|
|
884
978
|
logger.error("failed to cleanup the agent memory: " + str(e))
|
|
885
979
|
raise e
|
|
@@ -888,10 +982,7 @@ async def clean_agent_memory(
|
|
|
888
982
|
async def thread_stats(agent_id: str, chat_id: str) -> list[BaseMessage]:
|
|
889
983
|
thread_id = f"{agent_id}-{chat_id}"
|
|
890
984
|
stream_config = {"configurable": {"thread_id": thread_id}}
|
|
891
|
-
|
|
892
|
-
if chat_id.startswith("owner") or chat_id.startswith("autonomous"):
|
|
893
|
-
is_private = True
|
|
894
|
-
executor, _ = await agent_executor(agent_id, is_private)
|
|
985
|
+
executor, _ = await agent_executor(agent_id)
|
|
895
986
|
snap = await executor.aget_state(stream_config)
|
|
896
987
|
if snap.values and "messages" in snap.values:
|
|
897
988
|
return snap.values["messages"]
|