intentkit 0.6.9.dev2__py3-none-any.whl → 0.6.10.dev2__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.

Files changed (168) hide show
  1. intentkit/__init__.py +1 -1
  2. intentkit/abstracts/graph.py +17 -2
  3. intentkit/core/engine.py +49 -30
  4. intentkit/core/node.py +10 -20
  5. intentkit/models/agent.py +3 -0
  6. intentkit/models/chat.py +9 -1
  7. intentkit/skills/acolyt/ask.py +2 -5
  8. intentkit/skills/acolyt/base.py +16 -6
  9. intentkit/skills/aixbt/__init__.py +3 -7
  10. intentkit/skills/aixbt/projects.py +12 -36
  11. intentkit/skills/allora/base.py +16 -6
  12. intentkit/skills/allora/price.py +2 -4
  13. intentkit/skills/base.py +8 -1
  14. intentkit/skills/carv/base.py +12 -10
  15. intentkit/skills/carv/fetch_news.py +90 -92
  16. intentkit/skills/carv/onchain_query.py +162 -164
  17. intentkit/skills/carv/token_info_and_price.py +108 -110
  18. intentkit/skills/chainlist/chain_lookup.py +1 -2
  19. intentkit/skills/common/current_time.py +1 -2
  20. intentkit/skills/cookiefun/base.py +20 -12
  21. intentkit/skills/cookiefun/get_account_details.py +1 -3
  22. intentkit/skills/cookiefun/get_account_feed.py +1 -3
  23. intentkit/skills/cookiefun/get_account_smart_followers.py +1 -3
  24. intentkit/skills/cookiefun/get_sectors.py +2 -3
  25. intentkit/skills/cookiefun/search_accounts.py +1 -3
  26. intentkit/skills/cryptocompare/fetch_news.py +3 -4
  27. intentkit/skills/cryptocompare/fetch_price.py +3 -4
  28. intentkit/skills/cryptocompare/fetch_top_exchanges.py +3 -4
  29. intentkit/skills/cryptocompare/fetch_top_market_cap.py +3 -4
  30. intentkit/skills/cryptocompare/fetch_top_volume.py +3 -4
  31. intentkit/skills/cryptocompare/fetch_trading_signals.py +3 -4
  32. intentkit/skills/cryptopanic/base.py +13 -9
  33. intentkit/skills/cryptopanic/fetch_crypto_news.py +150 -153
  34. intentkit/skills/cryptopanic/fetch_crypto_sentiment.py +133 -136
  35. intentkit/skills/dapplooker/base.py +16 -6
  36. intentkit/skills/dapplooker/dapplooker_token_data.py +2 -4
  37. intentkit/skills/defillama/coins/fetch_batch_historical_prices.py +2 -3
  38. intentkit/skills/defillama/coins/fetch_block.py +2 -3
  39. intentkit/skills/defillama/coins/fetch_current_prices.py +2 -5
  40. intentkit/skills/defillama/coins/fetch_first_price.py +2 -5
  41. intentkit/skills/defillama/coins/fetch_historical_prices.py +2 -3
  42. intentkit/skills/defillama/coins/fetch_price_chart.py +2 -5
  43. intentkit/skills/defillama/coins/fetch_price_percentage.py +2 -5
  44. intentkit/skills/defillama/fees/fetch_fees_overview.py +2 -3
  45. intentkit/skills/defillama/stablecoins/fetch_stablecoin_chains.py +2 -3
  46. intentkit/skills/defillama/stablecoins/fetch_stablecoin_charts.py +2 -3
  47. intentkit/skills/defillama/stablecoins/fetch_stablecoin_prices.py +2 -3
  48. intentkit/skills/defillama/stablecoins/fetch_stablecoins.py +2 -3
  49. intentkit/skills/defillama/tvl/fetch_chain_historical_tvl.py +2 -5
  50. intentkit/skills/defillama/tvl/fetch_chains.py +2 -3
  51. intentkit/skills/defillama/tvl/fetch_historical_tvl.py +2 -3
  52. intentkit/skills/defillama/tvl/fetch_protocol.py +2 -5
  53. intentkit/skills/defillama/tvl/fetch_protocol_current_tvl.py +2 -5
  54. intentkit/skills/defillama/tvl/fetch_protocols.py +2 -3
  55. intentkit/skills/defillama/volumes/fetch_dex_overview.py +2 -3
  56. intentkit/skills/defillama/volumes/fetch_dex_summary.py +2 -5
  57. intentkit/skills/defillama/volumes/fetch_options_overview.py +2 -3
  58. intentkit/skills/defillama/yields/fetch_pool_chart.py +2 -5
  59. intentkit/skills/defillama/yields/fetch_pools.py +2 -3
  60. intentkit/skills/dune_analytics/base.py +15 -9
  61. intentkit/skills/dune_analytics/fetch_kol_buys.py +125 -128
  62. intentkit/skills/dune_analytics/fetch_nation_metrics.py +234 -237
  63. intentkit/skills/elfa/base.py +16 -6
  64. intentkit/skills/elfa/mention.py +2 -7
  65. intentkit/skills/elfa/stats.py +2 -6
  66. intentkit/skills/elfa/tokens.py +1 -4
  67. intentkit/skills/enso/base.py +25 -13
  68. intentkit/skills/enso/best_yield.py +1 -4
  69. intentkit/skills/enso/networks.py +2 -5
  70. intentkit/skills/enso/prices.py +1 -5
  71. intentkit/skills/enso/route.py +2 -5
  72. intentkit/skills/enso/tokens.py +1 -4
  73. intentkit/skills/enso/wallet.py +3 -9
  74. intentkit/skills/firecrawl/base.py +16 -6
  75. intentkit/skills/firecrawl/clear.py +1 -3
  76. intentkit/skills/firecrawl/crawl.py +7 -8
  77. intentkit/skills/firecrawl/query.py +7 -9
  78. intentkit/skills/firecrawl/scrape.py +7 -8
  79. intentkit/skills/github/github_search.py +1 -3
  80. intentkit/skills/heurist/base.py +15 -0
  81. intentkit/skills/heurist/image_generation_animagine_xl.py +3 -4
  82. intentkit/skills/heurist/image_generation_arthemy_comics.py +3 -4
  83. intentkit/skills/heurist/image_generation_arthemy_real.py +3 -4
  84. intentkit/skills/heurist/image_generation_braindance.py +3 -4
  85. intentkit/skills/heurist/image_generation_cyber_realistic_xl.py +3 -4
  86. intentkit/skills/heurist/image_generation_flux_1_dev.py +3 -4
  87. intentkit/skills/heurist/image_generation_sdxl.py +3 -4
  88. intentkit/skills/http/get.py +0 -2
  89. intentkit/skills/http/post.py +0 -2
  90. intentkit/skills/http/put.py +0 -2
  91. intentkit/skills/lifi/token_execute.py +1 -3
  92. intentkit/skills/lifi/token_quote.py +0 -2
  93. intentkit/skills/moralis/base.py +15 -1
  94. intentkit/skills/nation/nft_check.py +2 -5
  95. intentkit/skills/openai/base.py +14 -5
  96. intentkit/skills/openai/dalle_image_generation.py +6 -5
  97. intentkit/skills/openai/gpt_image_generation.py +6 -5
  98. intentkit/skills/openai/gpt_image_to_image.py +6 -5
  99. intentkit/skills/openai/image_to_text.py +6 -6
  100. intentkit/skills/portfolio/base.py +4 -3
  101. intentkit/skills/portfolio/token_balances.py +2 -4
  102. intentkit/skills/portfolio/wallet_approvals.py +2 -4
  103. intentkit/skills/portfolio/wallet_defi_positions.py +3 -4
  104. intentkit/skills/portfolio/wallet_history.py +2 -4
  105. intentkit/skills/portfolio/wallet_net_worth.py +2 -4
  106. intentkit/skills/portfolio/wallet_nfts.py +2 -4
  107. intentkit/skills/portfolio/wallet_profitability.py +2 -4
  108. intentkit/skills/portfolio/wallet_profitability_summary.py +2 -4
  109. intentkit/skills/portfolio/wallet_stats.py +2 -4
  110. intentkit/skills/portfolio/wallet_swaps.py +2 -4
  111. intentkit/skills/slack/base.py +18 -0
  112. intentkit/skills/slack/get_channel.py +3 -4
  113. intentkit/skills/slack/get_message.py +3 -4
  114. intentkit/skills/slack/schedule_message.py +3 -4
  115. intentkit/skills/slack/send_message.py +3 -4
  116. intentkit/skills/supabase/delete_data.py +3 -6
  117. intentkit/skills/supabase/fetch_data.py +3 -6
  118. intentkit/skills/supabase/insert_data.py +3 -6
  119. intentkit/skills/supabase/invoke_function.py +3 -6
  120. intentkit/skills/supabase/update_data.py +3 -6
  121. intentkit/skills/supabase/upsert_data.py +3 -6
  122. intentkit/skills/system/add_autonomous_task.py +1 -3
  123. intentkit/skills/system/delete_autonomous_task.py +1 -3
  124. intentkit/skills/system/edit_autonomous_task.py +1 -3
  125. intentkit/skills/system/list_autonomous_tasks.py +1 -3
  126. intentkit/skills/system/read_agent_api_key.py +2 -3
  127. intentkit/skills/system/regenerate_agent_api_key.py +2 -5
  128. intentkit/skills/tavily/base.py +14 -5
  129. intentkit/skills/tavily/tavily_extract.py +7 -8
  130. intentkit/skills/tavily/tavily_search.py +11 -9
  131. intentkit/skills/token/base.py +4 -6
  132. intentkit/skills/token/erc20_transfers.py +2 -4
  133. intentkit/skills/token/token_analytics.py +2 -4
  134. intentkit/skills/token/token_price.py +2 -4
  135. intentkit/skills/token/token_search.py +2 -4
  136. intentkit/skills/twitter/base.py +41 -0
  137. intentkit/skills/twitter/follow_user.py +4 -4
  138. intentkit/skills/twitter/get_mentions.py +4 -4
  139. intentkit/skills/twitter/get_timeline.py +4 -4
  140. intentkit/skills/twitter/get_user_by_username.py +4 -4
  141. intentkit/skills/twitter/get_user_tweets.py +4 -4
  142. intentkit/skills/twitter/like_tweet.py +4 -4
  143. intentkit/skills/twitter/post_tweet.py +3 -4
  144. intentkit/skills/twitter/reply_tweet.py +3 -4
  145. intentkit/skills/twitter/retweet.py +4 -4
  146. intentkit/skills/twitter/search_tweets.py +4 -4
  147. intentkit/skills/unrealspeech/base.py +16 -0
  148. intentkit/skills/unrealspeech/text_to_speech.py +4 -4
  149. intentkit/skills/venice_audio/base.py +11 -9
  150. intentkit/skills/venice_audio/venice_audio.py +238 -240
  151. intentkit/skills/venice_image/base.py +23 -19
  152. intentkit/skills/venice_image/image_enhance/image_enhance.py +78 -80
  153. intentkit/skills/venice_image/image_generation/image_generation_base.py +115 -117
  154. intentkit/skills/venice_image/image_upscale/image_upscale.py +88 -90
  155. intentkit/skills/venice_image/image_vision/image_vision.py +98 -100
  156. intentkit/skills/web_scraper/document_indexer.py +3 -5
  157. intentkit/skills/web_scraper/scrape_and_index.py +14 -17
  158. intentkit/skills/web_scraper/website_indexer.py +8 -10
  159. intentkit/skills/xmtp/README.md +110 -0
  160. intentkit/skills/xmtp/__init__.py +82 -0
  161. intentkit/skills/xmtp/base.py +15 -0
  162. intentkit/skills/xmtp/schema.json +41 -0
  163. intentkit/skills/xmtp/transfer.py +155 -0
  164. intentkit/skills/xmtp/xmtp.svg +26 -0
  165. {intentkit-0.6.9.dev2.dist-info → intentkit-0.6.10.dev2.dist-info}/METADATA +3 -3
  166. {intentkit-0.6.9.dev2.dist-info → intentkit-0.6.10.dev2.dist-info}/RECORD +168 -162
  167. {intentkit-0.6.9.dev2.dist-info → intentkit-0.6.10.dev2.dist-info}/WHEEL +0 -0
  168. {intentkit-0.6.9.dev2.dist-info → intentkit-0.6.10.dev2.dist-info}/licenses/LICENSE +0 -0
