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/draft.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""Service functions for agent draft operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from epyxid import XID
|
|
6
|
+
from fastapi import status
|
|
7
|
+
from sqlalchemy import desc, select
|
|
8
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
9
|
+
|
|
10
|
+
from intentkit.models.agent import Agent, AgentUserInput
|
|
11
|
+
from intentkit.models.draft import AgentDraft, AgentDraftTable
|
|
12
|
+
from intentkit.utils.error import IntentKitAPIError
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def update_agent_draft(
|
|
16
|
+
*,
|
|
17
|
+
agent_id: str,
|
|
18
|
+
user_id: str,
|
|
19
|
+
input: AgentUserInput,
|
|
20
|
+
db: AsyncSession,
|
|
21
|
+
) -> AgentDraft:
|
|
22
|
+
"""Update the latest draft for the specified agent with partial field updates.
|
|
23
|
+
|
|
24
|
+
This function only updates fields that are explicitly provided in the input,
|
|
25
|
+
leaving other fields unchanged. This is more efficient than override as it
|
|
26
|
+
reduces context usage and minimizes the risk of accidentally changing fields.
|
|
27
|
+
"""
|
|
28
|
+
query = (
|
|
29
|
+
select(AgentDraftTable)
|
|
30
|
+
.where(AgentDraftTable.agent_id == agent_id, AgentDraftTable.owner == user_id)
|
|
31
|
+
.order_by(desc(AgentDraftTable.created_at))
|
|
32
|
+
.limit(1)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
result = await db.execute(query)
|
|
36
|
+
latest_draft = result.scalar_one_or_none()
|
|
37
|
+
|
|
38
|
+
if not latest_draft:
|
|
39
|
+
raise IntentKitAPIError(
|
|
40
|
+
status.HTTP_404_NOT_FOUND,
|
|
41
|
+
"DraftNotFound",
|
|
42
|
+
"No drafts found for this agent",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Get only the fields that are explicitly provided (exclude_unset=True)
|
|
46
|
+
update_data = input.model_dump(exclude_unset=True)
|
|
47
|
+
|
|
48
|
+
if latest_draft.deployed_at is not None:
|
|
49
|
+
# Create new draft version if current one is deployed
|
|
50
|
+
draft_id = str(XID())
|
|
51
|
+
|
|
52
|
+
# Start with existing draft data and merge updates
|
|
53
|
+
draft_data = AgentUserInput.model_validate(latest_draft).model_dump()
|
|
54
|
+
draft_data.update(update_data)
|
|
55
|
+
|
|
56
|
+
updated_input = AgentUserInput.model_validate(draft_data)
|
|
57
|
+
|
|
58
|
+
draft_table = AgentDraftTable(
|
|
59
|
+
id=draft_id,
|
|
60
|
+
agent_id=agent_id,
|
|
61
|
+
owner=user_id,
|
|
62
|
+
version=updated_input.hash(),
|
|
63
|
+
last_draft_id=latest_draft.id,
|
|
64
|
+
project_id=latest_draft.project_id,
|
|
65
|
+
**draft_data,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
db.add(draft_table)
|
|
69
|
+
await db.commit()
|
|
70
|
+
await db.refresh(draft_table)
|
|
71
|
+
|
|
72
|
+
return AgentDraft.model_validate(draft_table)
|
|
73
|
+
|
|
74
|
+
# Update existing draft in-place
|
|
75
|
+
for key, value in update_data.items():
|
|
76
|
+
setattr(latest_draft, key, value)
|
|
77
|
+
|
|
78
|
+
# Update version hash based on updated data
|
|
79
|
+
updated_input = AgentUserInput.model_validate(latest_draft)
|
|
80
|
+
latest_draft.version = updated_input.hash()
|
|
81
|
+
|
|
82
|
+
await db.commit()
|
|
83
|
+
await db.refresh(latest_draft)
|
|
84
|
+
|
|
85
|
+
return AgentDraft.model_validate(latest_draft)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def override_agent_draft(
|
|
89
|
+
*,
|
|
90
|
+
agent_id: str,
|
|
91
|
+
user_id: str,
|
|
92
|
+
input: AgentUserInput,
|
|
93
|
+
db: AsyncSession,
|
|
94
|
+
) -> AgentDraft:
|
|
95
|
+
"""Override the latest draft for the specified agent."""
|
|
96
|
+
query = (
|
|
97
|
+
select(AgentDraftTable)
|
|
98
|
+
.where(AgentDraftTable.agent_id == agent_id, AgentDraftTable.owner == user_id)
|
|
99
|
+
.order_by(desc(AgentDraftTable.created_at))
|
|
100
|
+
.limit(1)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
result = await db.execute(query)
|
|
104
|
+
latest_draft = result.scalar_one_or_none()
|
|
105
|
+
|
|
106
|
+
if not latest_draft:
|
|
107
|
+
raise IntentKitAPIError(
|
|
108
|
+
status.HTTP_404_NOT_FOUND,
|
|
109
|
+
"DraftNotFound",
|
|
110
|
+
"No drafts found for this agent",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if latest_draft.deployed_at is not None:
|
|
114
|
+
draft_id = str(XID())
|
|
115
|
+
|
|
116
|
+
draft_table = AgentDraftTable(
|
|
117
|
+
id=draft_id,
|
|
118
|
+
agent_id=agent_id,
|
|
119
|
+
owner=user_id,
|
|
120
|
+
version=input.hash(),
|
|
121
|
+
last_draft_id=latest_draft.id,
|
|
122
|
+
project_id=latest_draft.project_id,
|
|
123
|
+
**input.model_dump(),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
db.add(draft_table)
|
|
127
|
+
await db.commit()
|
|
128
|
+
await db.refresh(draft_table)
|
|
129
|
+
|
|
130
|
+
return AgentDraft.model_validate(draft_table)
|
|
131
|
+
|
|
132
|
+
for key, value in input.model_dump().items():
|
|
133
|
+
setattr(latest_draft, key, value)
|
|
134
|
+
|
|
135
|
+
latest_draft.version = input.hash()
|
|
136
|
+
|
|
137
|
+
await db.commit()
|
|
138
|
+
await db.refresh(latest_draft)
|
|
139
|
+
|
|
140
|
+
return AgentDraft.model_validate(latest_draft)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
async def get_agent_latest_draft(
|
|
144
|
+
*,
|
|
145
|
+
agent_id: str,
|
|
146
|
+
user_id: str,
|
|
147
|
+
db: AsyncSession,
|
|
148
|
+
) -> AgentDraft:
|
|
149
|
+
"""Return the latest draft for the specified agent."""
|
|
150
|
+
query = (
|
|
151
|
+
select(AgentDraftTable)
|
|
152
|
+
.where(AgentDraftTable.agent_id == agent_id, AgentDraftTable.owner == user_id)
|
|
153
|
+
.order_by(desc(AgentDraftTable.created_at))
|
|
154
|
+
.limit(1)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
result = await db.execute(query)
|
|
158
|
+
latest_draft = result.scalar_one_or_none()
|
|
159
|
+
|
|
160
|
+
if latest_draft:
|
|
161
|
+
return AgentDraft.model_validate(latest_draft)
|
|
162
|
+
|
|
163
|
+
agent = await Agent.get(agent_id)
|
|
164
|
+
|
|
165
|
+
if not agent:
|
|
166
|
+
raise IntentKitAPIError(
|
|
167
|
+
status.HTTP_404_NOT_FOUND,
|
|
168
|
+
"AgentNotFound",
|
|
169
|
+
"No drafts found for this agent",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
if agent.owner != user_id:
|
|
173
|
+
raise IntentKitAPIError(
|
|
174
|
+
status.HTTP_403_FORBIDDEN,
|
|
175
|
+
"Forbidden",
|
|
176
|
+
"Not your agent",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
draft_id = str(XID())
|
|
180
|
+
|
|
181
|
+
agent_dict = agent.model_dump()
|
|
182
|
+
input_dict: dict[str, object] = {}
|
|
183
|
+
for key in AgentUserInput.model_fields:
|
|
184
|
+
if key in agent_dict:
|
|
185
|
+
input_dict[key] = agent_dict[key]
|
|
186
|
+
input = AgentUserInput.model_validate(input_dict)
|
|
187
|
+
|
|
188
|
+
draft_table = AgentDraftTable(
|
|
189
|
+
id=draft_id,
|
|
190
|
+
agent_id=agent_id,
|
|
191
|
+
owner=user_id,
|
|
192
|
+
version=input.hash(),
|
|
193
|
+
deployed_at=agent.updated_at,
|
|
194
|
+
**input.model_dump(),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
db.add(draft_table)
|
|
198
|
+
await db.commit()
|
|
199
|
+
await db.refresh(draft_table)
|
|
200
|
+
|
|
201
|
+
return AgentDraft.model_validate(draft_table)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Utilities for streaming draft agent conversations."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from datetime import datetime, timedelta, timezone
|
|
6
|
+
from typing import AsyncGenerator
|
|
7
|
+
|
|
8
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
9
|
+
from sqlalchemy import desc, select
|
|
10
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
11
|
+
|
|
12
|
+
from intentkit.core.engine import build_agent, stream_agent_raw
|
|
13
|
+
from intentkit.models.agent import Agent
|
|
14
|
+
from intentkit.models.agent_data import AgentData
|
|
15
|
+
from intentkit.models.chat import ChatMessage, ChatMessageCreate
|
|
16
|
+
from intentkit.models.db import get_session
|
|
17
|
+
from intentkit.models.draft import AgentDraft, AgentDraftTable
|
|
18
|
+
from intentkit.utils.error import IntentKitAPIError
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_draft_executors: dict[str, CompiledStateGraph] = {}
|
|
24
|
+
_draft_updated_at: dict[str, datetime] = {}
|
|
25
|
+
_draft_cached_at: dict[str, datetime] = {}
|
|
26
|
+
|
|
27
|
+
_CACHE_TTL = timedelta(days=1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
async def stream_draft(
|
|
31
|
+
agent_id: str, message: ChatMessageCreate
|
|
32
|
+
) -> AsyncGenerator[ChatMessage, None]:
|
|
33
|
+
"""Stream chat messages for the latest draft of an agent."""
|
|
34
|
+
|
|
35
|
+
draft = await _get_latest_draft(agent_id)
|
|
36
|
+
agent = _agent_from_draft(draft)
|
|
37
|
+
executor, cold_start_cost = await _get_draft_executor(agent, draft)
|
|
38
|
+
|
|
39
|
+
if not message.agent_id:
|
|
40
|
+
message.agent_id = agent.id
|
|
41
|
+
message.cold_start_cost = cold_start_cost
|
|
42
|
+
|
|
43
|
+
async for chat_message in stream_agent_raw(message, agent, executor):
|
|
44
|
+
yield chat_message
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def _get_latest_draft(agent_id: str) -> AgentDraft:
|
|
48
|
+
async with get_session() as session:
|
|
49
|
+
result = await _execute_latest_draft_query(session, agent_id)
|
|
50
|
+
draft_row = result.scalar_one_or_none()
|
|
51
|
+
|
|
52
|
+
if not draft_row:
|
|
53
|
+
raise IntentKitAPIError(
|
|
54
|
+
status_code=404,
|
|
55
|
+
key="DraftNotFound",
|
|
56
|
+
message=f"No draft found for agent {agent_id}",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return AgentDraft.model_validate(draft_row)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def _execute_latest_draft_query(session: AsyncSession, agent_id: str):
|
|
63
|
+
statement = (
|
|
64
|
+
select(AgentDraftTable)
|
|
65
|
+
.where(AgentDraftTable.agent_id == agent_id)
|
|
66
|
+
.order_by(desc(AgentDraftTable.updated_at))
|
|
67
|
+
.limit(1)
|
|
68
|
+
)
|
|
69
|
+
return await session.execute(statement)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _agent_from_draft(draft: AgentDraft) -> Agent:
|
|
73
|
+
data = draft.model_dump()
|
|
74
|
+
data.pop("id", None)
|
|
75
|
+
data.pop("agent_id", None)
|
|
76
|
+
data.pop("last_draft_id", None)
|
|
77
|
+
data["id"] = draft.agent_id
|
|
78
|
+
data["owner"] = draft.owner
|
|
79
|
+
data["deployed_at"] = draft.deployed_at
|
|
80
|
+
data["created_at"] = draft.created_at
|
|
81
|
+
data["updated_at"] = draft.updated_at
|
|
82
|
+
data["version"] = draft.version
|
|
83
|
+
return Agent.model_validate(data)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
async def _get_draft_executor(
|
|
87
|
+
agent: Agent, draft: AgentDraft
|
|
88
|
+
) -> tuple[CompiledStateGraph, float]:
|
|
89
|
+
now = datetime.now(timezone.utc)
|
|
90
|
+
_cleanup_cache(now)
|
|
91
|
+
|
|
92
|
+
cached_executor = _draft_executors.get(agent.id)
|
|
93
|
+
cached_updated = _draft_updated_at.get(agent.id)
|
|
94
|
+
cold_start_cost = 0.0
|
|
95
|
+
|
|
96
|
+
if not cached_executor or cached_updated != draft.updated_at:
|
|
97
|
+
start = time.perf_counter()
|
|
98
|
+
agent_data = AgentData(id=agent.id)
|
|
99
|
+
cached_executor = await build_agent(agent, agent_data)
|
|
100
|
+
cold_start_cost = time.perf_counter() - start
|
|
101
|
+
_draft_executors[agent.id] = cached_executor
|
|
102
|
+
_draft_updated_at[agent.id] = draft.updated_at
|
|
103
|
+
_draft_cached_at[agent.id] = now
|
|
104
|
+
logger.info("Initialized draft executor for agent %s", agent.id)
|
|
105
|
+
else:
|
|
106
|
+
_draft_cached_at[agent.id] = now
|
|
107
|
+
|
|
108
|
+
return cached_executor, cold_start_cost
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _cleanup_cache(now: datetime) -> None:
|
|
112
|
+
expired_before = now - _CACHE_TTL
|
|
113
|
+
for agent_id, cached_time in list(_draft_cached_at.items()):
|
|
114
|
+
if cached_time < expired_before:
|
|
115
|
+
_draft_cached_at.pop(agent_id, None)
|
|
116
|
+
_draft_updated_at.pop(agent_id, None)
|
|
117
|
+
_draft_executors.pop(agent_id, None)
|
|
118
|
+
logger.debug("Removed expired draft executor for agent %s", agent_id)
|