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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Manager module for agent management operations."""
|
|
2
|
+
|
|
3
|
+
from intentkit.core.manager.engine import stream_manager
|
|
4
|
+
from intentkit.core.manager.service import (
|
|
5
|
+
agent_draft_json_schema,
|
|
6
|
+
get_latest_public_info,
|
|
7
|
+
get_skills_hierarchical_text,
|
|
8
|
+
)
|
|
9
|
+
from intentkit.core.manager.skills import (
|
|
10
|
+
get_agent_latest_draft_skill,
|
|
11
|
+
get_agent_latest_public_info_skill,
|
|
12
|
+
update_agent_draft_skill,
|
|
13
|
+
update_public_info_skill,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"stream_manager",
|
|
18
|
+
"agent_draft_json_schema",
|
|
19
|
+
"get_skills_hierarchical_text",
|
|
20
|
+
"get_latest_public_info",
|
|
21
|
+
"get_agent_latest_draft_skill",
|
|
22
|
+
"get_agent_latest_public_info_skill",
|
|
23
|
+
"update_agent_draft_skill",
|
|
24
|
+
"update_public_info_skill",
|
|
25
|
+
]
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"""Streaming utilities for the on-demand manager agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import time
|
|
7
|
+
from datetime import datetime, timedelta, timezone
|
|
8
|
+
from typing import AsyncGenerator
|
|
9
|
+
|
|
10
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
11
|
+
|
|
12
|
+
from intentkit.core.engine import build_agent, stream_agent_raw
|
|
13
|
+
from intentkit.core.manager.skills import (
|
|
14
|
+
get_agent_latest_draft_skill,
|
|
15
|
+
get_agent_latest_public_info_skill,
|
|
16
|
+
update_agent_draft_skill,
|
|
17
|
+
update_public_info_skill,
|
|
18
|
+
)
|
|
19
|
+
from intentkit.models.agent import Agent
|
|
20
|
+
from intentkit.models.agent_data import AgentData
|
|
21
|
+
from intentkit.models.chat import ChatMessage, ChatMessageCreate
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_MANAGER_CACHE_TTL = timedelta(hours=1)
|
|
27
|
+
|
|
28
|
+
_manager_executors: dict[str, CompiledStateGraph] = {}
|
|
29
|
+
_manager_agents: dict[str, Agent] = {}
|
|
30
|
+
_manager_cached_at: dict[str, datetime] = {}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def stream_manager(
|
|
34
|
+
agent_id: str, user_id: str, message: ChatMessageCreate
|
|
35
|
+
) -> AsyncGenerator[ChatMessage, None]:
|
|
36
|
+
"""Stream chat messages for the manager agent of a specific agent."""
|
|
37
|
+
|
|
38
|
+
executor, manager_agent, cold_start_cost = await _get_manager_executor(
|
|
39
|
+
agent_id, user_id
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if not message.agent_id:
|
|
43
|
+
message.agent_id = manager_agent.id
|
|
44
|
+
message.cold_start_cost = cold_start_cost
|
|
45
|
+
|
|
46
|
+
async for chat_message in stream_agent_raw(message, manager_agent, executor):
|
|
47
|
+
yield chat_message
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _build_manager_agent(agent_id: str, user_id: str) -> Agent:
|
|
51
|
+
now = datetime.now(timezone.utc)
|
|
52
|
+
|
|
53
|
+
# Get hierarchical skills text
|
|
54
|
+
# skills_text = get_skills_hierarchical_text()
|
|
55
|
+
|
|
56
|
+
prompt = (
|
|
57
|
+
"### Create or Update Agent Draft.\n\n"
|
|
58
|
+
"Use the available tools get_agent_latest_draft and update_agent_draft"
|
|
59
|
+
" to review the latest draft, summarise updates, and propose modifications"
|
|
60
|
+
" when necessary.\n"
|
|
61
|
+
"Always explain what changed, why it changed, and whether any drafts"
|
|
62
|
+
" were created or updated.\n"
|
|
63
|
+
"When you update a draft, ensure the saved content remains consistent"
|
|
64
|
+
" with the agent's purpose and principles.\n"
|
|
65
|
+
"When a user makes a request to create or update an agent,"
|
|
66
|
+
" you should always use skill get_agent_latest_draft to get the latest draft,"
|
|
67
|
+
" then make changes from it and use skill update_agent_draft for the changes,"
|
|
68
|
+
" remember the tool input data will only update the explicitly provided fields,"
|
|
69
|
+
" at last summarize the changes to the user.\n"
|
|
70
|
+
"The update_agent_draft function is efficient and safe, only updating fields you explicitly provide.\n"
|
|
71
|
+
"If the field deployed_at of the latest draft is empty,"
|
|
72
|
+
" it means the draft has not been deployed yet,"
|
|
73
|
+
" and you should refuse requests such as autonomous management and agent analysis.\n\n"
|
|
74
|
+
"\n\n### Avatar Generation\n\n"
|
|
75
|
+
"The field `picture` in the agent draft is used to store the avatar image URL."
|
|
76
|
+
"If the `picture` field is empty after a draft generation, you can ask user if they want to generate an avatar."
|
|
77
|
+
"Use the `gpt_avatar_generator` skill to generate avatar-friendly images."
|
|
78
|
+
"After get the avatar url from the skill result, you can update the `picture` field in the draft."
|
|
79
|
+
"\n\n### Model Choice\n\n"
|
|
80
|
+
"Use `gpt-5-mini` for normal requests, and `gpt-5` for complex requests."
|
|
81
|
+
"If the user specified a model, call the `get_available_llms` skill to retrieve all"
|
|
82
|
+
" available model IDs and find the closest match."
|
|
83
|
+
"\n\n### Skill Configuration\n\n"
|
|
84
|
+
"""Because skills consume context, too much context can lead to a decline in LLM performance.
|
|
85
|
+
Therefore, please use skills sparingly, ideally keeping the number below 20.
|
|
86
|
+
If multiple skills are available for a single function, choose the one you deem most reliable.
|
|
87
|
+
In a category, there are often many skills. Please select only the ones that are definitely useful.
|
|
88
|
+
|
|
89
|
+
If a skill category's `api_key_provider` has only `agent_owner` as an option,
|
|
90
|
+
then that skill will definitely require user input for the API key.
|
|
91
|
+
You can suggest in your communication that the user manually configure it later,
|
|
92
|
+
and avoid automatically generating drafts that use this skill.
|
|
93
|
+
A typical skill configuration would look like this:
|
|
94
|
+
```
|
|
95
|
+
"skills": {"category1": {"states": {"skill1": "public"}, "enabled": true}}
|
|
96
|
+
```
|
|
97
|
+
The `enabled` flag is at the category level, and `states` refers to specific skills.
|
|
98
|
+
For content involving sensitive material, select `private`. For content suitable for all users, select `public`.
|
|
99
|
+
"""
|
|
100
|
+
"\n\n### Public Information\n\n"
|
|
101
|
+
"Only agents that have already been deployed at least once can have their public"
|
|
102
|
+
" information updated.\n"
|
|
103
|
+
"The way to determine if it has been deployed at least once is to call `get_agent_latest_public_info`."
|
|
104
|
+
"Public info is only required when preparing to publish an agent;"
|
|
105
|
+
" private agents do not need it.\n"
|
|
106
|
+
"Always call get_agent_latest_public_info before updating"
|
|
107
|
+
" public info, and use update_public_info only when changes"
|
|
108
|
+
" are necessary.\n"
|
|
109
|
+
"The update_public_info function is efficient and safe, only updating fields you explicitly provide.\n\n"
|
|
110
|
+
# "### Available Skills for Agent Configuration\n\n"
|
|
111
|
+
# f"{skills_text}\n\n"
|
|
112
|
+
# "When using the update_agent_draft tool, select skills from the list above based on the agent's requirements. "
|
|
113
|
+
# "Use the exact skill names (e.g., 'erc20', 'common', 'twitter', etc.) when configuring the skills property. "
|
|
114
|
+
# "Each skill can be enabled/disabled and configured with specific states and API key providers according to its schema."
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
agent_data = {
|
|
118
|
+
"id": agent_id,
|
|
119
|
+
"owner": user_id,
|
|
120
|
+
"name": "Agent Manager",
|
|
121
|
+
"purpose": "Assist with generating, updating, and reviewing agent drafts.",
|
|
122
|
+
"personality": "Thorough, collaborative, and transparent about actions.",
|
|
123
|
+
"principles": (
|
|
124
|
+
"1. Keep the agent owner informed about every change.\n"
|
|
125
|
+
"2. Preserve important context from prior drafts.\n"
|
|
126
|
+
"3. Only modify drafts using the provided update tool.\n"
|
|
127
|
+
"4. Speak to users in the language they ask their questions, but always use English in Agent Draft.\n"
|
|
128
|
+
"5. When updating a draft, try to select the right skills. Don't pick too many, just enough to meet user needs.\n"
|
|
129
|
+
"6. Update skill is override update, you must put the whole fields to input data, not only changed fields."
|
|
130
|
+
),
|
|
131
|
+
"model": "grok-code-fast-1",
|
|
132
|
+
"prompt": prompt,
|
|
133
|
+
"prompt_append": None,
|
|
134
|
+
"short_term_memory_strategy": "trim",
|
|
135
|
+
"temperature": 0.2,
|
|
136
|
+
"frequency_penalty": 0.0,
|
|
137
|
+
"presence_penalty": 0.0,
|
|
138
|
+
"skills": {
|
|
139
|
+
"system": {
|
|
140
|
+
"enabled": True,
|
|
141
|
+
"states": {
|
|
142
|
+
"add_autonomous_task": "private",
|
|
143
|
+
"delete_autonomous_task": "private",
|
|
144
|
+
"edit_autonomous_task": "private",
|
|
145
|
+
"list_autonomous_tasks": "private",
|
|
146
|
+
"read_agent_api_key": "private",
|
|
147
|
+
"regenerate_agent_api_key": "private",
|
|
148
|
+
"get_available_llms": "private",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
"openai": {
|
|
152
|
+
"enabled": True,
|
|
153
|
+
"api_key_provider": "platform",
|
|
154
|
+
"states": {
|
|
155
|
+
"gpt_avatar_generator": "private",
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
"created_at": now,
|
|
160
|
+
"updated_at": now,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return Agent.model_validate(agent_data)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
async def _get_manager_executor(
|
|
167
|
+
agent_id: str, user_id: str
|
|
168
|
+
) -> tuple[CompiledStateGraph, Agent, float]:
|
|
169
|
+
now = datetime.now(timezone.utc)
|
|
170
|
+
_cleanup_cache(now)
|
|
171
|
+
|
|
172
|
+
cache_key = _cache_key(agent_id, user_id)
|
|
173
|
+
executor = _manager_executors.get(cache_key)
|
|
174
|
+
manager_agent = _manager_agents.get(cache_key)
|
|
175
|
+
cold_start_cost = 0.0
|
|
176
|
+
|
|
177
|
+
if not executor or not manager_agent:
|
|
178
|
+
start = time.perf_counter()
|
|
179
|
+
|
|
180
|
+
# Build manager agent if not cached
|
|
181
|
+
if not manager_agent:
|
|
182
|
+
manager_agent = _build_manager_agent(agent_id, user_id)
|
|
183
|
+
_manager_agents[cache_key] = manager_agent
|
|
184
|
+
|
|
185
|
+
# Build executor if not cached
|
|
186
|
+
if not executor:
|
|
187
|
+
custom_skills = [
|
|
188
|
+
get_agent_latest_draft_skill,
|
|
189
|
+
get_agent_latest_public_info_skill,
|
|
190
|
+
update_agent_draft_skill,
|
|
191
|
+
update_public_info_skill,
|
|
192
|
+
]
|
|
193
|
+
executor = await build_agent(
|
|
194
|
+
manager_agent, AgentData(id=manager_agent.id), custom_skills
|
|
195
|
+
)
|
|
196
|
+
_manager_executors[cache_key] = executor
|
|
197
|
+
|
|
198
|
+
cold_start_cost = time.perf_counter() - start
|
|
199
|
+
_manager_cached_at[cache_key] = now
|
|
200
|
+
logger.info(
|
|
201
|
+
"Initialized manager executor for agent %s and user %s", agent_id, user_id
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
_manager_cached_at[cache_key] = now
|
|
205
|
+
|
|
206
|
+
return executor, manager_agent, cold_start_cost
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _cache_key(agent_id: str, user_id: str) -> str:
|
|
210
|
+
return f"{agent_id}:{user_id}"
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _cleanup_cache(now: datetime) -> None:
|
|
214
|
+
expired_before = now - _MANAGER_CACHE_TTL
|
|
215
|
+
for cache_key, cached_time in list(_manager_cached_at.items()):
|
|
216
|
+
if cached_time < expired_before:
|
|
217
|
+
_manager_cached_at.pop(cache_key, None)
|
|
218
|
+
_manager_executors.pop(cache_key, None)
|
|
219
|
+
_manager_agents.pop(cache_key, None)
|
|
220
|
+
logger.debug("Removed expired manager executor for %s", cache_key)
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Services for agent manager utilities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from importlib import resources
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import jsonref
|
|
11
|
+
from fastapi import status
|
|
12
|
+
|
|
13
|
+
from intentkit.models.agent import Agent, AgentPublicInfo, AgentUserInput
|
|
14
|
+
from intentkit.utils.error import IntentKitAPIError
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def agent_draft_json_schema() -> dict[str, object]:
|
|
20
|
+
"""Return AgentUserInput schema tailored for LLM draft generation."""
|
|
21
|
+
schema: dict[str, object] = AgentUserInput.model_json_schema()
|
|
22
|
+
properties: dict[str, object] = schema.get("properties", {})
|
|
23
|
+
|
|
24
|
+
fields_to_remove = {"autonomous", "frequency_penalty", "presence_penalty"}
|
|
25
|
+
for field in fields_to_remove:
|
|
26
|
+
properties.pop(field, None)
|
|
27
|
+
|
|
28
|
+
if "required" in schema and isinstance(schema["required"], list):
|
|
29
|
+
schema["required"] = [
|
|
30
|
+
field for field in schema["required"] if field not in fields_to_remove
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
skills_property = properties.get("skills")
|
|
34
|
+
if not isinstance(skills_property, dict):
|
|
35
|
+
return schema
|
|
36
|
+
|
|
37
|
+
skills_properties: dict[str, object] = {}
|
|
38
|
+
try:
|
|
39
|
+
skills_root = resources.files("intentkit.skills")
|
|
40
|
+
except (AttributeError, ModuleNotFoundError):
|
|
41
|
+
logger.warning("intentkit skills package not found when building schema")
|
|
42
|
+
return schema
|
|
43
|
+
|
|
44
|
+
for entry in skills_root.iterdir():
|
|
45
|
+
if not entry.is_dir():
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
schema_path = entry / "schema.json"
|
|
49
|
+
if not schema_path.is_file():
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
skills_properties[entry.name] = _load_skill_schema(schema_path)
|
|
54
|
+
except (
|
|
55
|
+
OSError,
|
|
56
|
+
ValueError,
|
|
57
|
+
json.JSONDecodeError,
|
|
58
|
+
jsonref.JsonRefError,
|
|
59
|
+
) as exc:
|
|
60
|
+
logger.warning("Failed to load schema for skill '%s': %s", entry.name, exc)
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
if skills_properties:
|
|
64
|
+
skills_property.setdefault("type", "object")
|
|
65
|
+
skills_property["properties"] = skills_properties
|
|
66
|
+
|
|
67
|
+
return schema
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_skills_hierarchical_text() -> str:
|
|
71
|
+
"""Extract skills organized by category and return as hierarchical text."""
|
|
72
|
+
try:
|
|
73
|
+
skills_root = resources.files("intentkit.skills")
|
|
74
|
+
except (AttributeError, ModuleNotFoundError):
|
|
75
|
+
logger.warning("intentkit skills package not found when building skills text")
|
|
76
|
+
return "No skills available"
|
|
77
|
+
|
|
78
|
+
# Group skills by category (x-tags)
|
|
79
|
+
categories: dict[str, list] = {}
|
|
80
|
+
|
|
81
|
+
for entry in skills_root.iterdir():
|
|
82
|
+
if not entry.is_dir():
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
schema_path = entry / "schema.json"
|
|
86
|
+
if not schema_path.is_file():
|
|
87
|
+
continue
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
skill_schema = _load_skill_schema(schema_path)
|
|
91
|
+
skill_name = entry.name
|
|
92
|
+
skill_title = skill_schema.get(
|
|
93
|
+
"title", skill_name.replace("_", " ").title()
|
|
94
|
+
)
|
|
95
|
+
skill_description = skill_schema.get(
|
|
96
|
+
"description", "No description available"
|
|
97
|
+
)
|
|
98
|
+
skill_tags = skill_schema.get("x-tags", ["Other"])
|
|
99
|
+
|
|
100
|
+
# Use the first tag as the primary category
|
|
101
|
+
primary_category = skill_tags[0] if skill_tags else "Other"
|
|
102
|
+
|
|
103
|
+
if primary_category not in categories:
|
|
104
|
+
categories[primary_category] = []
|
|
105
|
+
|
|
106
|
+
categories[primary_category].append(
|
|
107
|
+
{
|
|
108
|
+
"name": skill_name,
|
|
109
|
+
"title": skill_title,
|
|
110
|
+
"description": skill_description,
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
except (
|
|
115
|
+
OSError,
|
|
116
|
+
ValueError,
|
|
117
|
+
json.JSONDecodeError,
|
|
118
|
+
jsonref.JsonRefError,
|
|
119
|
+
) as exc:
|
|
120
|
+
logger.warning("Failed to load schema for skill '%s': %s", entry.name, exc)
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
# Build hierarchical text
|
|
124
|
+
text_lines = []
|
|
125
|
+
text_lines.append("Available Skills by Category:")
|
|
126
|
+
text_lines.append("")
|
|
127
|
+
|
|
128
|
+
# Sort categories alphabetically
|
|
129
|
+
for category in sorted(categories.keys()):
|
|
130
|
+
text_lines.append(f"#### {category}")
|
|
131
|
+
text_lines.append("")
|
|
132
|
+
|
|
133
|
+
# Sort skills within category alphabetically by name
|
|
134
|
+
for skill in sorted(categories[category], key=lambda x: x["name"]):
|
|
135
|
+
text_lines.append(
|
|
136
|
+
f"- **{skill['name']}** ({skill['title']}): {skill['description']}"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
text_lines.append("")
|
|
140
|
+
|
|
141
|
+
return "\n".join(text_lines)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _load_skill_schema(schema_path: Path) -> dict[str, object]:
|
|
145
|
+
base_uri = f"file://{schema_path}"
|
|
146
|
+
with schema_path.open("r", encoding="utf-8") as schema_file:
|
|
147
|
+
embedded_schema: dict[str, object] = jsonref.load(
|
|
148
|
+
schema_file, base_uri=base_uri, proxies=False, lazy_load=False
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
schema_copy = dict(embedded_schema)
|
|
152
|
+
schema_copy.setdefault("title", schema_path.parent.name.replace("_", " ").title())
|
|
153
|
+
return schema_copy
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
async def get_latest_public_info(*, agent_id: str, user_id: str) -> AgentPublicInfo:
|
|
157
|
+
"""Return the latest public information for a specific agent."""
|
|
158
|
+
|
|
159
|
+
agent = await Agent.get(agent_id)
|
|
160
|
+
if not agent:
|
|
161
|
+
raise IntentKitAPIError(
|
|
162
|
+
status.HTTP_404_NOT_FOUND, "AgentNotFound", "Agent not found"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if agent.owner != user_id:
|
|
166
|
+
raise IntentKitAPIError(
|
|
167
|
+
status.HTTP_403_FORBIDDEN,
|
|
168
|
+
"AgentForbidden",
|
|
169
|
+
"Not authorized to access this agent",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return AgentPublicInfo.model_validate(agent)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Manager skills for agent management operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Annotated, Any
|
|
7
|
+
|
|
8
|
+
from langchain_core.tools import ArgsSchema
|
|
9
|
+
from pydantic import BaseModel, SkipValidation
|
|
10
|
+
|
|
11
|
+
from intentkit.core.draft import (
|
|
12
|
+
get_agent_latest_draft,
|
|
13
|
+
update_agent_draft,
|
|
14
|
+
)
|
|
15
|
+
from intentkit.core.manager.service import (
|
|
16
|
+
agent_draft_json_schema,
|
|
17
|
+
get_latest_public_info,
|
|
18
|
+
)
|
|
19
|
+
from intentkit.models.agent import AgentPublicInfo, AgentUserInput
|
|
20
|
+
from intentkit.models.db import get_session
|
|
21
|
+
from intentkit.skills.base import IntentKitSkill
|
|
22
|
+
from intentkit.utils.error import IntentKitAPIError
|
|
23
|
+
from intentkit.utils.schema import resolve_schema_refs
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NoArgsSchema(BaseModel):
|
|
27
|
+
"""Empty schema for skills without arguments."""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class GetAgentLatestDraftSkill(IntentKitSkill):
|
|
31
|
+
"""Skill that retrieves the latest draft for the active agent."""
|
|
32
|
+
|
|
33
|
+
name: str = "get_agent_latest_draft"
|
|
34
|
+
description: str = "Fetch the latest draft for the current agent."
|
|
35
|
+
args_schema: Annotated[ArgsSchema | None, SkipValidation()] = NoArgsSchema
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def category(self) -> str:
|
|
39
|
+
return "manager"
|
|
40
|
+
|
|
41
|
+
async def _arun(self) -> str:
|
|
42
|
+
context = self.get_context()
|
|
43
|
+
if not context.user_id:
|
|
44
|
+
raise ValueError("User identifier missing from context")
|
|
45
|
+
|
|
46
|
+
async with get_session() as session:
|
|
47
|
+
draft = await get_agent_latest_draft(
|
|
48
|
+
agent_id=context.agent_id,
|
|
49
|
+
user_id=context.user_id,
|
|
50
|
+
db=session,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return json.dumps(draft.model_dump(mode="json"), indent=2)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class GetAgentLatestPublicInfoSkill(IntentKitSkill):
|
|
57
|
+
"""Skill that retrieves the latest public info for the active agent."""
|
|
58
|
+
|
|
59
|
+
name: str = "get_agent_latest_public_info"
|
|
60
|
+
description: str = "Fetch the latest public info for the current agent."
|
|
61
|
+
args_schema: Annotated[ArgsSchema | None, SkipValidation()] = NoArgsSchema
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def category(self) -> str:
|
|
65
|
+
return "manager"
|
|
66
|
+
|
|
67
|
+
async def _arun(self) -> str:
|
|
68
|
+
context = self.get_context()
|
|
69
|
+
if not context.user_id:
|
|
70
|
+
raise ValueError("User identifier missing from context")
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
public_info = await get_latest_public_info(
|
|
74
|
+
agent_id=context.agent_id,
|
|
75
|
+
user_id=context.user_id,
|
|
76
|
+
)
|
|
77
|
+
except IntentKitAPIError as exc:
|
|
78
|
+
if exc.key == "AgentNotFound":
|
|
79
|
+
return (
|
|
80
|
+
"Agent not found. Please inform the user that only deployed agents "
|
|
81
|
+
"can update public info."
|
|
82
|
+
)
|
|
83
|
+
raise
|
|
84
|
+
|
|
85
|
+
return json.dumps(public_info.model_dump(mode="json"), indent=2)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class UpdateAgentDraftSkill(IntentKitSkill):
|
|
89
|
+
"""Skill to update agent drafts with partial field updates."""
|
|
90
|
+
|
|
91
|
+
name: str = "update_agent_draft"
|
|
92
|
+
description: str = (
|
|
93
|
+
"Update the latest draft for the current agent with only the specified fields. "
|
|
94
|
+
"Only fields that are explicitly provided will be updated, leaving other fields unchanged. "
|
|
95
|
+
"This is more efficient than override and reduces the risk of accidentally changing fields."
|
|
96
|
+
)
|
|
97
|
+
args_schema: dict[str, Any] = {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"draft_update": agent_draft_json_schema(),
|
|
101
|
+
},
|
|
102
|
+
"required": ["draft_update"],
|
|
103
|
+
"additionalProperties": False,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def category(self) -> str:
|
|
108
|
+
return "manager"
|
|
109
|
+
|
|
110
|
+
async def _arun(self, **kwargs: Any) -> str:
|
|
111
|
+
context = self.get_context()
|
|
112
|
+
if not context.user_id:
|
|
113
|
+
raise ValueError("User identifier missing from context")
|
|
114
|
+
|
|
115
|
+
if "draft_update" not in kwargs:
|
|
116
|
+
raise ValueError("Missing required argument 'draft_update'")
|
|
117
|
+
|
|
118
|
+
input_model = AgentUserInput.model_validate(kwargs["draft_update"])
|
|
119
|
+
|
|
120
|
+
async with get_session() as session:
|
|
121
|
+
draft = await update_agent_draft(
|
|
122
|
+
agent_id=context.agent_id,
|
|
123
|
+
user_id=context.user_id,
|
|
124
|
+
input=input_model,
|
|
125
|
+
db=session,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return json.dumps(draft.model_dump(mode="json"), indent=2)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class UpdatePublicInfoSkill(IntentKitSkill):
|
|
132
|
+
"""Skill to update the public info of an agent with partial field updates."""
|
|
133
|
+
|
|
134
|
+
name: str = "update_public_info"
|
|
135
|
+
description: str = (
|
|
136
|
+
"Update the public info for a deployed agent with only the specified fields. "
|
|
137
|
+
"Only fields that are explicitly provided will be updated, leaving other fields unchanged. "
|
|
138
|
+
"This is more efficient than override and reduces the risk of accidentally changing fields. "
|
|
139
|
+
"Always review the latest public info before making changes."
|
|
140
|
+
)
|
|
141
|
+
args_schema: dict[str, Any] = {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"properties": {
|
|
144
|
+
"public_info_update": resolve_schema_refs(
|
|
145
|
+
AgentPublicInfo.model_json_schema()
|
|
146
|
+
),
|
|
147
|
+
},
|
|
148
|
+
"required": ["public_info_update"],
|
|
149
|
+
"additionalProperties": False,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def category(self) -> str:
|
|
154
|
+
return "manager"
|
|
155
|
+
|
|
156
|
+
async def _arun(self, **kwargs: Any) -> str:
|
|
157
|
+
context = self.get_context()
|
|
158
|
+
if not context.user_id:
|
|
159
|
+
raise ValueError("User identifier missing from context")
|
|
160
|
+
|
|
161
|
+
if "public_info_update" not in kwargs:
|
|
162
|
+
raise ValueError("Missing required argument 'public_info_update'")
|
|
163
|
+
|
|
164
|
+
# Ensure the agent exists and belongs to the current user
|
|
165
|
+
await get_latest_public_info(agent_id=context.agent_id, user_id=context.user_id)
|
|
166
|
+
|
|
167
|
+
public_info = AgentPublicInfo.model_validate(kwargs["public_info_update"])
|
|
168
|
+
updated_agent = await public_info.update(context.agent_id)
|
|
169
|
+
updated_public_info = AgentPublicInfo.model_validate(updated_agent)
|
|
170
|
+
|
|
171
|
+
return json.dumps(updated_public_info.model_dump(mode="json"), indent=2)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# Shared skill instances to avoid repeated instantiation
|
|
175
|
+
get_agent_latest_draft_skill = GetAgentLatestDraftSkill()
|
|
176
|
+
get_agent_latest_public_info_skill = GetAgentLatestPublicInfoSkill()
|
|
177
|
+
update_agent_draft_skill = UpdateAgentDraftSkill()
|
|
178
|
+
update_public_info_skill = UpdatePublicInfoSkill()
|