@@ -1,80 +1,78 @@
1
- import logging
2
- from typing import Optional
3
-
4
- from langchain_core.runnables import RunnableConfig
5
- from pydantic import HttpUrl
6
-
7
- from intentkit.skills.base import ToolException
8
- from intentkit.skills.venice_image.image_enhance.image_enhance_base import (
9
- VeniceImageEnhanceBaseTool,
10
- )
11
- from intentkit.skills.venice_image.utils import fetch_image_as_base64
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
-
16
- class ImageEnhance(VeniceImageEnhanceBaseTool):
17
- """
18
- Enhances an existing image provided via URL using the Venice AI enhancer (not upscaling).
19
- Useful for improving visual quality, adding style, or refining image features.
20
- """
21
-
22
- name: str = "venice_image_enhance"
23
- description: str = (
24
- "Enhances an existing image from a URL using Venice AI.\n"
25
- "Provide the public URL of the image to enhance.\n"
26
- "Specify enhancement creativity level and a required prompt for style.\n"
27
- "Returns the URL of the enhanced image."
28
- )
29
-
30
- async def _arun(
31
- self,
32
- image_url: HttpUrl,
33
- enhancePrompt: str,
34
- replication: Optional[float] = 0.35,
35
- enhanceCreativity: Optional[float] = 0.5,
36
- config: RunnableConfig = None,
37
- **kwargs,
38
- ) -> dict:
39
- """
40
- Applies AI enhancement to an image without changing its size.
41
- """
42
-
43
- try:
44
- context = self.context_from_config(config)
45
-
46
- await self.apply_venice_rate_limit(context)
47
-
48
- image_base64 = await fetch_image_as_base64(image_url)
49
- if not image_base64:
50
- error_msg = f"Failed to fetch or validate image from URL: {image_url}"
51
- logger.error(error_msg)
52
- raise ToolException(
53
- str({"success": False, "error": error_msg, "result": None})
54
- )
55
-
56
- payload = {
57
- "image": image_base64,
58
- "scale": 1,
59
- "enhance": True,
60
- "replication": replication,
61
- "enhanceCreativity": enhanceCreativity,
62
- "enhancePrompt": enhancePrompt,
63
- }
64
-
65
- result, error = await self.post("api/v1/image/upscale", payload, context)
66
- if error:
67
- raise ToolException(f"Venice Image Enhance API error: {error}")
68
- return result
69
- except ToolException as e:
70
- raise e
71
- except Exception as e:
72
- logger.error(f"Error in {self.name}: {str(e)}")
73
- raise ToolException(
74
- str(
75
- {
76
- "success": False,
77
- "error": f"An unexpected error occurred: {str(e)}",
78
- }
79
- )
80
- )
1
+ import logging
2
+ from typing import Optional
3
+
4
+ from pydantic import HttpUrl
5
+
6
+ from intentkit.skills.base import ToolException
7
+ from intentkit.skills.venice_image.image_enhance.image_enhance_base import (
8
+ VeniceImageEnhanceBaseTool,
9
+ )
10
+ from intentkit.skills.venice_image.utils import fetch_image_as_base64
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class ImageEnhance(VeniceImageEnhanceBaseTool):
16
+ """
17
+ Enhances an existing image provided via URL using the Venice AI enhancer (not upscaling).
18
+ Useful for improving visual quality, adding style, or refining image features.
19
+ """
20
+
21
+ name: str = "venice_image_enhance"
22
+ description: str = (
23
+ "Enhances an existing image from a URL using Venice AI.\n"
24
+ "Provide the public URL of the image to enhance.\n"
25
+ "Specify enhancement creativity level and a required prompt for style.\n"
26
+ "Returns the URL of the enhanced image."
27
+ )
28
+
29
+ async def _arun(
30
+ self,
31
+ image_url: HttpUrl,
32
+ enhancePrompt: str,
33
+ replication: Optional[float] = 0.35,
34
+ enhanceCreativity: Optional[float] = 0.5,
35
+ **kwargs,
36
+ ) -> dict:
37
+ """
38
+ Applies AI enhancement to an image without changing its size.
39
+ """
40
+
41
+ try:
42
+ context = self.get_context()
43
+
44
+ await self.apply_venice_rate_limit(context)
45
+
46
+ image_base64 = await fetch_image_as_base64(image_url)
47
+ if not image_base64:
48
+ error_msg = f"Failed to fetch or validate image from URL: {image_url}"
49
+ logger.error(error_msg)
50
+ raise ToolException(
51
+ str({"success": False, "error": error_msg, "result": None})
52
+ )
53
+
54
+ payload = {
55
+ "image": image_base64,
56
+ "scale": 1,
57
+ "enhance": True,
58
+ "replication": replication,
59
+ "enhanceCreativity": enhanceCreativity,
60
+ "enhancePrompt": enhancePrompt,
61
+ }
62
+
63
+ result, error = await self.post("api/v1/image/upscale", payload, context)
64
+ if error:
65
+ raise ToolException(f"Venice Image Enhance API error: {error}")
66
+ return result
67
+ except ToolException as e:
68
+ raise e
69
+ except Exception as e:
70
+ logger.error(f"Error in {self.name}: {str(e)}")
71
+ raise ToolException(
72
+ str(
73
+ {
74
+ "success": False,
75
+ "error": f"An unexpected error occurred: {str(e)}",
76
+ }
77
+ )
78
+ )
@@ -1,117 +1,115 @@
1
- import base64
2
- import hashlib
3
- import logging
4
- from typing import Any, Dict, Literal, Optional, Type
5
-
6
- from langchain_core.runnables import RunnableConfig
7
- from pydantic import BaseModel, Field
8
-
9
- # Import the generic base
10
- from intentkit.skills.base import ToolException
11
- from intentkit.skills.venice_image.base import VeniceImageBaseTool
12
- from intentkit.skills.venice_image.image_generation.image_generation_input import (
13
- VeniceImageGenerationInput,
14
- )
15
- from intentkit.utils.s3 import store_image_bytes
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
-
20
- class VeniceImageGenerationBaseTool(VeniceImageBaseTool):
21
- """
22
- Base class for Venice AI *Image Generation* tools.
23
- Inherits from VeniceAIBaseTool and handles specifics of the
24
- /image/generate endpoint.
25
- """
26
-
27
- # --- Attributes specific to Image Generation ---
28
- args_schema: Type[BaseModel] = VeniceImageGenerationInput
29
-
30
- # --- Attributes Subclasses MUST Define ---
31
- name: str = Field(description="The unique name of the image generation tool/model.")
32
- description: str = Field(
33
- description="A description of what the image generation tool/model does."
34
- )
35
- model_id: str = Field(
36
- description="The specific model ID used in the Venice Image API call."
37
- )
38
-
39
- async def _arun(
40
- self,
41
- prompt: str,
42
- seed: Optional[int] = None,
43
- negative_prompt: Optional[str] = None,
44
- width: Optional[int] = 1024,
45
- height: Optional[int] = 1024,
46
- format: Literal["png", "jpeg", "webp"] = "png",
47
- cfg_scale: Optional[float] = 7.5,
48
- style_preset: Optional[str] = "Photographic",
49
- config: RunnableConfig = None,
50
- **kwargs,
51
- ) -> Dict[str, Any]:
52
- try:
53
- context = self.context_from_config(config)
54
- skillConfig = self.getSkillConfig(context)
55
- await self.apply_venice_rate_limit(context)
56
-
57
- final_negative_prompt = negative_prompt or skillConfig.negative_prompt
58
-
59
- payload = {
60
- "model": self.model_id,
61
- "prompt": prompt,
62
- "width": width,
63
- "height": height,
64
- "seed": seed,
65
- "format": format,
66
- "steps": 30,
67
- "safe_mode": skillConfig.safe_mode,
68
- "hide_watermark": skillConfig.hide_watermark,
69
- "embed_exif_metadata": skillConfig.embed_exif_metadata,
70
- "cfg_scale": cfg_scale or 7.0,
71
- "style_preset": style_preset,
72
- "negative_prompt": final_negative_prompt,
73
- "return_binary": False,
74
- }
75
-
76
- # Strip out None values
77
- payload = {k: v for k, v in payload.items() if v is not None}
78
-
79
- result, error = await self.post("/api/v1/image/generate", payload, context)
80
-
81
- if error:
82
- raise ToolException(f"Venice Image Generation API error: {error}")
83
-
84
- base64_image_string = result.get("images", [None])[0]
85
- if not base64_image_string:
86
- raise ToolException("No image data found in Venice Image API response.")
87
-
88
- try:
89
- image_bytes = base64.b64decode(base64_image_string)
90
- except Exception as decode_error:
91
- raise ToolException("Invalid base64 image data.") from decode_error
92
-
93
- response_format = (
94
- result.get("request", {}).get("data", {}).get("format", format)
95
- )
96
- file_extension = response_format or format
97
- content_type = f"image/{file_extension}"
98
-
99
- image_hash = hashlib.sha256(image_bytes).hexdigest()
100
- key = f"{self.category}/{self.model_id}/{image_hash}.{file_extension}"
101
-
102
- stored_url = await store_image_bytes(
103
- image_bytes, key, content_type=content_type
104
- )
105
-
106
- # Cleanup & enrich the response
107
- result.pop("images", None)
108
- result["image_url"] = stored_url
109
- result["image_bytes_sha256"] = image_hash
110
-
111
- return result
112
- except ToolException as e:
113
- raise e
114
- except Exception as e:
115
- raise ToolException(
116
- "An unexpected error occurred during the image generation process."
117
- ) from e
1
+ import base64
2
+ import hashlib
3
+ import logging
4
+ from typing import Any, Dict, Literal, Optional, Type
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ # Import the generic base
9
+ from intentkit.skills.base import ToolException
10
+ from intentkit.skills.venice_image.base import VeniceImageBaseTool
11
+ from intentkit.skills.venice_image.image_generation.image_generation_input import (
12
+ VeniceImageGenerationInput,
13
+ )
14
+ from intentkit.utils.s3 import store_image_bytes
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class VeniceImageGenerationBaseTool(VeniceImageBaseTool):
20
+ """
21
+ Base class for Venice AI *Image Generation* tools.
22
+ Inherits from VeniceAIBaseTool and handles specifics of the
23
+ /image/generate endpoint.
24
+ """
25
+
26
+ # --- Attributes specific to Image Generation ---
27
+ args_schema: Type[BaseModel] = VeniceImageGenerationInput
28
+
29
+ # --- Attributes Subclasses MUST Define ---
30
+ name: str = Field(description="The unique name of the image generation tool/model.")
31
+ description: str = Field(
32
+ description="A description of what the image generation tool/model does."
33
+ )
34
+ model_id: str = Field(
35
+ description="The specific model ID used in the Venice Image API call."
36
+ )
37
+
38
+ async def _arun(
39
+ self,
40
+ prompt: str,
41
+ seed: Optional[int] = None,
42
+ negative_prompt: Optional[str] = None,
43
+ width: Optional[int] = 1024,
44
+ height: Optional[int] = 1024,
45
+ format: Literal["png", "jpeg", "webp"] = "png",
46
+ cfg_scale: Optional[float] = 7.5,
47
+ style_preset: Optional[str] = "Photographic",
48
+ **kwargs,
49
+ ) -> Dict[str, Any]:
50
+ try:
51
+ context = self.get_context()
52
+ skillConfig = self.getSkillConfig(context)
53
+ await self.apply_venice_rate_limit(context)
54
+
55
+ final_negative_prompt = negative_prompt or skillConfig.negative_prompt
56
+
57
+ payload = {
58
+ "model": self.model_id,
59
+ "prompt": prompt,
60
+ "width": width,
61
+ "height": height,
62
+ "seed": seed,
63
+ "format": format,
64
+ "steps": 30,
65
+ "safe_mode": skillConfig.safe_mode,
66
+ "hide_watermark": skillConfig.hide_watermark,
67
+ "embed_exif_metadata": skillConfig.embed_exif_metadata,
68
+ "cfg_scale": cfg_scale or 7.0,
69
+ "style_preset": style_preset,
70
+ "negative_prompt": final_negative_prompt,
71
+ "return_binary": False,
72
+ }
73
+
74
+ # Strip out None values
75
+ payload = {k: v for k, v in payload.items() if v is not None}
76
+
77
+ result, error = await self.post("/api/v1/image/generate", payload, context)
78
+
79
+ if error:
80
+ raise ToolException(f"Venice Image Generation API error: {error}")
81
+
82
+ base64_image_string = result.get("images", [None])[0]
83
+ if not base64_image_string:
84
+ raise ToolException("No image data found in Venice Image API response.")
85
+
86
+ try:
87
+ image_bytes = base64.b64decode(base64_image_string)
88
+ except Exception as decode_error:
89
+ raise ToolException("Invalid base64 image data.") from decode_error
90
+
91
+ response_format = (
92
+ result.get("request", {}).get("data", {}).get("format", format)
93
+ )
94
+ file_extension = response_format or format
95
+ content_type = f"image/{file_extension}"
96
+
97
+ image_hash = hashlib.sha256(image_bytes).hexdigest()
98
+ key = f"{self.category}/{self.model_id}/{image_hash}.{file_extension}"
99
+
100
+ stored_url = await store_image_bytes(
101
+ image_bytes, key, content_type=content_type
102
+ )
103
+
104
+ # Cleanup & enrich the response
105
+ result.pop("images", None)
106
+ result["image_url"] = stored_url
107
+ result["image_bytes_sha256"] = image_hash
108
+
109
+ return result
110
+ except ToolException as e:
111
+ raise e
112
+ except Exception as e:
113
+ raise ToolException(
114
+ "An unexpected error occurred during the image generation process."
115
+ ) from e
@@ -1,90 +1,88 @@
1
- import logging
2
- from typing import Literal, Optional
3
-
4
- from langchain_core.runnables import RunnableConfig
5
- from pydantic import HttpUrl
6
-
7
- from intentkit.skills.base import ToolException
8
- from intentkit.skills.venice_image.image_upscale.image_upscale_base import (
9
- VeniceImageUpscaleBaseTool,
10
- )
11
- from intentkit.skills.venice_image.utils import fetch_image_as_base64
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
-
16
- class ImageUpscale(VeniceImageUpscaleBaseTool):
17
- """
18
- Upscales an existing image provided via URL by a factor of 2 or 4 using the Venice AI API.
19
- Ideal for enhancing the resolution of previously generated or existing images.
20
- """
21
-
22
- # --- Tool Specific Configuration ---
23
- name: str = "venice_image_upscale"
24
- description: str = (
25
- "Upscales an existing image from a URL using Venice AI.\n"
26
- "Provide the public URL of the image to upscale.\n"
27
- "Specify the desired scale factor: 2 (for 2x upscale) or 4 (for 4x upscale).\n"
28
- "Returns the URL of the upscaled image."
29
- )
30
-
31
- # No model_id needed for the generic upscale endpoint currently
32
- async def _arun(
33
- self,
34
- image_url: HttpUrl,
35
- scale: Literal[2, 4],
36
- replication: Optional[float] = 0.35,
37
- config: RunnableConfig = None,
38
- **kwargs,
39
- ) -> dict:
40
- """
41
- Asynchronously upscales an image from the provided URL using the Venice AI API.
42
-
43
- Args:
44
- image_url (HttpUrl): The public URL of the image to upscale.
45
- scale (Literal[2, 4]): The scale factor for upscaling (2x or 4x).
46
- replication (Optional[float]): The replication factor for the upscale process, defaults to 0.35.
47
- config (RunnableConfig, optional): Configuration for the runnable, if any.
48
- **kwargs: Additional keyword arguments.
49
-
50
- Returns:
51
- dict: The API response containing the URL of the upscaled image.
52
-
53
- Raises:
54
- ToolException: If the image cannot be fetched, validated, or upscaled, or if an API error occurs.
55
- """
56
-
57
- try:
58
- context = self.context_from_config(config)
59
-
60
- await self.apply_venice_rate_limit(context)
61
-
62
- image_base64 = await fetch_image_as_base64(image_url)
63
- if not image_base64:
64
- error_msg = f"Failed to fetch or validate image from URL: {image_url}"
65
- logger.error(error_msg)
66
- raise ToolException(
67
- str({"success": False, "error": error_msg, "result": None})
68
- )
69
-
70
- payload = {
71
- "image": image_base64,
72
- "scale": scale,
73
- "replication": replication,
74
- }
75
- result, error = await self.post("api/v1/image/upscale", payload, context)
76
- if error:
77
- raise ToolException(f"Venice Image Upscale API error: {error}")
78
- return result
79
- except ToolException as e:
80
- raise e
81
- except Exception as e:
82
- logger.error(f"Error in {self.name}: {str(e)}")
83
- raise ToolException(
84
- str(
85
- {
86
- "success": False,
87
- "error": f"An unexpected error occurred: {str(e)}",
88
- }
89
- )
90
- )
1
+ import logging
2
+ from typing import Literal, Optional
3
+
4
+ from pydantic import HttpUrl
5
+
6
+ from intentkit.skills.base import ToolException
7
+ from intentkit.skills.venice_image.image_upscale.image_upscale_base import (
8
+ VeniceImageUpscaleBaseTool,
9
+ )
10
+ from intentkit.skills.venice_image.utils import fetch_image_as_base64
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class ImageUpscale(VeniceImageUpscaleBaseTool):
16
+ """
17
+ Upscales an existing image provided via URL by a factor of 2 or 4 using the Venice AI API.
18
+ Ideal for enhancing the resolution of previously generated or existing images.
19
+ """
20
+
21
+ # --- Tool Specific Configuration ---
22
+ name: str = "venice_image_upscale"
23
+ description: str = (
24
+ "Upscales an existing image from a URL using Venice AI.\n"
25
+ "Provide the public URL of the image to upscale.\n"
26
+ "Specify the desired scale factor: 2 (for 2x upscale) or 4 (for 4x upscale).\n"
27
+ "Returns the URL of the upscaled image."
28
+ )
29
+
30
+ # No model_id needed for the generic upscale endpoint currently
31
+ async def _arun(
32
+ self,
33
+ image_url: HttpUrl,
34
+ scale: Literal[2, 4],
35
+ replication: Optional[float] = 0.35,
36
+ **kwargs,
37
+ ) -> dict:
38
+ """
39
+ Asynchronously upscales an image from the provided URL using the Venice AI API.
40
+
41
+ Args:
42
+ image_url (HttpUrl): The public URL of the image to upscale.
43
+ scale (Literal[2, 4]): The scale factor for upscaling (2x or 4x).
44
+ replication (Optional[float]): The replication factor for the upscale process, defaults to 0.35.
45
+ config (RunnableConfig, optional): Configuration for the runnable, if any.
46
+ **kwargs: Additional keyword arguments.
47
+
48
+ Returns:
49
+ dict: The API response containing the URL of the upscaled image.
50
+
51
+ Raises:
52
+ ToolException: If the image cannot be fetched, validated, or upscaled, or if an API error occurs.
53
+ """
54
+
55
+ try:
56
+ context = self.get_context()
57
+
58
+ await self.apply_venice_rate_limit(context)
59
+
60
+ image_base64 = await fetch_image_as_base64(image_url)
61
+ if not image_base64:
62
+ error_msg = f"Failed to fetch or validate image from URL: {image_url}"
63
+ logger.error(error_msg)
64
+ raise ToolException(
65
+ str({"success": False, "error": error_msg, "result": None})
66
+ )
67
+
68
+ payload = {
69
+ "image": image_base64,
70
+ "scale": scale,
71
+ "replication": replication,
72
+ }
73
+ result, error = await self.post("api/v1/image/upscale", payload, context)
74
+ if error:
75
+ raise ToolException(f"Venice Image Upscale API error: {error}")
76
+ return result
77
+ except ToolException as e:
78
+ raise e
79
+ except Exception as e:
80
+ logger.error(f"Error in {self.name}: {str(e)}")
81
+ raise ToolException(
82
+ str(
83
+ {
84
+ "success": False,
85
+ "error": f"An unexpected error occurred: {str(e)}",
86
+ }
87
+ )
88
+ )