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,23 @@
|
|
|
1
|
+
from typing import Type
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
# Import the generic base and shared input
|
|
6
|
+
from intentkit.skills.venice_image.base import VeniceImageBaseTool
|
|
7
|
+
from intentkit.skills.venice_image.image_upscale.image_upscale_input import (
|
|
8
|
+
VeniceImageUpscaleInput,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class VeniceImageUpscaleBaseTool(VeniceImageBaseTool):
|
|
13
|
+
"""
|
|
14
|
+
Base class for Venice AI *Image Upscaling* tools.
|
|
15
|
+
Inherits from VeniceAIBaseTool and handles specifics of the
|
|
16
|
+
/image/upscale endpoint
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
args_schema: Type[BaseModel] = VeniceImageUpscaleInput
|
|
20
|
+
name: str = Field(description="The unique name of the image upscaling tool.")
|
|
21
|
+
description: str = Field(
|
|
22
|
+
description="A description of what the image upscaling tool does."
|
|
23
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from typing import Literal, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field, HttpUrl
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VeniceImageUpscaleInput(BaseModel):
|
|
7
|
+
"""Input for the Image Upscale tool."""
|
|
8
|
+
|
|
9
|
+
image_url: HttpUrl = Field(
|
|
10
|
+
description="The URL of the image to upscale. Must be a publicly accessible URL.",
|
|
11
|
+
)
|
|
12
|
+
replication: Optional[float] = Field(
|
|
13
|
+
default=0.35,
|
|
14
|
+
description=(
|
|
15
|
+
'How strongly lines and noise in the base image are preserved. Higher values are noisier but less plastic/AI "generated"/hallucinated. Must be between 0.1 and 1.'
|
|
16
|
+
"Required range: 0.1 <= x <= 1"
|
|
17
|
+
),
|
|
18
|
+
)
|
|
19
|
+
scale: Literal[2, 4] = Field(
|
|
20
|
+
default=2,
|
|
21
|
+
description="The factor by which to upscale the image (either 2 or 4). Defaults to 2.",
|
|
22
|
+
)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# image_vision
|
|
2
|
+
|
|
3
|
+
**Image Vision** is a sub-tool in the Venice Image suite that provides highly detailed, comprehensive, AI-generated textual descriptions of images. It is designed for analyzing and summarizing the visual content of any image accessible via URL.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What does it do?
|
|
8
|
+
|
|
9
|
+
This tool uses Venice AI’s latest visual-language model (`qwen-2.5-vl`) to “see” an image as a human or curator would. It returns a paragraph-length, multi-faceted, exhaustive description covering:
|
|
10
|
+
|
|
11
|
+
- All visible objects and their properties (colors, shapes, count, arrangement)
|
|
12
|
+
- Scene composition: spatial arrangement, relationships, perspective
|
|
13
|
+
- Surface textures, materials, lighting, color palette
|
|
14
|
+
- Contextual, stylistic, or artistic features (e.g., “art deco style,” “digital illustration”)
|
|
15
|
+
- Mood, visual storytelling elements, or any notable anomalies
|
|
16
|
+
- Additional inferred details where possible
|
|
17
|
+
|
|
18
|
+
This tool is ideal for accessibility, archiving, content discovery, search, and cognitive AI workflows.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Input
|
|
23
|
+
|
|
24
|
+
| Field | Type | Description | Required |
|
|
25
|
+
|--------------|----------|---------------------------------------------------------------------|----------|
|
|
26
|
+
| image_url | HttpUrl | Publicly accessible URL to the target image. | Yes |
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"image_url": "https://example.com/some_picture.jpg"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Example Output
|
|
38
|
+
|
|
39
|
+
A typical result will be a dictionary with the generated description under a relevant key (the raw API response may vary based on Venice formats):
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"success": true,
|
|
44
|
+
"result": "A vibrant, high-resolution digital illustration depicting a Venetian canal at midday. The scene features pastel-hued buildings on either side of the canal with ornate balconies and open shuttered windows. Gondolas and small boats glide over the calm, reflective water, casting rippling shadows. The sky is clear and blue, with sunlight streaming across the facades, creating sharp contrasts and lively reflections. Crowds of tourists are visible on the far bank, while colorful banners and flowerpots accent the architecture. The composition is balanced, with attention to perspective and depth, and the general mood is lively and picturesque."
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
In case of errors (invalid URL, fetch issues, inappropriate filetype, etc.), a descriptive error message is returned:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"success": false,
|
|
53
|
+
"error": "Failed to fetch or validate image from URL: https://example.com/broken.jpg",
|
|
54
|
+
"result": null
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Typical Use Cases
|
|
61
|
+
|
|
62
|
+
- **Accessibility:** Generate alt-text for visually impaired users.
|
|
63
|
+
- **AI Agents:** Understand and react to visual content in workflow automations.
|
|
64
|
+
- **Search & Tagging:** Automatically caption and index photo libraries.
|
|
65
|
+
- **Content Moderation:** Pre-screen or context-check image uploads.
|
|
66
|
+
- **Educational Tools:** Explain or transcribe visual materials for students.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Advanced Notes
|
|
71
|
+
|
|
72
|
+
- The tool only works with image URLs that are publicly accessible and in a common web format (JPG, PNG, etc).
|
|
73
|
+
- Image URLs are validated and, where necessary, format-normalized using Pillow.
|
|
74
|
+
- The system never stores or caches the image, but will download it temporarily for analysis.
|
|
75
|
+
|
|
76
|
+
**Model Details**
|
|
77
|
+
Venice AI leverages licensed large vision-language models; this tool currently uses `qwen-2.5-vl`, known for dense, multi-aspect, human-like image explanations.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Configuration Options
|
|
82
|
+
|
|
83
|
+
- No special options; inherits API key, safe mode, and base logging from the main suite configuration.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Limitations
|
|
88
|
+
|
|
89
|
+
- May not detect “hidden” content, steganographic messages, or small details lost in low-res images.
|
|
90
|
+
- Will describe as best possible—if the image is blank, corrupted, or unrelated, a best-effort bland description may be given.
|
|
91
|
+
- Not a content moderator—use with your own safety checks if required.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Example Usage (Pseudo-code)
|
|
96
|
+
```python
|
|
97
|
+
result = await agent.send_tool(
|
|
98
|
+
"image_vision",
|
|
99
|
+
{
|
|
100
|
+
"image_url": "https://mycdn.com/image.jpg"
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
desc = result["result"]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Attribution/Compliance
|
|
109
|
+
|
|
110
|
+
All usage subject to [Venice AI terms of service](https://venice.ai/). Do not use for unlawful or privacy-invading data mining.
|
|
111
|
+
|
|
112
|
+
---
|
|
File without changes
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Type
|
|
3
|
+
|
|
4
|
+
from langchain_core.runnables import RunnableConfig
|
|
5
|
+
from pydantic import BaseModel, HttpUrl
|
|
6
|
+
|
|
7
|
+
from intentkit.skills.base import ToolException
|
|
8
|
+
from intentkit.skills.venice_image.image_vision.image_vision_base import (
|
|
9
|
+
VeniceImageVisionBaseTool,
|
|
10
|
+
)
|
|
11
|
+
from intentkit.skills.venice_image.image_vision.image_vision_input import (
|
|
12
|
+
VeniceImageVision,
|
|
13
|
+
)
|
|
14
|
+
from intentkit.skills.venice_image.utils import fetch_image_as_base64
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ImageVision(VeniceImageVisionBaseTool):
|
|
20
|
+
"""
|
|
21
|
+
Describes an image provided via URL using the Venice AI API.
|
|
22
|
+
Ideal for understanding the content of an existing image.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
name: str = "venice_image_vision"
|
|
26
|
+
description: str = (
|
|
27
|
+
"Describes an image from a URL using Venice AI.\n"
|
|
28
|
+
"Provide the public URL of the image to describe.\n"
|
|
29
|
+
"Returns a descriptive text of the image."
|
|
30
|
+
)
|
|
31
|
+
args_schema: Type[BaseModel] = VeniceImageVision
|
|
32
|
+
# No model_id needed for the generic vision endpoint currently
|
|
33
|
+
|
|
34
|
+
async def _arun(
|
|
35
|
+
self,
|
|
36
|
+
image_url: HttpUrl,
|
|
37
|
+
config: RunnableConfig = None,
|
|
38
|
+
**kwargs,
|
|
39
|
+
) -> dict[str, Any]:
|
|
40
|
+
try:
|
|
41
|
+
context = self.context_from_config(config)
|
|
42
|
+
|
|
43
|
+
await self.apply_venice_rate_limit(context)
|
|
44
|
+
|
|
45
|
+
image_base64 = await fetch_image_as_base64(image_url)
|
|
46
|
+
if not image_base64:
|
|
47
|
+
error_msg = f"Failed to fetch or validate image from URL: {image_url}"
|
|
48
|
+
logger.error(error_msg)
|
|
49
|
+
return {"success": False, "error": error_msg, "result": None}
|
|
50
|
+
|
|
51
|
+
payload = {
|
|
52
|
+
"model": "qwen-2.5-vl",
|
|
53
|
+
"messages": [
|
|
54
|
+
{
|
|
55
|
+
"role": "system",
|
|
56
|
+
"content": [
|
|
57
|
+
{
|
|
58
|
+
"type": "text",
|
|
59
|
+
"text": (
|
|
60
|
+
"You are an AI model that provides detailed descriptions of images. "
|
|
61
|
+
"When given an image, you must respond with a description that is as comprehensive and detailed as possible. "
|
|
62
|
+
"Focus on identifying all objects, colors, textures, and any other relevant features present in the image. "
|
|
63
|
+
"Provide a thorough and exhaustive account of what is visible in the image."
|
|
64
|
+
),
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"role": "user",
|
|
70
|
+
"content": [
|
|
71
|
+
{
|
|
72
|
+
"type": "text",
|
|
73
|
+
"text": (
|
|
74
|
+
"Provide an extremely detailed description of the image, focusing on every discernible aspect. "
|
|
75
|
+
"Include information about objects, colors, textures, lighting conditions, artistic style (if applicable), "
|
|
76
|
+
"composition, and any other relevant details that would allow someone to accurately understand and potentially "
|
|
77
|
+
"recreate the image. Be as thorough and comprehensive as possible."
|
|
78
|
+
),
|
|
79
|
+
},
|
|
80
|
+
{"type": "image_url", "image_url": {"url": str(image_url)}},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
result, error = await self.post("api/v1/chat/completions", payload, context)
|
|
87
|
+
if error:
|
|
88
|
+
raise ToolException(f"Venice Image Vision API error: {error}")
|
|
89
|
+
return result
|
|
90
|
+
except ToolException as e:
|
|
91
|
+
return {
|
|
92
|
+
"success": False,
|
|
93
|
+
"error": f"An unexpected error occurred: {str(e)}",
|
|
94
|
+
}
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Error in {self.name}: {str(e)}")
|
|
97
|
+
return {
|
|
98
|
+
"success": False,
|
|
99
|
+
"error": f"An unexpected error occurred: {str(e)}",
|
|
100
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from pydantic import Field
|
|
2
|
+
|
|
3
|
+
# Import the generic base and shared input
|
|
4
|
+
from intentkit.skills.venice_image.base import VeniceImageBaseTool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class VeniceImageVisionBaseTool(VeniceImageBaseTool):
|
|
8
|
+
"""
|
|
9
|
+
Base class for Venice AI *Image Vision* tools.
|
|
10
|
+
Inherits from VeniceAIBaseTool and handles specifics of the
|
|
11
|
+
/chat/completions endpoint.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
name: str = Field(description="The unique name of the image vision tool.")
|
|
15
|
+
description: str = Field(
|
|
16
|
+
description="A description of what the image vision tool does."
|
|
17
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, HttpUrl
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class VeniceImageVision(BaseModel):
|
|
5
|
+
"""Input for the Image Vision tool."""
|
|
6
|
+
|
|
7
|
+
image_url: HttpUrl = Field(
|
|
8
|
+
description="The URL of the image to to be described by the Vision model. Must be a publicly accessible URL.",
|
|
9
|
+
)
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"title": "Venice Image",
|
|
5
|
+
"description": "Skills for generating images using the Venice AI API.",
|
|
6
|
+
"x-icon": "https://ai.service.crestal.dev/skills/venice_image/venice_image.jpg",
|
|
7
|
+
"x-tags": [
|
|
8
|
+
"AI",
|
|
9
|
+
"Image Generation"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"enabled": {
|
|
13
|
+
"type": "boolean",
|
|
14
|
+
"title": "Enabled",
|
|
15
|
+
"description": "Whether this skill category is enabled",
|
|
16
|
+
"default": false
|
|
17
|
+
},
|
|
18
|
+
"states": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"title": "Skill States",
|
|
21
|
+
"description": "States for each Venice Image skill (disabled, public, or private)",
|
|
22
|
+
"properties": {
|
|
23
|
+
"image_vision": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"title": "Image Vision",
|
|
26
|
+
"enum": [
|
|
27
|
+
"disabled",
|
|
28
|
+
"public",
|
|
29
|
+
"private"
|
|
30
|
+
],
|
|
31
|
+
"x-enum-title": [
|
|
32
|
+
"Disabled",
|
|
33
|
+
"Agent Owner + All Users",
|
|
34
|
+
"Agent Owner Only"
|
|
35
|
+
],
|
|
36
|
+
"description": "Describes an image provided via URL using the Venice AI API. Ideal for understanding the content of an existing image",
|
|
37
|
+
"default": "public"
|
|
38
|
+
},
|
|
39
|
+
"image_enchance": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"title": "Image Enchance",
|
|
42
|
+
"enum": [
|
|
43
|
+
"disabled",
|
|
44
|
+
"public",
|
|
45
|
+
"private"
|
|
46
|
+
],
|
|
47
|
+
"x-enum-title": [
|
|
48
|
+
"Disabled",
|
|
49
|
+
"Agent Owner + All Users",
|
|
50
|
+
"Agent Owner Only"
|
|
51
|
+
],
|
|
52
|
+
"description": "Tool for **Enchance** (modifying specific areas of) an existing image using a selected image model via Venice AI",
|
|
53
|
+
"default": "public"
|
|
54
|
+
},
|
|
55
|
+
"image_upscale": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"title": "Image Upscale",
|
|
58
|
+
"enum": [
|
|
59
|
+
"disabled",
|
|
60
|
+
"public",
|
|
61
|
+
"private"
|
|
62
|
+
],
|
|
63
|
+
"x-enum-title": [
|
|
64
|
+
"Disabled",
|
|
65
|
+
"Agent Owner + All Users",
|
|
66
|
+
"Agent Owner Only"
|
|
67
|
+
],
|
|
68
|
+
"description": "Upscale an existing image by 2x or 4x using Venice AI.",
|
|
69
|
+
"default": "disabled"
|
|
70
|
+
},
|
|
71
|
+
"image_generation_flux_dev": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"title": "Image Generation (Flux-Dev)",
|
|
74
|
+
"enum": [
|
|
75
|
+
"disabled",
|
|
76
|
+
"public",
|
|
77
|
+
"private"
|
|
78
|
+
],
|
|
79
|
+
"x-enum-title": [
|
|
80
|
+
"Disabled",
|
|
81
|
+
"Agent Owner + All Users",
|
|
82
|
+
"Agent Owner Only"
|
|
83
|
+
],
|
|
84
|
+
"description": "Generate images using Venice AI's Flux Dev model (research, art workflows).",
|
|
85
|
+
"default": "public"
|
|
86
|
+
},
|
|
87
|
+
"image_generation_flux_dev_uncensored": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"title": "Image Generation (Flux-Dev-Uncensored)",
|
|
90
|
+
"enum": [
|
|
91
|
+
"disabled",
|
|
92
|
+
"public",
|
|
93
|
+
"private"
|
|
94
|
+
],
|
|
95
|
+
"x-enum-title": [
|
|
96
|
+
"Disabled",
|
|
97
|
+
"Agent Owner + All Users",
|
|
98
|
+
"Agent Owner Only"
|
|
99
|
+
],
|
|
100
|
+
"description": "Generate images using the uncensored Flux Dev model (unrestricted, NSFW).",
|
|
101
|
+
"default": "disabled"
|
|
102
|
+
},
|
|
103
|
+
"image_generation_venice_sd35": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"title": "Image Generation (Venice SD3.5)",
|
|
106
|
+
"enum": [
|
|
107
|
+
"disabled",
|
|
108
|
+
"public",
|
|
109
|
+
"private"
|
|
110
|
+
],
|
|
111
|
+
"x-enum-title": [
|
|
112
|
+
"Disabled",
|
|
113
|
+
"Agent Owner + All Users",
|
|
114
|
+
"Agent Owner Only"
|
|
115
|
+
],
|
|
116
|
+
"description": "Generate images using Stability AI's SD 3.5 Large (art, design).",
|
|
117
|
+
"default": "disabled"
|
|
118
|
+
},
|
|
119
|
+
"image_generation_fluently_xl": {
|
|
120
|
+
"type": "string",
|
|
121
|
+
"title": "Image Generation (Fluently-XL)",
|
|
122
|
+
"enum": [
|
|
123
|
+
"disabled",
|
|
124
|
+
"public",
|
|
125
|
+
"private"
|
|
126
|
+
],
|
|
127
|
+
"x-enum-title": [
|
|
128
|
+
"Disabled",
|
|
129
|
+
"Agent Owner + All Users",
|
|
130
|
+
"Agent Owner Only"
|
|
131
|
+
],
|
|
132
|
+
"description": "Generate images using Fluently-XL (aesthetics, lighting, realism).",
|
|
133
|
+
"default": "disabled"
|
|
134
|
+
},
|
|
135
|
+
"image_generation_lustify_sdxl": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"title": "Image Generation (Lustify-SDXL)",
|
|
138
|
+
"enum": [
|
|
139
|
+
"disabled",
|
|
140
|
+
"public",
|
|
141
|
+
"private"
|
|
142
|
+
],
|
|
143
|
+
"x-enum-title": [
|
|
144
|
+
"Disabled",
|
|
145
|
+
"Agent Owner + All Users",
|
|
146
|
+
"Agent Owner Only"
|
|
147
|
+
],
|
|
148
|
+
"description": "Generate images using Lustify SDXL (photorealistic, focus on NSFW).",
|
|
149
|
+
"default": "disabled"
|
|
150
|
+
},
|
|
151
|
+
"image_generation_pony_realism": {
|
|
152
|
+
"type": "string",
|
|
153
|
+
"title": "Image Generation (Pony-Realism)",
|
|
154
|
+
"enum": [
|
|
155
|
+
"disabled",
|
|
156
|
+
"public",
|
|
157
|
+
"private"
|
|
158
|
+
],
|
|
159
|
+
"x-enum-title": [
|
|
160
|
+
"Disabled",
|
|
161
|
+
"Agent Owner + All Users",
|
|
162
|
+
"Agent Owner Only"
|
|
163
|
+
],
|
|
164
|
+
"description": "Generate images using Pony Realism (high-detail, realistic, anime/characters).",
|
|
165
|
+
"default": "disabled"
|
|
166
|
+
},
|
|
167
|
+
"image_generation_stable_diffusion_3_5": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"title": "Image Generation (Stable Diffusion 3.5 - Alt ID)",
|
|
170
|
+
"enum": [
|
|
171
|
+
"disabled",
|
|
172
|
+
"public",
|
|
173
|
+
"private"
|
|
174
|
+
],
|
|
175
|
+
"x-enum-title": [
|
|
176
|
+
"Disabled",
|
|
177
|
+
"Agent Owner + All Users",
|
|
178
|
+
"Agent Owner Only"
|
|
179
|
+
],
|
|
180
|
+
"description": "Generate images using Stability AI's SD 3.5 Large (alternative API ID).",
|
|
181
|
+
"default": "disabled"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"safe_mode": {
|
|
186
|
+
"type": "boolean",
|
|
187
|
+
"title": "Safe Mode",
|
|
188
|
+
"description": "Whether to use safe mode. If enabled, this will blur images that are classified as having adult content",
|
|
189
|
+
"default": true
|
|
190
|
+
},
|
|
191
|
+
"embed_exif_metadata": {
|
|
192
|
+
"type": "boolean",
|
|
193
|
+
"title": "Embed Exif Metadata",
|
|
194
|
+
"description": "Embed prompt generation information into the image's EXIF metadata",
|
|
195
|
+
"default": false
|
|
196
|
+
},
|
|
197
|
+
"hide_watermark": {
|
|
198
|
+
"type": "boolean",
|
|
199
|
+
"title": "Hide Watermark",
|
|
200
|
+
"description": "Whether to hide the Venice watermark. Venice may ignore this parameter for certain generated content.",
|
|
201
|
+
"default": true
|
|
202
|
+
},
|
|
203
|
+
"negative_prompt": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"title": "Default Negative Prompt",
|
|
206
|
+
"description": "Default negative prompt to use if none is provided in the skill call.",
|
|
207
|
+
"default": "(worst quality: 1.4), bad quality, nsfw"
|
|
208
|
+
},
|
|
209
|
+
"api_key_provider": {
|
|
210
|
+
"type": "string",
|
|
211
|
+
"title": "API Key Provider",
|
|
212
|
+
"description": "Provider of the API key for AIXBT API service",
|
|
213
|
+
"enum": [
|
|
214
|
+
"agent_owner"
|
|
215
|
+
],
|
|
216
|
+
"x-enum-title": [
|
|
217
|
+
"Owner Provided"
|
|
218
|
+
],
|
|
219
|
+
"default": "agent_owner"
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"required": [
|
|
223
|
+
"states",
|
|
224
|
+
"enabled"
|
|
225
|
+
],
|
|
226
|
+
"if": {
|
|
227
|
+
"properties": {
|
|
228
|
+
"api_key_provider": {
|
|
229
|
+
"const": "agent_owner"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"then": {
|
|
234
|
+
"properties": {
|
|
235
|
+
"api_key": {
|
|
236
|
+
"type": "string",
|
|
237
|
+
"title": "Venice API Key",
|
|
238
|
+
"x-link": "[Get your API key](https://venice.ai/)",
|
|
239
|
+
"x-sensitive": true,
|
|
240
|
+
"description": "Optional API key for Venice AI services. If not provided, the system key will be used."
|
|
241
|
+
},
|
|
242
|
+
"rate_limit_number": {
|
|
243
|
+
"type": "integer",
|
|
244
|
+
"title": "Rate Limit Number",
|
|
245
|
+
"description": "Number of requests allowed per time window. Only applies if using an agent-specific API key."
|
|
246
|
+
},
|
|
247
|
+
"rate_limit_minutes": {
|
|
248
|
+
"type": "integer",
|
|
249
|
+
"title": "Rate Limit Minutes",
|
|
250
|
+
"description": "Time window in minutes for rate limiting. Only applies if using an agent-specific API key."
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"if": {
|
|
254
|
+
"properties": {
|
|
255
|
+
"enabled": {
|
|
256
|
+
"const": true
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
"then": {
|
|
261
|
+
"required": [
|
|
262
|
+
"api_key"
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"additionalProperties": true
|
|
267
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import io
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import filetype
|
|
7
|
+
import httpx
|
|
8
|
+
from PIL import Image
|
|
9
|
+
from pydantic import HttpUrl
|
|
10
|
+
|
|
11
|
+
from intentkit.skills.base import ToolException
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def fetch_image_as_bytes(image_url: HttpUrl) -> bytes:
|
|
17
|
+
"""Fetches image bytes from a given URL. Converts unsupported formats to PNG using Pillow.
|
|
18
|
+
|
|
19
|
+
Raises:
|
|
20
|
+
ToolException: If fetching or converting the image fails.
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
async with httpx.AsyncClient(timeout=90) as client:
|
|
24
|
+
response = await client.get(str(image_url), follow_redirects=True)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
|
|
27
|
+
original_bytes = response.content
|
|
28
|
+
|
|
29
|
+
# Guess file type from content
|
|
30
|
+
kind = filetype.guess(original_bytes)
|
|
31
|
+
detected_ext = kind.extension if kind else None
|
|
32
|
+
detected_mime = kind.mime if kind else "unknown"
|
|
33
|
+
|
|
34
|
+
if not detected_ext or not detected_mime.startswith("image/"):
|
|
35
|
+
msg = f"URL {image_url} did not return a recognizable image format. Detected: {detected_mime}"
|
|
36
|
+
logger.error(msg)
|
|
37
|
+
raise ToolException(msg)
|
|
38
|
+
|
|
39
|
+
if detected_ext in ("jpg", "jpeg", "png"):
|
|
40
|
+
return original_bytes
|
|
41
|
+
|
|
42
|
+
# Convert unsupported image to PNG
|
|
43
|
+
try:
|
|
44
|
+
img = Image.open(io.BytesIO(original_bytes)).convert("RGBA")
|
|
45
|
+
with io.BytesIO() as output:
|
|
46
|
+
img.save(output, format="PNG")
|
|
47
|
+
logger.info(
|
|
48
|
+
f"Converted unsupported image type '{detected_ext}' to PNG."
|
|
49
|
+
)
|
|
50
|
+
return output.getvalue()
|
|
51
|
+
except Exception as e:
|
|
52
|
+
msg = f"Failed to convert image ({detected_ext}) to PNG: {e}"
|
|
53
|
+
logger.error(msg, exc_info=True)
|
|
54
|
+
raise ToolException(msg) from e
|
|
55
|
+
|
|
56
|
+
except httpx.HTTPStatusError as e:
|
|
57
|
+
msg = f"HTTP error fetching image {image_url}: Status {e.response.status_code}"
|
|
58
|
+
logger.error(msg)
|
|
59
|
+
raise ToolException(msg) from e
|
|
60
|
+
except httpx.RequestError as e:
|
|
61
|
+
msg = f"Network error fetching image {image_url}: {e}"
|
|
62
|
+
logger.error(msg)
|
|
63
|
+
raise ToolException(msg) from e
|
|
64
|
+
except Exception as e:
|
|
65
|
+
msg = f"Unexpected error fetching image {image_url}: {e}"
|
|
66
|
+
logger.error(msg, exc_info=True)
|
|
67
|
+
raise ToolException(msg) from e
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def fetch_image_as_base64(image_url: HttpUrl) -> Optional[str]:
|
|
71
|
+
"""Fetches an image from the URL and returns the image as a Base64-encoded string."""
|
|
72
|
+
image_bytes = await fetch_image_as_bytes(image_url)
|
|
73
|
+
|
|
74
|
+
if image_bytes is None:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
# Convert image bytes to a Base64-encoded string
|
|
78
|
+
return base64.b64encode(image_bytes).decode("utf-8")
|
|
Binary file
|