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,106 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional, Type
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
from eth_utils import is_address
|
|
6
|
+
from langchain_core.runnables import RunnableConfig
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .base import NationBaseTool
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NftCheckInput(BaseModel):
|
|
15
|
+
nation_wallet_address: Optional[str] = Field(
|
|
16
|
+
default=None, description="Nation wallet address"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NftCheck(NationBaseTool):
|
|
21
|
+
name: str = "nft_check"
|
|
22
|
+
description: str = "Check user nation pass NFTs stats in nation, including usage status and linked agents.By default, it will use the user_id as the wallet address. If you want to check other wallet address, please pass the nation_wallet_address parameter."
|
|
23
|
+
args_schema: Type[BaseModel] = NftCheckInput
|
|
24
|
+
|
|
25
|
+
async def _arun(
|
|
26
|
+
self, nation_wallet_address: Optional[str] = None, config: RunnableConfig = None
|
|
27
|
+
) -> str:
|
|
28
|
+
"""Implementation of the NFT Check tool.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
nation_wallet_address: The wallet address of the nation (optional), if not passed, then get user_id from chat as wallet address.
|
|
32
|
+
config: Configuration for the runnable.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
str: Formatted NFT check results based on the nation wallet address.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
context = self.context_from_config(config)
|
|
39
|
+
logger.debug(f"nft_check.py: Running NFT check with context {context}")
|
|
40
|
+
|
|
41
|
+
# Use the provided nation_wallet_address or fetch it from the context
|
|
42
|
+
if not nation_wallet_address:
|
|
43
|
+
nation_wallet_address = context.user_id
|
|
44
|
+
if not nation_wallet_address:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
"Nation wallet address is not provided and not found in context"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Validate the normalized address
|
|
50
|
+
if not is_address(nation_wallet_address):
|
|
51
|
+
raise ValueError(
|
|
52
|
+
f"Invalid Ethereum wallet address: {nation_wallet_address}"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
url = f"{self.get_base_url()}/v1/users/{nation_wallet_address}"
|
|
56
|
+
|
|
57
|
+
api_key = self.get_api_key()
|
|
58
|
+
|
|
59
|
+
if not api_key:
|
|
60
|
+
raise ValueError("Backend API key not found")
|
|
61
|
+
|
|
62
|
+
headers = {"Accept": "application/json", "x-api-key": api_key}
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
66
|
+
response = await client.get(url, headers=headers)
|
|
67
|
+
|
|
68
|
+
if response.status_code != 200:
|
|
69
|
+
logger.error(
|
|
70
|
+
f"nft_check.py: Error from API: {response.status_code} - {response.text}"
|
|
71
|
+
)
|
|
72
|
+
return f"Error fetching NFT data: {response.status_code} - {response.text}"
|
|
73
|
+
|
|
74
|
+
data = response.json()
|
|
75
|
+
nfts = data.get("nfts", [])
|
|
76
|
+
|
|
77
|
+
if not nfts:
|
|
78
|
+
return f"No NFTs found for wallet address: {nation_wallet_address}"
|
|
79
|
+
|
|
80
|
+
# Format the NFT data
|
|
81
|
+
formatted_results = (
|
|
82
|
+
f"NFTs for wallet address '{nation_wallet_address}':\n\n"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
for i, nft in enumerate(nfts, 1):
|
|
86
|
+
token_id = nft.get("token_id", "Unknown")
|
|
87
|
+
used_by = nft.get("used_by", None)
|
|
88
|
+
linked_agent_id = nft.get("linked_agent_id", "None")
|
|
89
|
+
|
|
90
|
+
formatted_results += f"{i}. Token ID: {token_id}\n"
|
|
91
|
+
if used_by:
|
|
92
|
+
formatted_results += (
|
|
93
|
+
f" Status: Used by Agent ID {linked_agent_id}\n"
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
formatted_results += " Status: Available\n"
|
|
97
|
+
formatted_results += "\n"
|
|
98
|
+
|
|
99
|
+
return formatted_results.strip()
|
|
100
|
+
|
|
101
|
+
except httpx.TimeoutException:
|
|
102
|
+
logger.error("nft_check.py: Request timed out")
|
|
103
|
+
return "The request to the NFT API timed out. Please try again later."
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logger.error(f"nft_check.py: Error fetching NFT data: {e}", exc_info=True)
|
|
106
|
+
return "An error occurred while fetching NFT data. Please try again later."
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "Nation",
|
|
5
|
+
"description": "Check nation NFT stats",
|
|
6
|
+
"x-icon": "https://ai.service.crestal.dev/skills/nation/nation.png",
|
|
7
|
+
"x-tags": [
|
|
8
|
+
"Nation",
|
|
9
|
+
"NFTChecker"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"enabled": {
|
|
13
|
+
"type": "boolean",
|
|
14
|
+
"title": "Enabled",
|
|
15
|
+
"description": "Whether this skill is enabled",
|
|
16
|
+
"default": false
|
|
17
|
+
},
|
|
18
|
+
"states": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"nft_check": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"title": "Nation NFT Usage Check",
|
|
24
|
+
"enum": [
|
|
25
|
+
"disabled",
|
|
26
|
+
"public",
|
|
27
|
+
"private"
|
|
28
|
+
],
|
|
29
|
+
"x-enum-title": [
|
|
30
|
+
"Disabled",
|
|
31
|
+
"Agent Owner + All Users",
|
|
32
|
+
"Agent Owner Only"
|
|
33
|
+
],
|
|
34
|
+
"description": "Check User Nation NFT Usage",
|
|
35
|
+
"default": "disabled"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"description": "States for each Nation skill"
|
|
39
|
+
},
|
|
40
|
+
"api_key_provider": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"title": "API Key Provider",
|
|
43
|
+
"description": "Who provides the API key",
|
|
44
|
+
"enum": [
|
|
45
|
+
"platform"
|
|
46
|
+
],
|
|
47
|
+
"x-enum-title": [
|
|
48
|
+
"Nation Hosted"
|
|
49
|
+
],
|
|
50
|
+
"default": "platform"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"required": [
|
|
54
|
+
"states",
|
|
55
|
+
"enabled"
|
|
56
|
+
],
|
|
57
|
+
"additionalProperties": true
|
|
58
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""OpenAI skills."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TypedDict
|
|
5
|
+
|
|
6
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
7
|
+
from intentkit.skills.base import SkillConfig, SkillState
|
|
8
|
+
from intentkit.skills.openai.base import OpenAIBaseTool
|
|
9
|
+
from intentkit.skills.openai.dalle_image_generation import DALLEImageGeneration
|
|
10
|
+
from intentkit.skills.openai.gpt_image_generation import GPTImageGeneration
|
|
11
|
+
from intentkit.skills.openai.gpt_image_to_image import GPTImageToImage
|
|
12
|
+
from intentkit.skills.openai.image_to_text import ImageToText
|
|
13
|
+
|
|
14
|
+
# Cache skills at the system level, because they are stateless
|
|
15
|
+
_cache: dict[str, OpenAIBaseTool] = {}
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SkillStates(TypedDict):
|
|
21
|
+
image_to_text: SkillState
|
|
22
|
+
dalle_image_generation: SkillState
|
|
23
|
+
gpt_image_generation: SkillState
|
|
24
|
+
gpt_image_to_image: SkillState
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Config(SkillConfig):
|
|
28
|
+
"""Configuration for OpenAI skills."""
|
|
29
|
+
|
|
30
|
+
states: SkillStates
|
|
31
|
+
api_key: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def get_skills(
|
|
35
|
+
config: "Config",
|
|
36
|
+
is_private: bool,
|
|
37
|
+
store: SkillStoreABC,
|
|
38
|
+
**_,
|
|
39
|
+
) -> list[OpenAIBaseTool]:
|
|
40
|
+
"""Get all OpenAI skills.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
config: The configuration for OpenAI skills.
|
|
44
|
+
is_private: Whether to include private skills.
|
|
45
|
+
store: The skill store for persisting data.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A list of OpenAI skills.
|
|
49
|
+
"""
|
|
50
|
+
available_skills = []
|
|
51
|
+
|
|
52
|
+
# Include skills based on their state
|
|
53
|
+
for skill_name, state in config["states"].items():
|
|
54
|
+
if state == "disabled":
|
|
55
|
+
continue
|
|
56
|
+
elif state == "public" or (state == "private" and is_private):
|
|
57
|
+
available_skills.append(skill_name)
|
|
58
|
+
|
|
59
|
+
# Get each skill using the cached getter
|
|
60
|
+
result = []
|
|
61
|
+
for name in available_skills:
|
|
62
|
+
skill = get_openai_skill(name, store)
|
|
63
|
+
if skill:
|
|
64
|
+
result.append(skill)
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_openai_skill(
|
|
69
|
+
name: str,
|
|
70
|
+
store: SkillStoreABC,
|
|
71
|
+
) -> OpenAIBaseTool:
|
|
72
|
+
"""Get an OpenAI skill by name.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
name: The name of the skill to get
|
|
76
|
+
store: The skill store for persisting data
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The requested OpenAI skill
|
|
80
|
+
"""
|
|
81
|
+
if name == "image_to_text":
|
|
82
|
+
if name not in _cache:
|
|
83
|
+
_cache[name] = ImageToText(
|
|
84
|
+
skill_store=store,
|
|
85
|
+
)
|
|
86
|
+
return _cache[name]
|
|
87
|
+
elif name == "dalle_image_generation":
|
|
88
|
+
if name not in _cache:
|
|
89
|
+
_cache[name] = DALLEImageGeneration(
|
|
90
|
+
skill_store=store,
|
|
91
|
+
)
|
|
92
|
+
return _cache[name]
|
|
93
|
+
elif name == "gpt_image_generation":
|
|
94
|
+
if name not in _cache:
|
|
95
|
+
_cache[name] = GPTImageGeneration(
|
|
96
|
+
skill_store=store,
|
|
97
|
+
)
|
|
98
|
+
return _cache[name]
|
|
99
|
+
elif name == "gpt_image_to_image":
|
|
100
|
+
if name not in _cache:
|
|
101
|
+
_cache[name] = GPTImageToImage(
|
|
102
|
+
skill_store=store,
|
|
103
|
+
)
|
|
104
|
+
return _cache[name]
|
|
105
|
+
else:
|
|
106
|
+
logger.warning(f"Unknown OpenAI skill: {name}")
|
|
107
|
+
return None
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Base class for OpenAI skills."""
|
|
2
|
+
|
|
3
|
+
from typing import Type
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from intentkit.abstracts.skill import SkillStoreABC
|
|
8
|
+
from intentkit.skills.base import IntentKitSkill, SkillContext
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OpenAIBaseTool(IntentKitSkill):
|
|
12
|
+
"""Base class for all OpenAI skills.
|
|
13
|
+
|
|
14
|
+
This class provides common functionality for all OpenAI skills.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
name: str = Field(description="The name of the tool")
|
|
18
|
+
description: str = Field(description="A description of what the tool does")
|
|
19
|
+
args_schema: Type[BaseModel]
|
|
20
|
+
skill_store: SkillStoreABC = Field(
|
|
21
|
+
description="The skill store for persisting data"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def get_api_key(self, context: SkillContext) -> str:
|
|
25
|
+
skill_config = context.config
|
|
26
|
+
if skill_config.get("api_key_provider") == "agent_owner":
|
|
27
|
+
return skill_config.get("api_key")
|
|
28
|
+
return self.skill_store.get_system_config("openai_api_key")
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def category(self) -> str:
|
|
32
|
+
return "openai"
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""DALL-E image generation skill for OpenAI."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Type
|
|
5
|
+
|
|
6
|
+
import openai
|
|
7
|
+
from epyxid import XID
|
|
8
|
+
from langchain_core.runnables import RunnableConfig
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
|
|
11
|
+
from intentkit.skills.openai.base import OpenAIBaseTool
|
|
12
|
+
from intentkit.utils.s3 import store_image
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DALLEImageGenerationInput(BaseModel):
|
|
18
|
+
"""Input for DALLEImageGeneration tool."""
|
|
19
|
+
|
|
20
|
+
prompt: str = Field(
|
|
21
|
+
description="Text prompt describing the image to generate.",
|
|
22
|
+
)
|
|
23
|
+
size: str = Field(
|
|
24
|
+
default="1024x1024",
|
|
25
|
+
description="Size of the generated image. Options: 1024x1024, 1024x1792, 1792x1024",
|
|
26
|
+
)
|
|
27
|
+
quality: str = Field(
|
|
28
|
+
default="hd",
|
|
29
|
+
description="Quality of the generated image. Options: standard, hd",
|
|
30
|
+
)
|
|
31
|
+
style: str = Field(
|
|
32
|
+
default="vivid",
|
|
33
|
+
description="Style of the generated image. Options: vivid, natural",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class DALLEImageGeneration(OpenAIBaseTool):
|
|
38
|
+
"""Tool for generating high-quality images using OpenAI's DALL-E 3 model.
|
|
39
|
+
|
|
40
|
+
This tool takes a text prompt and uses OpenAI's API to generate
|
|
41
|
+
an image based on the description using the DALL-E 3 model.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
name: The name of the tool.
|
|
45
|
+
description: A description of what the tool does.
|
|
46
|
+
args_schema: The schema for the tool's input arguments.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
name: str = "dalle_image_generation"
|
|
50
|
+
description: str = (
|
|
51
|
+
"Generate images using OpenAI's DALL-E 3 model.\n"
|
|
52
|
+
"Provide a text prompt describing the image you want to generate.\n"
|
|
53
|
+
"DALL-E 3 is a powerful image generation model capable of creating detailed, "
|
|
54
|
+
"high-quality images from text descriptions.\n"
|
|
55
|
+
"You can specify size, quality, and style parameters for more control.\n"
|
|
56
|
+
)
|
|
57
|
+
args_schema: Type[BaseModel] = DALLEImageGenerationInput
|
|
58
|
+
|
|
59
|
+
async def _arun(
|
|
60
|
+
self,
|
|
61
|
+
prompt: str,
|
|
62
|
+
size: str = "1024x1024",
|
|
63
|
+
quality: str = "hd",
|
|
64
|
+
style: str = "vivid",
|
|
65
|
+
config: RunnableConfig = None,
|
|
66
|
+
**kwargs,
|
|
67
|
+
) -> str:
|
|
68
|
+
"""Implementation of the tool to generate images using OpenAI's DALL-E 3 model.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
prompt: Text prompt describing the image to generate.
|
|
72
|
+
size: Size of the generated image. Options: 1024x1024, 1024x1792, 1792x1024
|
|
73
|
+
quality: Quality of the generated image. Options: standard, hd
|
|
74
|
+
style: Style of the generated image. Options: vivid, natural
|
|
75
|
+
config: Configuration for the runnable.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
str: URL of the generated image.
|
|
79
|
+
|
|
80
|
+
Raises:
|
|
81
|
+
Exception: If the image generation fails.
|
|
82
|
+
"""
|
|
83
|
+
context = self.context_from_config(config)
|
|
84
|
+
|
|
85
|
+
# Get the OpenAI API key from the skill store
|
|
86
|
+
api_key = self.get_api_key(context)
|
|
87
|
+
|
|
88
|
+
# Generate a unique job ID
|
|
89
|
+
job_id = str(XID())
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
# Initialize the OpenAI client
|
|
93
|
+
client = openai.OpenAI(api_key=api_key)
|
|
94
|
+
|
|
95
|
+
# Make the API request to generate the image
|
|
96
|
+
response = client.images.generate(
|
|
97
|
+
model="dall-e-3",
|
|
98
|
+
prompt=prompt,
|
|
99
|
+
size=size,
|
|
100
|
+
quality=quality,
|
|
101
|
+
style=style,
|
|
102
|
+
n=1,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Get the image URL from the response
|
|
106
|
+
image_url = response.data[0].url
|
|
107
|
+
|
|
108
|
+
# Strip potential double quotes from the response
|
|
109
|
+
image_url = image_url.strip('"')
|
|
110
|
+
|
|
111
|
+
# Generate a key with agent ID as prefix
|
|
112
|
+
image_key = f"{context.agent.id}/dalle/{job_id}"
|
|
113
|
+
|
|
114
|
+
# Store the image and get the CDN URL
|
|
115
|
+
stored_url = await store_image(image_url, image_key)
|
|
116
|
+
|
|
117
|
+
# Return the stored image URL
|
|
118
|
+
return stored_url
|
|
119
|
+
|
|
120
|
+
except openai.OpenAIError as e:
|
|
121
|
+
error_message = f"OpenAI API error: {str(e)}"
|
|
122
|
+
logger.error(error_message)
|
|
123
|
+
raise Exception(error_message)
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
error_message = f"Error generating image with DALL-E: {str(e)}"
|
|
127
|
+
logger.error(error_message)
|
|
128
|
+
raise Exception(error_message)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""GPT image generation skill for OpenAI."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Literal, Type
|
|
6
|
+
|
|
7
|
+
import openai
|
|
8
|
+
from epyxid import XID
|
|
9
|
+
from langchain_core.runnables import RunnableConfig
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
from intentkit.skills.openai.base import OpenAIBaseTool
|
|
13
|
+
from intentkit.utils.s3 import store_image_bytes
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GPTImageGenerationInput(BaseModel):
|
|
19
|
+
"""Input for GPTImageGeneration tool."""
|
|
20
|
+
|
|
21
|
+
prompt: str = Field(
|
|
22
|
+
description="Text prompt describing the image to generate.",
|
|
23
|
+
)
|
|
24
|
+
size: Literal["1024x1024", "1536x1024", "1024x1536", "auto"] = Field(
|
|
25
|
+
default="auto",
|
|
26
|
+
description="Size of the generated image. Options: 1024x1024, 1536x1024, 1024x1536, auto",
|
|
27
|
+
)
|
|
28
|
+
quality: Literal["high", "medium", "low", "auto"] = Field(
|
|
29
|
+
default="auto",
|
|
30
|
+
description="Quality of the generated image. Options: high, medium, low, auto",
|
|
31
|
+
)
|
|
32
|
+
background: Literal["transparent", "opaque", "auto"] = Field(
|
|
33
|
+
default="auto",
|
|
34
|
+
description="Background transparency. Options: transparent, opaque, auto",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GPTImageGeneration(OpenAIBaseTool):
|
|
39
|
+
"""Tool for generating high-quality images using OpenAI's GPT-Image-1 model.
|
|
40
|
+
|
|
41
|
+
This tool takes a text prompt and uses OpenAI's API to generate
|
|
42
|
+
an image based on the description using the GPT-Image-1 model.
|
|
43
|
+
|
|
44
|
+
Attributes:
|
|
45
|
+
name: The name of the tool.
|
|
46
|
+
description: A description of what the tool does.
|
|
47
|
+
args_schema: The schema for the tool's input arguments.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
name: str = "gpt_image_generation"
|
|
51
|
+
description: str = (
|
|
52
|
+
"Generate images using OpenAI's GPT-Image-1 model.\n"
|
|
53
|
+
"Provide a text prompt describing the image you want to generate.\n"
|
|
54
|
+
"GPT-Image-1 is a powerful image generation model capable of creating detailed, "
|
|
55
|
+
"high-quality images from text descriptions.\n"
|
|
56
|
+
"You can specify size, quality, and background parameters for more control.\n"
|
|
57
|
+
)
|
|
58
|
+
args_schema: Type[BaseModel] = GPTImageGenerationInput
|
|
59
|
+
|
|
60
|
+
async def _arun(
|
|
61
|
+
self,
|
|
62
|
+
prompt: str,
|
|
63
|
+
size: Literal["1024x1024", "1536x1024", "1024x1536", "auto"] = "auto",
|
|
64
|
+
quality: Literal["high", "medium", "low", "auto"] = "auto",
|
|
65
|
+
background: Literal["transparent", "opaque", "auto"] = "auto",
|
|
66
|
+
config: RunnableConfig = None,
|
|
67
|
+
**kwargs,
|
|
68
|
+
) -> str:
|
|
69
|
+
"""Implementation of the tool to generate images using OpenAI's GPT-Image-1 model.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
prompt: Text prompt describing the image to generate.
|
|
73
|
+
size: Size of the generated image. Options: 1024x1024, 1536x1024, 1024x1536, auto
|
|
74
|
+
quality: Quality of the generated image. Options: high, medium, low, auto
|
|
75
|
+
background: Background transparency. Options: transparent, opaque, auto
|
|
76
|
+
config: Configuration for the runnable.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
str: URL of the generated image.
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
Exception: If the image generation fails.
|
|
83
|
+
"""
|
|
84
|
+
context = self.context_from_config(config)
|
|
85
|
+
|
|
86
|
+
# Get the OpenAI API key from the skill store
|
|
87
|
+
api_key = self.get_api_key(context)
|
|
88
|
+
|
|
89
|
+
# Generate a unique job ID
|
|
90
|
+
job_id = str(XID())
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
# Initialize the OpenAI client
|
|
94
|
+
client = openai.OpenAI(api_key=api_key)
|
|
95
|
+
|
|
96
|
+
# Determine content type based on background setting
|
|
97
|
+
content_type = "image/png" if background == "transparent" else "image/jpeg"
|
|
98
|
+
|
|
99
|
+
# Make the API request to generate the image
|
|
100
|
+
response = client.images.generate(
|
|
101
|
+
model="gpt-image-1",
|
|
102
|
+
prompt=prompt,
|
|
103
|
+
size=size,
|
|
104
|
+
quality=quality,
|
|
105
|
+
background=background,
|
|
106
|
+
moderation="low", # Using low moderation as specified
|
|
107
|
+
n=1,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# GPT-Image-1 always returns base64-encoded images
|
|
111
|
+
# Get the base64 image data from the response
|
|
112
|
+
base64_image = response.data[0].b64_json
|
|
113
|
+
|
|
114
|
+
# Log the usage information if available
|
|
115
|
+
if hasattr(response, "usage") and response.usage:
|
|
116
|
+
usage = response.usage
|
|
117
|
+
logger.info(
|
|
118
|
+
f"GPT-Image-1 generation usage: "
|
|
119
|
+
f"input_tokens={usage.input_tokens}, "
|
|
120
|
+
f"output_tokens={usage.output_tokens}, "
|
|
121
|
+
f"total_tokens={usage.total_tokens}"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Log detailed input tokens information if available
|
|
125
|
+
if (
|
|
126
|
+
hasattr(usage, "input_tokens_details")
|
|
127
|
+
and usage.input_tokens_details
|
|
128
|
+
):
|
|
129
|
+
details = usage.input_tokens_details
|
|
130
|
+
logger.info(f"Input tokens details: {details}")
|
|
131
|
+
|
|
132
|
+
# Decode the base64 string to bytes
|
|
133
|
+
image_bytes = base64.b64decode(base64_image)
|
|
134
|
+
|
|
135
|
+
# Generate a key with agent ID as prefix
|
|
136
|
+
image_key = f"{context.agent.id}/gpt-image/{job_id}"
|
|
137
|
+
|
|
138
|
+
# Store the image bytes and get the CDN URL
|
|
139
|
+
stored_url = await store_image_bytes(image_bytes, image_key, content_type)
|
|
140
|
+
|
|
141
|
+
# Return the stored image URL
|
|
142
|
+
return stored_url
|
|
143
|
+
|
|
144
|
+
except openai.OpenAIError as e:
|
|
145
|
+
error_message = f"OpenAI API error: {str(e)}"
|
|
146
|
+
logger.error(error_message)
|
|
147
|
+
raise Exception(error_message)
|
|
148
|
+
|
|
149
|
+
except Exception as e:
|
|
150
|
+
error_message = f"Error generating image with GPT-Image-1: {str(e)}"
|
|
151
|
+
logger.error(error_message)
|
|
152
|
+
raise Exception(error_message)
|