intentkit 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +17 -0
- intentkit/abstracts/__init__.py +0 -0
- intentkit/abstracts/agent.py +60 -0
- intentkit/abstracts/api.py +4 -0
- intentkit/abstracts/engine.py +38 -0
- intentkit/abstracts/exception.py +9 -0
- intentkit/abstracts/graph.py +25 -0
- intentkit/abstracts/skill.py +129 -0
- intentkit/abstracts/twitter.py +54 -0
- intentkit/clients/__init__.py +14 -0
- intentkit/clients/cdp.py +53 -0
- intentkit/clients/twitter.py +445 -0
- intentkit/config/__init__.py +0 -0
- intentkit/config/config.py +164 -0
- intentkit/core/__init__.py +0 -0
- intentkit/core/agent.py +191 -0
- intentkit/core/api.py +40 -0
- intentkit/core/client.py +45 -0
- intentkit/core/credit.py +1767 -0
- intentkit/core/engine.py +1018 -0
- intentkit/core/node.py +223 -0
- intentkit/core/prompt.py +58 -0
- intentkit/core/skill.py +124 -0
- intentkit/models/agent.py +1689 -0
- intentkit/models/agent_data.py +810 -0
- intentkit/models/agent_schema.json +733 -0
- intentkit/models/app_setting.py +156 -0
- intentkit/models/base.py +9 -0
- intentkit/models/chat.py +581 -0
- intentkit/models/conversation.py +286 -0
- intentkit/models/credit.py +1406 -0
- intentkit/models/db.py +120 -0
- intentkit/models/db_mig.py +102 -0
- intentkit/models/generator.py +347 -0
- intentkit/models/llm.py +746 -0
- intentkit/models/redis.py +132 -0
- intentkit/models/skill.py +466 -0
- intentkit/models/user.py +243 -0
- intentkit/skills/__init__.py +12 -0
- intentkit/skills/acolyt/__init__.py +83 -0
- intentkit/skills/acolyt/acolyt.jpg +0 -0
- intentkit/skills/acolyt/ask.py +128 -0
- intentkit/skills/acolyt/base.py +28 -0
- intentkit/skills/acolyt/schema.json +89 -0
- intentkit/skills/aixbt/README.md +71 -0
- intentkit/skills/aixbt/__init__.py +73 -0
- intentkit/skills/aixbt/aixbt.jpg +0 -0
- intentkit/skills/aixbt/base.py +21 -0
- intentkit/skills/aixbt/projects.py +153 -0
- intentkit/skills/aixbt/schema.json +99 -0
- intentkit/skills/allora/__init__.py +83 -0
- intentkit/skills/allora/allora.jpeg +0 -0
- intentkit/skills/allora/base.py +28 -0
- intentkit/skills/allora/price.py +130 -0
- intentkit/skills/allora/schema.json +89 -0
- intentkit/skills/base.py +174 -0
- intentkit/skills/carv/README.md +95 -0
- intentkit/skills/carv/__init__.py +121 -0
- intentkit/skills/carv/base.py +183 -0
- intentkit/skills/carv/carv.webp +0 -0
- intentkit/skills/carv/fetch_news.py +92 -0
- intentkit/skills/carv/onchain_query.py +164 -0
- intentkit/skills/carv/schema.json +137 -0
- intentkit/skills/carv/token_info_and_price.py +110 -0
- intentkit/skills/cdp/__init__.py +137 -0
- intentkit/skills/cdp/base.py +21 -0
- intentkit/skills/cdp/cdp.png +0 -0
- intentkit/skills/cdp/get_balance.py +81 -0
- intentkit/skills/cdp/schema.json +473 -0
- intentkit/skills/chainlist/README.md +38 -0
- intentkit/skills/chainlist/__init__.py +54 -0
- intentkit/skills/chainlist/base.py +21 -0
- intentkit/skills/chainlist/chain_lookup.py +208 -0
- intentkit/skills/chainlist/chainlist.png +0 -0
- intentkit/skills/chainlist/schema.json +47 -0
- intentkit/skills/common/__init__.py +82 -0
- intentkit/skills/common/base.py +21 -0
- intentkit/skills/common/common.jpg +0 -0
- intentkit/skills/common/current_time.py +84 -0
- intentkit/skills/common/schema.json +57 -0
- intentkit/skills/cookiefun/README.md +121 -0
- intentkit/skills/cookiefun/__init__.py +78 -0
- intentkit/skills/cookiefun/base.py +41 -0
- intentkit/skills/cookiefun/constants.py +18 -0
- intentkit/skills/cookiefun/cookiefun.png +0 -0
- intentkit/skills/cookiefun/get_account_details.py +171 -0
- intentkit/skills/cookiefun/get_account_feed.py +282 -0
- intentkit/skills/cookiefun/get_account_smart_followers.py +181 -0
- intentkit/skills/cookiefun/get_sectors.py +128 -0
- intentkit/skills/cookiefun/schema.json +155 -0
- intentkit/skills/cookiefun/search_accounts.py +225 -0
- intentkit/skills/cryptocompare/__init__.py +130 -0
- intentkit/skills/cryptocompare/api.py +159 -0
- intentkit/skills/cryptocompare/base.py +303 -0
- intentkit/skills/cryptocompare/cryptocompare.png +0 -0
- intentkit/skills/cryptocompare/fetch_news.py +96 -0
- intentkit/skills/cryptocompare/fetch_price.py +99 -0
- intentkit/skills/cryptocompare/fetch_top_exchanges.py +113 -0
- intentkit/skills/cryptocompare/fetch_top_market_cap.py +109 -0
- intentkit/skills/cryptocompare/fetch_top_volume.py +108 -0
- intentkit/skills/cryptocompare/fetch_trading_signals.py +107 -0
- intentkit/skills/cryptocompare/schema.json +168 -0
- intentkit/skills/cryptopanic/__init__.py +108 -0
- intentkit/skills/cryptopanic/base.py +51 -0
- intentkit/skills/cryptopanic/cryptopanic.png +0 -0
- intentkit/skills/cryptopanic/fetch_crypto_news.py +153 -0
- intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +136 -0
- intentkit/skills/cryptopanic/schema.json +103 -0
- intentkit/skills/dapplooker/README.md +92 -0
- intentkit/skills/dapplooker/__init__.py +83 -0
- intentkit/skills/dapplooker/base.py +26 -0
- intentkit/skills/dapplooker/dapplooker.jpg +0 -0
- intentkit/skills/dapplooker/dapplooker_token_data.py +476 -0
- intentkit/skills/dapplooker/schema.json +91 -0
- intentkit/skills/defillama/__init__.py +323 -0
- intentkit/skills/defillama/api.py +315 -0
- intentkit/skills/defillama/base.py +135 -0
- intentkit/skills/defillama/coins/__init__.py +0 -0
- intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +116 -0
- intentkit/skills/defillama/coins/fetch_block.py +98 -0
- intentkit/skills/defillama/coins/fetch_current_prices.py +105 -0
- intentkit/skills/defillama/coins/fetch_first_price.py +100 -0
- intentkit/skills/defillama/coins/fetch_historical_prices.py +110 -0
- intentkit/skills/defillama/coins/fetch_price_chart.py +109 -0
- intentkit/skills/defillama/coins/fetch_price_percentage.py +93 -0
- intentkit/skills/defillama/config/__init__.py +0 -0
- intentkit/skills/defillama/config/chains.py +433 -0
- intentkit/skills/defillama/defillama.jpeg +0 -0
- intentkit/skills/defillama/fees/__init__.py +0 -0
- intentkit/skills/defillama/fees/fetch_fees_overview.py +130 -0
- intentkit/skills/defillama/schema.json +383 -0
- intentkit/skills/defillama/stablecoins/__init__.py +0 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +100 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +129 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +83 -0
- intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +126 -0
- intentkit/skills/defillama/tests/__init__.py +0 -0
- intentkit/skills/defillama/tests/api_integration.test.py +192 -0
- intentkit/skills/defillama/tests/api_unit.test.py +583 -0
- intentkit/skills/defillama/tvl/__init__.py +0 -0
- intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +106 -0
- intentkit/skills/defillama/tvl/fetch_chains.py +107 -0
- intentkit/skills/defillama/tvl/fetch_historical_tvl.py +91 -0
- intentkit/skills/defillama/tvl/fetch_protocol.py +207 -0
- intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +93 -0
- intentkit/skills/defillama/tvl/fetch_protocols.py +196 -0
- intentkit/skills/defillama/volumes/__init__.py +0 -0
- intentkit/skills/defillama/volumes/fetch_dex_overview.py +157 -0
- intentkit/skills/defillama/volumes/fetch_dex_summary.py +123 -0
- intentkit/skills/defillama/volumes/fetch_options_overview.py +131 -0
- intentkit/skills/defillama/yields/__init__.py +0 -0
- intentkit/skills/defillama/yields/fetch_pool_chart.py +100 -0
- intentkit/skills/defillama/yields/fetch_pools.py +126 -0
- intentkit/skills/dexscreener/__init__.py +93 -0
- intentkit/skills/dexscreener/base.py +133 -0
- intentkit/skills/dexscreener/dexscreener.png +0 -0
- intentkit/skills/dexscreener/model/__init__.py +0 -0
- intentkit/skills/dexscreener/model/search_token_response.py +82 -0
- intentkit/skills/dexscreener/schema.json +48 -0
- intentkit/skills/dexscreener/search_token.py +321 -0
- intentkit/skills/dune_analytics/__init__.py +103 -0
- intentkit/skills/dune_analytics/base.py +46 -0
- intentkit/skills/dune_analytics/dune.png +0 -0
- intentkit/skills/dune_analytics/fetch_kol_buys.py +128 -0
- intentkit/skills/dune_analytics/fetch_nation_metrics.py +237 -0
- intentkit/skills/dune_analytics/schema.json +99 -0
- intentkit/skills/elfa/README.md +100 -0
- intentkit/skills/elfa/__init__.py +123 -0
- intentkit/skills/elfa/base.py +28 -0
- intentkit/skills/elfa/elfa.jpg +0 -0
- intentkit/skills/elfa/mention.py +504 -0
- intentkit/skills/elfa/schema.json +153 -0
- intentkit/skills/elfa/stats.py +118 -0
- intentkit/skills/elfa/tokens.py +126 -0
- intentkit/skills/enso/README.md +75 -0
- intentkit/skills/enso/__init__.py +114 -0
- intentkit/skills/enso/abi/__init__.py +0 -0
- intentkit/skills/enso/abi/approval.py +279 -0
- intentkit/skills/enso/abi/erc20.py +14 -0
- intentkit/skills/enso/abi/route.py +129 -0
- intentkit/skills/enso/base.py +44 -0
- intentkit/skills/enso/best_yield.py +286 -0
- intentkit/skills/enso/enso.jpg +0 -0
- intentkit/skills/enso/networks.py +105 -0
- intentkit/skills/enso/prices.py +93 -0
- intentkit/skills/enso/route.py +300 -0
- intentkit/skills/enso/schema.json +212 -0
- intentkit/skills/enso/tokens.py +223 -0
- intentkit/skills/enso/wallet.py +381 -0
- intentkit/skills/github/README.md +63 -0
- intentkit/skills/github/__init__.py +54 -0
- intentkit/skills/github/base.py +21 -0
- intentkit/skills/github/github.jpg +0 -0
- intentkit/skills/github/github_search.py +183 -0
- intentkit/skills/github/schema.json +59 -0
- intentkit/skills/heurist/__init__.py +143 -0
- intentkit/skills/heurist/base.py +26 -0
- intentkit/skills/heurist/heurist.png +0 -0
- intentkit/skills/heurist/image_generation_animagine_xl.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_comics.py +162 -0
- intentkit/skills/heurist/image_generation_arthemy_real.py +162 -0
- intentkit/skills/heurist/image_generation_braindance.py +162 -0
- intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +162 -0
- intentkit/skills/heurist/image_generation_flux_1_dev.py +162 -0
- intentkit/skills/heurist/image_generation_sdxl.py +161 -0
- intentkit/skills/heurist/schema.json +196 -0
- intentkit/skills/lifi/README.md +294 -0
- intentkit/skills/lifi/__init__.py +141 -0
- intentkit/skills/lifi/base.py +21 -0
- intentkit/skills/lifi/lifi.png +0 -0
- intentkit/skills/lifi/schema.json +89 -0
- intentkit/skills/lifi/token_execute.py +472 -0
- intentkit/skills/lifi/token_quote.py +190 -0
- intentkit/skills/lifi/utils.py +656 -0
- intentkit/skills/moralis/README.md +490 -0
- intentkit/skills/moralis/__init__.py +110 -0
- intentkit/skills/moralis/api.py +281 -0
- intentkit/skills/moralis/base.py +55 -0
- intentkit/skills/moralis/fetch_chain_portfolio.py +191 -0
- intentkit/skills/moralis/fetch_nft_portfolio.py +284 -0
- intentkit/skills/moralis/fetch_solana_portfolio.py +331 -0
- intentkit/skills/moralis/fetch_wallet_portfolio.py +301 -0
- intentkit/skills/moralis/moralis.png +0 -0
- intentkit/skills/moralis/schema.json +156 -0
- intentkit/skills/moralis/tests/__init__.py +0 -0
- intentkit/skills/moralis/tests/test_wallet.py +511 -0
- intentkit/skills/nation/__init__.py +62 -0
- intentkit/skills/nation/base.py +31 -0
- intentkit/skills/nation/nation.png +0 -0
- intentkit/skills/nation/nft_check.py +106 -0
- intentkit/skills/nation/schema.json +58 -0
- intentkit/skills/openai/__init__.py +107 -0
- intentkit/skills/openai/base.py +32 -0
- intentkit/skills/openai/dalle_image_generation.py +128 -0
- intentkit/skills/openai/gpt_image_generation.py +152 -0
- intentkit/skills/openai/gpt_image_to_image.py +186 -0
- intentkit/skills/openai/image_to_text.py +126 -0
- intentkit/skills/openai/openai.png +0 -0
- intentkit/skills/openai/schema.json +139 -0
- intentkit/skills/portfolio/README.md +55 -0
- intentkit/skills/portfolio/__init__.py +151 -0
- intentkit/skills/portfolio/base.py +107 -0
- intentkit/skills/portfolio/constants.py +9 -0
- intentkit/skills/portfolio/moralis.png +0 -0
- intentkit/skills/portfolio/schema.json +237 -0
- intentkit/skills/portfolio/token_balances.py +155 -0
- intentkit/skills/portfolio/wallet_approvals.py +102 -0
- intentkit/skills/portfolio/wallet_defi_positions.py +80 -0
- intentkit/skills/portfolio/wallet_history.py +155 -0
- intentkit/skills/portfolio/wallet_net_worth.py +112 -0
- intentkit/skills/portfolio/wallet_nfts.py +139 -0
- intentkit/skills/portfolio/wallet_profitability.py +101 -0
- intentkit/skills/portfolio/wallet_profitability_summary.py +91 -0
- intentkit/skills/portfolio/wallet_stats.py +79 -0
- intentkit/skills/portfolio/wallet_swaps.py +147 -0
- intentkit/skills/skills.toml +103 -0
- intentkit/skills/slack/__init__.py +98 -0
- intentkit/skills/slack/base.py +55 -0
- intentkit/skills/slack/get_channel.py +109 -0
- intentkit/skills/slack/get_message.py +136 -0
- intentkit/skills/slack/schedule_message.py +92 -0
- intentkit/skills/slack/schema.json +135 -0
- intentkit/skills/slack/send_message.py +81 -0
- intentkit/skills/slack/slack.jpg +0 -0
- intentkit/skills/system/__init__.py +90 -0
- intentkit/skills/system/base.py +22 -0
- intentkit/skills/system/read_agent_api_key.py +87 -0
- intentkit/skills/system/regenerate_agent_api_key.py +77 -0
- intentkit/skills/system/schema.json +53 -0
- intentkit/skills/system/system.svg +76 -0
- intentkit/skills/tavily/README.md +86 -0
- intentkit/skills/tavily/__init__.py +91 -0
- intentkit/skills/tavily/base.py +27 -0
- intentkit/skills/tavily/schema.json +119 -0
- intentkit/skills/tavily/tavily.jpg +0 -0
- intentkit/skills/tavily/tavily_extract.py +147 -0
- intentkit/skills/tavily/tavily_search.py +139 -0
- intentkit/skills/token/README.md +89 -0
- intentkit/skills/token/__init__.py +107 -0
- intentkit/skills/token/base.py +154 -0
- intentkit/skills/token/constants.py +9 -0
- intentkit/skills/token/erc20_transfers.py +145 -0
- intentkit/skills/token/moralis.png +0 -0
- intentkit/skills/token/schema.json +141 -0
- intentkit/skills/token/token_analytics.py +81 -0
- intentkit/skills/token/token_price.py +132 -0
- intentkit/skills/token/token_search.py +121 -0
- intentkit/skills/twitter/__init__.py +146 -0
- intentkit/skills/twitter/base.py +68 -0
- intentkit/skills/twitter/follow_user.py +69 -0
- intentkit/skills/twitter/get_mentions.py +124 -0
- intentkit/skills/twitter/get_timeline.py +111 -0
- intentkit/skills/twitter/get_user_by_username.py +84 -0
- intentkit/skills/twitter/get_user_tweets.py +123 -0
- intentkit/skills/twitter/like_tweet.py +65 -0
- intentkit/skills/twitter/post_tweet.py +90 -0
- intentkit/skills/twitter/reply_tweet.py +98 -0
- intentkit/skills/twitter/retweet.py +76 -0
- intentkit/skills/twitter/schema.json +258 -0
- intentkit/skills/twitter/search_tweets.py +115 -0
- intentkit/skills/twitter/twitter.png +0 -0
- intentkit/skills/unrealspeech/__init__.py +55 -0
- intentkit/skills/unrealspeech/base.py +21 -0
- intentkit/skills/unrealspeech/schema.json +100 -0
- intentkit/skills/unrealspeech/text_to_speech.py +177 -0
- intentkit/skills/unrealspeech/unrealspeech.jpg +0 -0
- intentkit/skills/venice_audio/__init__.py +106 -0
- intentkit/skills/venice_audio/base.py +119 -0
- intentkit/skills/venice_audio/input.py +41 -0
- intentkit/skills/venice_audio/schema.json +152 -0
- intentkit/skills/venice_audio/venice_audio.py +240 -0
- intentkit/skills/venice_audio/venice_logo.jpg +0 -0
- intentkit/skills/venice_image/README.md +119 -0
- intentkit/skills/venice_image/__init__.py +154 -0
- intentkit/skills/venice_image/api.py +138 -0
- intentkit/skills/venice_image/base.py +188 -0
- intentkit/skills/venice_image/config.py +35 -0
- intentkit/skills/venice_image/image_enhance/README.md +119 -0
- intentkit/skills/venice_image/image_enhance/__init__.py +0 -0
- intentkit/skills/venice_image/image_enhance/image_enhance.py +80 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_base.py +23 -0
- intentkit/skills/venice_image/image_enhance/image_enhance_input.py +40 -0
- intentkit/skills/venice_image/image_generation/README.md +144 -0
- intentkit/skills/venice_image/image_generation/__init__.py +0 -0
- intentkit/skills/venice_image/image_generation/image_generation_base.py +117 -0
- intentkit/skills/venice_image/image_generation/image_generation_fluently_xl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev.py +27 -0
- intentkit/skills/venice_image/image_generation/image_generation_flux_dev_uncensored.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_input.py +158 -0
- intentkit/skills/venice_image/image_generation/image_generation_lustify_sdxl.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_pony_realism.py +26 -0
- intentkit/skills/venice_image/image_generation/image_generation_stable_diffusion_3_5.py +28 -0
- intentkit/skills/venice_image/image_generation/image_generation_venice_sd35.py +28 -0
- intentkit/skills/venice_image/image_upscale/README.md +111 -0
- intentkit/skills/venice_image/image_upscale/__init__.py +0 -0
- intentkit/skills/venice_image/image_upscale/image_upscale.py +90 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_base.py +23 -0
- intentkit/skills/venice_image/image_upscale/image_upscale_input.py +22 -0
- intentkit/skills/venice_image/image_vision/README.md +112 -0
- intentkit/skills/venice_image/image_vision/__init__.py +0 -0
- intentkit/skills/venice_image/image_vision/image_vision.py +100 -0
- intentkit/skills/venice_image/image_vision/image_vision_base.py +17 -0
- intentkit/skills/venice_image/image_vision/image_vision_input.py +9 -0
- intentkit/skills/venice_image/schema.json +267 -0
- intentkit/skills/venice_image/utils.py +78 -0
- intentkit/skills/venice_image/venice_image.jpg +0 -0
- intentkit/skills/web_scraper/README.md +82 -0
- intentkit/skills/web_scraper/__init__.py +92 -0
- intentkit/skills/web_scraper/base.py +21 -0
- intentkit/skills/web_scraper/langchain.png +0 -0
- intentkit/skills/web_scraper/schema.json +115 -0
- intentkit/skills/web_scraper/scrape_and_index.py +327 -0
- intentkit/utils/__init__.py +1 -0
- intentkit/utils/chain.py +436 -0
- intentkit/utils/error.py +134 -0
- intentkit/utils/logging.py +70 -0
- intentkit/utils/middleware.py +61 -0
- intentkit/utils/random.py +16 -0
- intentkit/utils/s3.py +267 -0
- intentkit/utils/slack_alert.py +79 -0
- intentkit/utils/tx.py +37 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/METADATA +1 -1
- intentkit-0.5.2.dist-info/RECORD +365 -0
- intentkit-0.5.0.dist-info/RECORD +0 -4
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/WHEEL +0 -0
- {intentkit-0.5.0.dist-info → intentkit-0.5.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,810 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from typing import Annotated, Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
from fastapi import HTTPException
|
|
7
|
+
from intentkit.models.base import Base
|
|
8
|
+
from intentkit.models.db import get_session
|
|
9
|
+
from pydantic import BaseModel, ConfigDict
|
|
10
|
+
from pydantic import Field as PydanticField
|
|
11
|
+
from sqlalchemy import (
|
|
12
|
+
BigInteger,
|
|
13
|
+
Boolean,
|
|
14
|
+
Column,
|
|
15
|
+
DateTime,
|
|
16
|
+
Numeric,
|
|
17
|
+
String,
|
|
18
|
+
func,
|
|
19
|
+
select,
|
|
20
|
+
)
|
|
21
|
+
from sqlalchemy.dialects.postgresql import JSON, JSONB
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AgentDataTable(Base):
|
|
27
|
+
"""Agent data model for database storage of additional data related to the agent."""
|
|
28
|
+
|
|
29
|
+
__tablename__ = "agent_data"
|
|
30
|
+
|
|
31
|
+
id = Column(String, primary_key=True, comment="Same as Agent.id")
|
|
32
|
+
cdp_wallet_data = Column(String, nullable=True, comment="CDP wallet data")
|
|
33
|
+
crossmint_wallet_data = Column(
|
|
34
|
+
JSON().with_variant(JSONB(), "postgresql"),
|
|
35
|
+
nullable=True,
|
|
36
|
+
comment="Crossmint wallet information",
|
|
37
|
+
)
|
|
38
|
+
twitter_id = Column(String, nullable=True, comment="Twitter user ID")
|
|
39
|
+
twitter_username = Column(String, nullable=True, comment="Twitter username")
|
|
40
|
+
twitter_name = Column(String, nullable=True, comment="Twitter display name")
|
|
41
|
+
twitter_access_token = Column(String, nullable=True, comment="Twitter access token")
|
|
42
|
+
twitter_access_token_expires_at = Column(
|
|
43
|
+
DateTime(timezone=True),
|
|
44
|
+
nullable=True,
|
|
45
|
+
comment="Twitter access token expiration time",
|
|
46
|
+
)
|
|
47
|
+
twitter_refresh_token = Column(
|
|
48
|
+
String, nullable=True, comment="Twitter refresh token"
|
|
49
|
+
)
|
|
50
|
+
twitter_self_key_refreshed_at = Column(
|
|
51
|
+
DateTime(timezone=True),
|
|
52
|
+
nullable=True,
|
|
53
|
+
comment="Twitter self-key userinfo last refresh time",
|
|
54
|
+
)
|
|
55
|
+
twitter_is_verified = Column(
|
|
56
|
+
Boolean,
|
|
57
|
+
nullable=False,
|
|
58
|
+
default=False,
|
|
59
|
+
comment="Whether the Twitter account is verified",
|
|
60
|
+
)
|
|
61
|
+
telegram_id = Column(String, nullable=True, comment="Telegram user ID")
|
|
62
|
+
telegram_username = Column(String, nullable=True, comment="Telegram username")
|
|
63
|
+
telegram_name = Column(String, nullable=True, comment="Telegram display name")
|
|
64
|
+
error_message = Column(String, nullable=True, comment="Last error message")
|
|
65
|
+
api_key = Column(
|
|
66
|
+
String, nullable=True, unique=True, comment="API key for the agent"
|
|
67
|
+
)
|
|
68
|
+
api_key_public = Column(
|
|
69
|
+
String, nullable=True, unique=True, comment="Public API key for the agent"
|
|
70
|
+
)
|
|
71
|
+
created_at = Column(
|
|
72
|
+
DateTime(timezone=True),
|
|
73
|
+
nullable=False,
|
|
74
|
+
server_default=func.now(),
|
|
75
|
+
comment="Timestamp when the agent data was created",
|
|
76
|
+
)
|
|
77
|
+
updated_at = Column(
|
|
78
|
+
DateTime(timezone=True),
|
|
79
|
+
nullable=False,
|
|
80
|
+
server_default=func.now(),
|
|
81
|
+
onupdate=lambda: datetime.now(timezone.utc),
|
|
82
|
+
comment="Timestamp when the agent data was last updated",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class AgentData(BaseModel):
|
|
87
|
+
"""Agent data model for storing additional data related to the agent."""
|
|
88
|
+
|
|
89
|
+
model_config = ConfigDict(from_attributes=True)
|
|
90
|
+
|
|
91
|
+
id: Annotated[
|
|
92
|
+
str,
|
|
93
|
+
PydanticField(
|
|
94
|
+
description="Same as Agent.id",
|
|
95
|
+
),
|
|
96
|
+
]
|
|
97
|
+
cdp_wallet_data: Annotated[
|
|
98
|
+
Optional[str],
|
|
99
|
+
PydanticField(
|
|
100
|
+
default=None,
|
|
101
|
+
description="CDP wallet data",
|
|
102
|
+
),
|
|
103
|
+
]
|
|
104
|
+
crossmint_wallet_data: Annotated[
|
|
105
|
+
Optional[dict],
|
|
106
|
+
PydanticField(
|
|
107
|
+
default=None,
|
|
108
|
+
description="Crossmint wallet information",
|
|
109
|
+
),
|
|
110
|
+
]
|
|
111
|
+
twitter_id: Annotated[
|
|
112
|
+
Optional[str],
|
|
113
|
+
PydanticField(
|
|
114
|
+
default=None,
|
|
115
|
+
description="Twitter user ID",
|
|
116
|
+
),
|
|
117
|
+
]
|
|
118
|
+
twitter_username: Annotated[
|
|
119
|
+
Optional[str],
|
|
120
|
+
PydanticField(
|
|
121
|
+
default=None,
|
|
122
|
+
description="Twitter username",
|
|
123
|
+
),
|
|
124
|
+
]
|
|
125
|
+
twitter_name: Annotated[
|
|
126
|
+
Optional[str],
|
|
127
|
+
PydanticField(
|
|
128
|
+
default=None,
|
|
129
|
+
description="Twitter display name",
|
|
130
|
+
),
|
|
131
|
+
]
|
|
132
|
+
twitter_access_token: Annotated[
|
|
133
|
+
Optional[str],
|
|
134
|
+
PydanticField(
|
|
135
|
+
default=None,
|
|
136
|
+
description="Twitter access token",
|
|
137
|
+
),
|
|
138
|
+
]
|
|
139
|
+
twitter_access_token_expires_at: Annotated[
|
|
140
|
+
Optional[datetime],
|
|
141
|
+
PydanticField(
|
|
142
|
+
default=None,
|
|
143
|
+
description="Twitter access token expiration time",
|
|
144
|
+
),
|
|
145
|
+
]
|
|
146
|
+
twitter_refresh_token: Annotated[
|
|
147
|
+
Optional[str],
|
|
148
|
+
PydanticField(
|
|
149
|
+
default=None,
|
|
150
|
+
description="Twitter refresh token",
|
|
151
|
+
),
|
|
152
|
+
]
|
|
153
|
+
twitter_self_key_refreshed_at: Annotated[
|
|
154
|
+
Optional[datetime],
|
|
155
|
+
PydanticField(
|
|
156
|
+
default=None,
|
|
157
|
+
description="Twitter self-key userinfo last refresh time",
|
|
158
|
+
),
|
|
159
|
+
]
|
|
160
|
+
twitter_is_verified: Annotated[
|
|
161
|
+
bool,
|
|
162
|
+
PydanticField(
|
|
163
|
+
default=False,
|
|
164
|
+
description="Whether the Twitter account is verified",
|
|
165
|
+
),
|
|
166
|
+
]
|
|
167
|
+
telegram_id: Annotated[
|
|
168
|
+
Optional[str],
|
|
169
|
+
PydanticField(
|
|
170
|
+
default=None,
|
|
171
|
+
description="Telegram user ID",
|
|
172
|
+
),
|
|
173
|
+
]
|
|
174
|
+
telegram_username: Annotated[
|
|
175
|
+
Optional[str],
|
|
176
|
+
PydanticField(
|
|
177
|
+
default=None,
|
|
178
|
+
description="Telegram username",
|
|
179
|
+
),
|
|
180
|
+
]
|
|
181
|
+
telegram_name: Annotated[
|
|
182
|
+
Optional[str],
|
|
183
|
+
PydanticField(
|
|
184
|
+
default=None,
|
|
185
|
+
description="Telegram display name",
|
|
186
|
+
),
|
|
187
|
+
]
|
|
188
|
+
error_message: Annotated[
|
|
189
|
+
Optional[str],
|
|
190
|
+
PydanticField(
|
|
191
|
+
default=None,
|
|
192
|
+
description="Last error message",
|
|
193
|
+
),
|
|
194
|
+
]
|
|
195
|
+
api_key: Annotated[
|
|
196
|
+
Optional[str],
|
|
197
|
+
PydanticField(
|
|
198
|
+
default=None,
|
|
199
|
+
description="API key for the agent",
|
|
200
|
+
),
|
|
201
|
+
]
|
|
202
|
+
api_key_public: Annotated[
|
|
203
|
+
Optional[str],
|
|
204
|
+
PydanticField(
|
|
205
|
+
default=None,
|
|
206
|
+
description="Public API key for the agent",
|
|
207
|
+
),
|
|
208
|
+
]
|
|
209
|
+
created_at: Annotated[
|
|
210
|
+
datetime,
|
|
211
|
+
PydanticField(
|
|
212
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
213
|
+
description="Timestamp when the agent data was created",
|
|
214
|
+
),
|
|
215
|
+
]
|
|
216
|
+
updated_at: Annotated[
|
|
217
|
+
datetime,
|
|
218
|
+
PydanticField(
|
|
219
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
220
|
+
description="Timestamp when the agent data was last updated",
|
|
221
|
+
),
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
async def get(cls, agent_id: str) -> Optional["AgentData"]:
|
|
226
|
+
"""Get agent data by ID.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
agent_id: Agent ID
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
AgentData if found, None otherwise
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
HTTPException: If there are database errors
|
|
236
|
+
"""
|
|
237
|
+
async with get_session() as db:
|
|
238
|
+
item = await db.get(AgentDataTable, agent_id)
|
|
239
|
+
if item:
|
|
240
|
+
return cls.model_validate(item)
|
|
241
|
+
return cls.model_construct(id=agent_id)
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
async def get_by_api_key(cls, api_key: str) -> Optional["AgentData"]:
|
|
245
|
+
"""Get agent data by API key.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
api_key: API key (sk- for private, pk- for public)
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
AgentData if found, None otherwise
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
HTTPException: If there are database errors
|
|
255
|
+
"""
|
|
256
|
+
async with get_session() as db:
|
|
257
|
+
if api_key.startswith("sk-"):
|
|
258
|
+
# Search in api_key field for private keys
|
|
259
|
+
result = await db.execute(
|
|
260
|
+
select(AgentDataTable).where(AgentDataTable.api_key == api_key)
|
|
261
|
+
)
|
|
262
|
+
elif api_key.startswith("pk-"):
|
|
263
|
+
# Search in api_key_public field for public keys
|
|
264
|
+
result = await db.execute(
|
|
265
|
+
select(AgentDataTable).where(
|
|
266
|
+
AgentDataTable.api_key_public == api_key
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
else:
|
|
270
|
+
# Invalid key format
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
item = result.scalar_one_or_none()
|
|
274
|
+
if item:
|
|
275
|
+
return cls.model_validate(item)
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
async def save(self) -> None:
|
|
279
|
+
"""Save or update agent data.
|
|
280
|
+
|
|
281
|
+
Raises:
|
|
282
|
+
HTTPException: If there are database errors
|
|
283
|
+
"""
|
|
284
|
+
async with get_session() as db:
|
|
285
|
+
existing = await db.get(AgentDataTable, self.id)
|
|
286
|
+
if existing:
|
|
287
|
+
# Update existing record
|
|
288
|
+
for field, value in self.model_dump(exclude_unset=True).items():
|
|
289
|
+
setattr(existing, field, value)
|
|
290
|
+
db.add(existing)
|
|
291
|
+
else:
|
|
292
|
+
# Create new record
|
|
293
|
+
db_agent_data = AgentDataTable(**self.model_dump())
|
|
294
|
+
db.add(db_agent_data)
|
|
295
|
+
|
|
296
|
+
await db.commit()
|
|
297
|
+
|
|
298
|
+
@staticmethod
|
|
299
|
+
async def patch(id: str, data: dict) -> "AgentData":
|
|
300
|
+
"""Update agent data.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
id: ID of the agent
|
|
304
|
+
data: Dictionary containing fields to update
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Updated agent data
|
|
308
|
+
|
|
309
|
+
Raises:
|
|
310
|
+
HTTPException: If there are database errors
|
|
311
|
+
"""
|
|
312
|
+
async with get_session() as db:
|
|
313
|
+
agent_data = await db.get(AgentDataTable, id)
|
|
314
|
+
if not agent_data:
|
|
315
|
+
agent_data = AgentDataTable(id=id, **data)
|
|
316
|
+
db.add(agent_data)
|
|
317
|
+
else:
|
|
318
|
+
for key, value in data.items():
|
|
319
|
+
setattr(agent_data, key, value)
|
|
320
|
+
await db.commit()
|
|
321
|
+
await db.refresh(agent_data)
|
|
322
|
+
return AgentData.model_validate(agent_data)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class AgentPluginDataTable(Base):
|
|
326
|
+
"""Database model for storing plugin-specific data for agents.
|
|
327
|
+
|
|
328
|
+
This model uses a composite primary key of (agent_id, plugin, key) to store
|
|
329
|
+
plugin-specific data for agents in a flexible way.
|
|
330
|
+
|
|
331
|
+
Attributes:
|
|
332
|
+
agent_id: ID of the agent this data belongs to
|
|
333
|
+
plugin: Name of the plugin this data is for
|
|
334
|
+
key: Key for this specific piece of data
|
|
335
|
+
data: JSON data stored for this key
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
__tablename__ = "agent_plugin_data"
|
|
339
|
+
|
|
340
|
+
agent_id = Column(String, primary_key=True)
|
|
341
|
+
plugin = Column(String, primary_key=True)
|
|
342
|
+
key = Column(String, primary_key=True)
|
|
343
|
+
data = Column(JSON().with_variant(JSONB(), "postgresql"), nullable=True)
|
|
344
|
+
created_at = Column(
|
|
345
|
+
DateTime(timezone=True),
|
|
346
|
+
nullable=False,
|
|
347
|
+
server_default=func.now(),
|
|
348
|
+
)
|
|
349
|
+
updated_at = Column(
|
|
350
|
+
DateTime(timezone=True),
|
|
351
|
+
nullable=False,
|
|
352
|
+
server_default=func.now(),
|
|
353
|
+
onupdate=lambda: datetime.now(timezone.utc),
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class AgentPluginData(BaseModel):
|
|
358
|
+
"""Model for storing plugin-specific data for agents.
|
|
359
|
+
|
|
360
|
+
This model uses a composite primary key of (agent_id, plugin, key) to store
|
|
361
|
+
plugin-specific data for agents in a flexible way.
|
|
362
|
+
|
|
363
|
+
Attributes:
|
|
364
|
+
agent_id: ID of the agent this data belongs to
|
|
365
|
+
plugin: Name of the plugin this data is for
|
|
366
|
+
key: Key for this specific piece of data
|
|
367
|
+
data: JSON data stored for this key
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
model_config = ConfigDict(from_attributes=True)
|
|
371
|
+
|
|
372
|
+
agent_id: Annotated[
|
|
373
|
+
str,
|
|
374
|
+
PydanticField(description="ID of the agent this data belongs to"),
|
|
375
|
+
]
|
|
376
|
+
plugin: Annotated[
|
|
377
|
+
str,
|
|
378
|
+
PydanticField(description="Name of the plugin this data is for"),
|
|
379
|
+
]
|
|
380
|
+
key: Annotated[
|
|
381
|
+
str,
|
|
382
|
+
PydanticField(description="Key for this specific piece of data"),
|
|
383
|
+
]
|
|
384
|
+
data: Annotated[
|
|
385
|
+
Dict[str, Any],
|
|
386
|
+
PydanticField(default=None, description="JSON data stored for this key"),
|
|
387
|
+
]
|
|
388
|
+
created_at: Annotated[
|
|
389
|
+
datetime,
|
|
390
|
+
PydanticField(
|
|
391
|
+
description="Timestamp when this data was created",
|
|
392
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
393
|
+
),
|
|
394
|
+
]
|
|
395
|
+
updated_at: Annotated[
|
|
396
|
+
datetime,
|
|
397
|
+
PydanticField(
|
|
398
|
+
description="Timestamp when this data was last updated",
|
|
399
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
400
|
+
),
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
@classmethod
|
|
404
|
+
async def get(
|
|
405
|
+
cls, agent_id: str, plugin: str, key: str
|
|
406
|
+
) -> Optional["AgentPluginData"]:
|
|
407
|
+
"""Get plugin data for an agent.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
agent_id: ID of the agent
|
|
411
|
+
plugin: Name of the plugin
|
|
412
|
+
key: Data key
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
AgentPluginData if found, None otherwise
|
|
416
|
+
|
|
417
|
+
Raises:
|
|
418
|
+
HTTPException: If there are database errors
|
|
419
|
+
"""
|
|
420
|
+
async with get_session() as db:
|
|
421
|
+
item = await db.scalar(
|
|
422
|
+
select(AgentPluginDataTable).where(
|
|
423
|
+
AgentPluginDataTable.agent_id == agent_id,
|
|
424
|
+
AgentPluginDataTable.plugin == plugin,
|
|
425
|
+
AgentPluginDataTable.key == key,
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
if item:
|
|
429
|
+
return cls.model_validate(item)
|
|
430
|
+
return None
|
|
431
|
+
|
|
432
|
+
async def save(self) -> None:
|
|
433
|
+
"""Save or update plugin data.
|
|
434
|
+
|
|
435
|
+
Raises:
|
|
436
|
+
HTTPException: If there are database errors
|
|
437
|
+
"""
|
|
438
|
+
async with get_session() as db:
|
|
439
|
+
plugin_data = await db.scalar(
|
|
440
|
+
select(AgentPluginDataTable).where(
|
|
441
|
+
AgentPluginDataTable.agent_id == self.agent_id,
|
|
442
|
+
AgentPluginDataTable.plugin == self.plugin,
|
|
443
|
+
AgentPluginDataTable.key == self.key,
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
if plugin_data:
|
|
448
|
+
# Update existing record
|
|
449
|
+
plugin_data.data = self.data
|
|
450
|
+
db.add(plugin_data)
|
|
451
|
+
else:
|
|
452
|
+
# Create new record
|
|
453
|
+
plugin_data = AgentPluginDataTable(
|
|
454
|
+
agent_id=self.agent_id,
|
|
455
|
+
plugin=self.plugin,
|
|
456
|
+
key=self.key,
|
|
457
|
+
data=self.data,
|
|
458
|
+
)
|
|
459
|
+
db.add(plugin_data)
|
|
460
|
+
|
|
461
|
+
await db.commit()
|
|
462
|
+
await db.refresh(plugin_data)
|
|
463
|
+
|
|
464
|
+
# Refresh the model with updated data
|
|
465
|
+
self.model_validate(plugin_data)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
class AgentQuotaTable(Base):
|
|
469
|
+
"""AgentQuota database table model."""
|
|
470
|
+
|
|
471
|
+
__tablename__ = "agent_quotas"
|
|
472
|
+
|
|
473
|
+
id = Column(String, primary_key=True)
|
|
474
|
+
plan = Column(String, default="self-hosted")
|
|
475
|
+
message_count_total = Column(BigInteger, default=0)
|
|
476
|
+
message_limit_total = Column(BigInteger, default=99999999)
|
|
477
|
+
message_count_monthly = Column(BigInteger, default=0)
|
|
478
|
+
message_limit_monthly = Column(BigInteger, default=99999999)
|
|
479
|
+
message_count_daily = Column(BigInteger, default=0)
|
|
480
|
+
message_limit_daily = Column(BigInteger, default=99999999)
|
|
481
|
+
last_message_time = Column(DateTime(timezone=True), default=None, nullable=True)
|
|
482
|
+
autonomous_count_total = Column(BigInteger, default=0)
|
|
483
|
+
autonomous_limit_total = Column(BigInteger, default=99999999)
|
|
484
|
+
autonomous_count_monthly = Column(BigInteger, default=0)
|
|
485
|
+
autonomous_limit_monthly = Column(BigInteger, default=99999999)
|
|
486
|
+
last_autonomous_time = Column(DateTime(timezone=True), default=None, nullable=True)
|
|
487
|
+
twitter_count_total = Column(BigInteger, default=0)
|
|
488
|
+
twitter_limit_total = Column(BigInteger, default=99999999)
|
|
489
|
+
twitter_count_monthly = Column(BigInteger, default=0)
|
|
490
|
+
twitter_limit_monthly = Column(BigInteger, default=99999999)
|
|
491
|
+
twitter_count_daily = Column(BigInteger, default=0)
|
|
492
|
+
twitter_limit_daily = Column(BigInteger, default=99999999)
|
|
493
|
+
last_twitter_time = Column(DateTime(timezone=True), default=None, nullable=True)
|
|
494
|
+
free_income_daily = Column(Numeric(22, 4), default=0)
|
|
495
|
+
avg_action_cost = Column(Numeric(22, 4), default=0)
|
|
496
|
+
min_action_cost = Column(Numeric(22, 4), default=0)
|
|
497
|
+
max_action_cost = Column(Numeric(22, 4), default=0)
|
|
498
|
+
low_action_cost = Column(Numeric(22, 4), default=0)
|
|
499
|
+
medium_action_cost = Column(Numeric(22, 4), default=0)
|
|
500
|
+
high_action_cost = Column(Numeric(22, 4), default=0)
|
|
501
|
+
created_at = Column(
|
|
502
|
+
DateTime(timezone=True),
|
|
503
|
+
nullable=False,
|
|
504
|
+
server_default=func.now(),
|
|
505
|
+
)
|
|
506
|
+
updated_at = Column(
|
|
507
|
+
DateTime(timezone=True),
|
|
508
|
+
nullable=False,
|
|
509
|
+
server_default=func.now(),
|
|
510
|
+
onupdate=lambda: datetime.now(timezone.utc),
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class AgentQuota(BaseModel):
|
|
515
|
+
"""AgentQuota model."""
|
|
516
|
+
|
|
517
|
+
model_config = ConfigDict(from_attributes=True)
|
|
518
|
+
|
|
519
|
+
id: Annotated[
|
|
520
|
+
str, PydanticField(description="ID of the agent this quota belongs to")
|
|
521
|
+
]
|
|
522
|
+
plan: Annotated[
|
|
523
|
+
str, PydanticField(default="self-hosted", description="Agent plan name")
|
|
524
|
+
]
|
|
525
|
+
message_count_total: Annotated[
|
|
526
|
+
int, PydanticField(default=0, description="Total message count")
|
|
527
|
+
]
|
|
528
|
+
message_limit_total: Annotated[
|
|
529
|
+
int, PydanticField(default=99999999, description="Total message limit")
|
|
530
|
+
]
|
|
531
|
+
message_count_monthly: Annotated[
|
|
532
|
+
int, PydanticField(default=0, description="Monthly message count")
|
|
533
|
+
]
|
|
534
|
+
message_limit_monthly: Annotated[
|
|
535
|
+
int, PydanticField(default=99999999, description="Monthly message limit")
|
|
536
|
+
]
|
|
537
|
+
message_count_daily: Annotated[
|
|
538
|
+
int, PydanticField(default=0, description="Daily message count")
|
|
539
|
+
]
|
|
540
|
+
message_limit_daily: Annotated[
|
|
541
|
+
int, PydanticField(default=99999999, description="Daily message limit")
|
|
542
|
+
]
|
|
543
|
+
last_message_time: Annotated[
|
|
544
|
+
Optional[datetime],
|
|
545
|
+
PydanticField(default=None, description="Last message timestamp"),
|
|
546
|
+
]
|
|
547
|
+
autonomous_count_total: Annotated[
|
|
548
|
+
int, PydanticField(default=0, description="Total autonomous operations count")
|
|
549
|
+
]
|
|
550
|
+
autonomous_limit_total: Annotated[
|
|
551
|
+
int,
|
|
552
|
+
PydanticField(
|
|
553
|
+
default=99999999, description="Total autonomous operations limit"
|
|
554
|
+
),
|
|
555
|
+
]
|
|
556
|
+
autonomous_count_monthly: Annotated[
|
|
557
|
+
int, PydanticField(default=0, description="Monthly autonomous operations count")
|
|
558
|
+
]
|
|
559
|
+
autonomous_limit_monthly: Annotated[
|
|
560
|
+
int,
|
|
561
|
+
PydanticField(
|
|
562
|
+
default=99999999, description="Monthly autonomous operations limit"
|
|
563
|
+
),
|
|
564
|
+
]
|
|
565
|
+
autonomous_count_daily: Annotated[
|
|
566
|
+
int, PydanticField(default=0, description="Daily autonomous operations count")
|
|
567
|
+
]
|
|
568
|
+
autonomous_limit_daily: Annotated[
|
|
569
|
+
int,
|
|
570
|
+
PydanticField(
|
|
571
|
+
default=99999999, description="Daily autonomous operations limit"
|
|
572
|
+
),
|
|
573
|
+
]
|
|
574
|
+
last_autonomous_time: Annotated[
|
|
575
|
+
Optional[datetime],
|
|
576
|
+
PydanticField(default=None, description="Last autonomous operation timestamp"),
|
|
577
|
+
]
|
|
578
|
+
twitter_count_total: Annotated[
|
|
579
|
+
int, PydanticField(default=0, description="Total Twitter operations count")
|
|
580
|
+
]
|
|
581
|
+
twitter_limit_total: Annotated[
|
|
582
|
+
int,
|
|
583
|
+
PydanticField(default=99999999, description="Total Twitter operations limit"),
|
|
584
|
+
]
|
|
585
|
+
twitter_count_monthly: Annotated[
|
|
586
|
+
int, PydanticField(default=0, description="Monthly Twitter operations count")
|
|
587
|
+
]
|
|
588
|
+
twitter_limit_monthly: Annotated[
|
|
589
|
+
int,
|
|
590
|
+
PydanticField(default=99999999, description="Monthly Twitter operations limit"),
|
|
591
|
+
]
|
|
592
|
+
twitter_count_daily: Annotated[
|
|
593
|
+
int, PydanticField(default=0, description="Daily Twitter operations count")
|
|
594
|
+
]
|
|
595
|
+
twitter_limit_daily: Annotated[
|
|
596
|
+
int,
|
|
597
|
+
PydanticField(default=99999999, description="Daily Twitter operations limit"),
|
|
598
|
+
]
|
|
599
|
+
last_twitter_time: Annotated[
|
|
600
|
+
Optional[datetime],
|
|
601
|
+
PydanticField(default=None, description="Last Twitter operation timestamp"),
|
|
602
|
+
]
|
|
603
|
+
free_income_daily: Annotated[
|
|
604
|
+
Decimal,
|
|
605
|
+
PydanticField(default=0, description="Daily free income amount"),
|
|
606
|
+
]
|
|
607
|
+
avg_action_cost: Annotated[
|
|
608
|
+
Decimal,
|
|
609
|
+
PydanticField(default=0, description="Average cost per action"),
|
|
610
|
+
]
|
|
611
|
+
max_action_cost: Annotated[
|
|
612
|
+
Decimal,
|
|
613
|
+
PydanticField(default=0, description="Maximum cost per action"),
|
|
614
|
+
]
|
|
615
|
+
min_action_cost: Annotated[
|
|
616
|
+
Decimal,
|
|
617
|
+
PydanticField(default=0, description="Minimum cost per action"),
|
|
618
|
+
]
|
|
619
|
+
high_action_cost: Annotated[
|
|
620
|
+
Decimal,
|
|
621
|
+
PydanticField(default=0, description="High expected action cost"),
|
|
622
|
+
]
|
|
623
|
+
medium_action_cost: Annotated[
|
|
624
|
+
Decimal,
|
|
625
|
+
PydanticField(default=0, description="Medium expected action cost"),
|
|
626
|
+
]
|
|
627
|
+
low_action_cost: Annotated[
|
|
628
|
+
Decimal,
|
|
629
|
+
PydanticField(default=0, description="Low expected action cost"),
|
|
630
|
+
]
|
|
631
|
+
created_at: Annotated[
|
|
632
|
+
datetime,
|
|
633
|
+
PydanticField(
|
|
634
|
+
description="Timestamp when this quota was created",
|
|
635
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
636
|
+
),
|
|
637
|
+
]
|
|
638
|
+
updated_at: Annotated[
|
|
639
|
+
datetime,
|
|
640
|
+
PydanticField(
|
|
641
|
+
description="Timestamp when this quota was last updated",
|
|
642
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
643
|
+
),
|
|
644
|
+
]
|
|
645
|
+
|
|
646
|
+
@classmethod
|
|
647
|
+
async def get(cls, agent_id: str) -> "AgentQuota":
|
|
648
|
+
"""Get agent quota by id, if not exists, create a new one.
|
|
649
|
+
|
|
650
|
+
Args:
|
|
651
|
+
agent_id: Agent ID
|
|
652
|
+
|
|
653
|
+
Returns:
|
|
654
|
+
AgentQuota: The agent's quota object
|
|
655
|
+
|
|
656
|
+
Raises:
|
|
657
|
+
HTTPException: If there are database errors
|
|
658
|
+
"""
|
|
659
|
+
async with get_session() as db:
|
|
660
|
+
quota_record = await db.get(AgentQuotaTable, agent_id)
|
|
661
|
+
if not quota_record:
|
|
662
|
+
# Create new record
|
|
663
|
+
quota_record = AgentQuotaTable(
|
|
664
|
+
id=agent_id,
|
|
665
|
+
)
|
|
666
|
+
db.add(quota_record)
|
|
667
|
+
await db.commit()
|
|
668
|
+
await db.refresh(quota_record)
|
|
669
|
+
|
|
670
|
+
return cls.model_validate(quota_record)
|
|
671
|
+
|
|
672
|
+
def has_message_quota(self) -> bool:
|
|
673
|
+
"""Check if the agent has message quota.
|
|
674
|
+
|
|
675
|
+
Returns:
|
|
676
|
+
bool: True if the agent has quota, False otherwise
|
|
677
|
+
"""
|
|
678
|
+
# Check total limit
|
|
679
|
+
if self.message_count_total >= self.message_limit_total:
|
|
680
|
+
return False
|
|
681
|
+
# Check monthly limit
|
|
682
|
+
if self.message_count_monthly >= self.message_limit_monthly:
|
|
683
|
+
return False
|
|
684
|
+
# Check daily limit
|
|
685
|
+
if self.message_count_daily >= self.message_limit_daily:
|
|
686
|
+
return False
|
|
687
|
+
return True
|
|
688
|
+
|
|
689
|
+
def has_autonomous_quota(self) -> bool:
|
|
690
|
+
"""Check if the agent has autonomous quota.
|
|
691
|
+
|
|
692
|
+
Returns:
|
|
693
|
+
bool: True if the agent has quota, False otherwise
|
|
694
|
+
"""
|
|
695
|
+
# Check total limit
|
|
696
|
+
if self.autonomous_count_total >= self.autonomous_limit_total:
|
|
697
|
+
return False
|
|
698
|
+
# Check monthly limit
|
|
699
|
+
if self.autonomous_count_monthly >= self.autonomous_limit_monthly:
|
|
700
|
+
return False
|
|
701
|
+
return True
|
|
702
|
+
|
|
703
|
+
def has_twitter_quota(self) -> bool:
|
|
704
|
+
"""Check if the agent has twitter quota.
|
|
705
|
+
|
|
706
|
+
Returns:
|
|
707
|
+
bool: True if the agent has quota, False otherwise
|
|
708
|
+
"""
|
|
709
|
+
# Check total limit
|
|
710
|
+
if self.twitter_count_total >= self.twitter_limit_total:
|
|
711
|
+
return False
|
|
712
|
+
# Check daily limit
|
|
713
|
+
if self.twitter_count_daily >= self.twitter_limit_daily:
|
|
714
|
+
return False
|
|
715
|
+
return True
|
|
716
|
+
|
|
717
|
+
@staticmethod
|
|
718
|
+
async def add_free_income_in_session(session, id: str, amount: Decimal) -> None:
|
|
719
|
+
"""Add free income to an agent's quota directly in the database.
|
|
720
|
+
|
|
721
|
+
Args:
|
|
722
|
+
session: SQLAlchemy session
|
|
723
|
+
id: Agent ID
|
|
724
|
+
amount: Amount to add to free_income_daily
|
|
725
|
+
|
|
726
|
+
Raises:
|
|
727
|
+
HTTPException: If there are database errors
|
|
728
|
+
"""
|
|
729
|
+
try:
|
|
730
|
+
# Check if the record exists using session.get
|
|
731
|
+
quota_record = await session.get(AgentQuotaTable, id)
|
|
732
|
+
|
|
733
|
+
if not quota_record:
|
|
734
|
+
# Create new record if it doesn't exist
|
|
735
|
+
quota_record = AgentQuotaTable(id=id, free_income_daily=amount)
|
|
736
|
+
session.add(quota_record)
|
|
737
|
+
else:
|
|
738
|
+
# Use update statement with func to directly add the amount
|
|
739
|
+
from sqlalchemy import update
|
|
740
|
+
|
|
741
|
+
stmt = update(AgentQuotaTable).where(AgentQuotaTable.id == id)
|
|
742
|
+
stmt = stmt.values(
|
|
743
|
+
free_income_daily=func.coalesce(
|
|
744
|
+
AgentQuotaTable.free_income_daily, 0
|
|
745
|
+
)
|
|
746
|
+
+ amount
|
|
747
|
+
)
|
|
748
|
+
await session.execute(stmt)
|
|
749
|
+
except Exception as e:
|
|
750
|
+
logger.error(f"Error adding free income: {str(e)}")
|
|
751
|
+
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
|
|
752
|
+
|
|
753
|
+
async def add_message(self) -> None:
|
|
754
|
+
"""Add a message to the agent's message count."""
|
|
755
|
+
async with get_session() as db:
|
|
756
|
+
quota_record = await db.get(AgentQuotaTable, self.id)
|
|
757
|
+
|
|
758
|
+
if quota_record:
|
|
759
|
+
# Update record
|
|
760
|
+
quota_record.message_count_total += 1
|
|
761
|
+
quota_record.message_count_monthly += 1
|
|
762
|
+
quota_record.message_count_daily += 1
|
|
763
|
+
quota_record.last_message_time = datetime.now(timezone.utc)
|
|
764
|
+
db.add(quota_record)
|
|
765
|
+
await db.commit()
|
|
766
|
+
|
|
767
|
+
# Update this instance
|
|
768
|
+
await db.refresh(quota_record)
|
|
769
|
+
self.message_count_total = quota_record.message_count_total
|
|
770
|
+
self.message_count_monthly = quota_record.message_count_monthly
|
|
771
|
+
self.message_count_daily = quota_record.message_count_daily
|
|
772
|
+
self.last_message_time = quota_record.last_message_time
|
|
773
|
+
self.updated_at = quota_record.updated_at
|
|
774
|
+
|
|
775
|
+
async def add_autonomous(self) -> None:
|
|
776
|
+
"""Add an autonomous operation to the agent's autonomous count."""
|
|
777
|
+
async with get_session() as db:
|
|
778
|
+
quota_record = await db.get(AgentQuotaTable, self.id)
|
|
779
|
+
if quota_record:
|
|
780
|
+
# Update record
|
|
781
|
+
quota_record.autonomous_count_total += 1
|
|
782
|
+
quota_record.autonomous_count_monthly += 1
|
|
783
|
+
quota_record.last_autonomous_time = datetime.now(timezone.utc)
|
|
784
|
+
db.add(quota_record)
|
|
785
|
+
await db.commit()
|
|
786
|
+
|
|
787
|
+
# Update this instance
|
|
788
|
+
await db.refresh(quota_record)
|
|
789
|
+
self.model_validate(quota_record)
|
|
790
|
+
|
|
791
|
+
async def add_twitter_message(self) -> None:
|
|
792
|
+
"""Add a twitter message to the agent's twitter count.
|
|
793
|
+
|
|
794
|
+
Raises:
|
|
795
|
+
HTTPException: If there are database errors
|
|
796
|
+
"""
|
|
797
|
+
async with get_session() as db:
|
|
798
|
+
quota_record = await db.get(AgentQuotaTable, self.id)
|
|
799
|
+
|
|
800
|
+
if quota_record:
|
|
801
|
+
# Update record
|
|
802
|
+
quota_record.twitter_count_total += 1
|
|
803
|
+
quota_record.twitter_count_daily += 1
|
|
804
|
+
quota_record.last_twitter_time = datetime.now(timezone.utc)
|
|
805
|
+
db.add(quota_record)
|
|
806
|
+
await db.commit()
|
|
807
|
+
|
|
808
|
+
# Update this instance
|
|
809
|
+
await db.refresh(quota_record)
|
|
810
|
+
self.model_validate(quota_record)
|