refactor: use subprocess to call ave-cloud-skill CLI scripts

Instead of importing library functions directly, now calling the
ave_data_rest.py CLI script via subprocess. This follows the
recommended approach from the SKILL.md documentation.

Changes:
- Add _call_ave_script helper method for subprocess calls
- Update search_tokens, get_token, get_price, get_risk to use CLI
- Set AVE_USE_DOCKER=false to run scripts directly without Docker
- Remove direct imports of ave.http module
This commit is contained in:
shokollm
2026-04-13 10:24:42 +00:00
parent 99dded8d16
commit 2b7f54703e

View File

@@ -317,48 +317,41 @@ class ConversationalAgent:
keyword = args.get("keyword", "") keyword = args.get("keyword", "")
limit = args.get("limit", 10) limit = args.get("limit", 10)
# Execute the tool using ave-cloud-skill code, output = self._call_ave_script(
import os "search",
import asyncio [
from ...core.config import get_settings "--keyword",
keyword,
settings = get_settings() "--chain",
os.environ["AVE_API_KEY"] = settings.AVE_API_KEY "bsc",
os.environ["API_PLAN"] = settings.AVE_API_PLAN "--limit",
str(limit),
from ave.http import api_get ],
resp = asyncio.run(
api_get(
"/tokens",
{
"keyword": keyword,
"limit": limit,
"chain": "bsc",
},
)
) )
if resp.status_code == 200: if code == 0:
data = resp.json() try:
tokens = data.get("data", {}).get("tokens", []) data = json.loads(output)
if tokens: tokens = data.get("data", {}).get("tokens", [])
token_list = "" if tokens:
for t in tokens[:limit]: token_list = ""
addr = t.get("token", "") for t in tokens[:limit]:
symbol = t.get("symbol", "") addr = t.get("token", "")
name = t.get("name", "") symbol = t.get("symbol", "")
price_change = t.get( name = t.get("name", "")
"token_price_change_24h", "N/A" price_change = t.get(
) "token_price_change_24h", "N/A"
mc = t.get("market_cap", "N/A") )
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: ${mc:,.0f} - 24h: {price_change}%\n" mc = t.get("market_cap", "N/A")
response_text = f"Here are the search results for '{keyword}' on BSC:\n\n{token_list}\nWould you like me to set up a strategy for any of these?" token_list += f"- **{symbol}** ({name}): `{addr}` - MC: ${mc:,.0f} - 24h: {price_change}%\n"
else: response_text = f"Here are the search results for '{keyword}' on BSC:\n\n{token_list}\nWould you like me to set up a strategy for any of these?"
response_text = f"No tokens found for '{keyword}'. Try a different keyword." else:
response_text = f"No tokens found for '{keyword}'. Try a different keyword."
except json.JSONDecodeError:
response_text = (
f"Failed to parse search results."
)
else: else:
response_text = ( response_text = f"Failed to search tokens: {output}"
f"Failed to search tokens: {resp.status_code}"
)
return { return {
"response": response_text, "response": response_text,
@@ -372,39 +365,36 @@ class ConversationalAgent:
address = args.get("address", "") address = args.get("address", "")
chain = args.get("chain", "bsc") chain = args.get("chain", "bsc")
import os code, output = self._call_ave_script(
import asyncio "token", ["--address", address, "--chain", chain]
from ...core.config import get_settings
settings = get_settings()
os.environ["AVE_API_KEY"] = settings.AVE_API_KEY
os.environ["API_PLAN"] = settings.AVE_API_PLAN
from ave.http import api_get
resp = asyncio.run(
api_get(f"/tokens/{address}-{chain}")
) )
if resp.status_code == 200: if code == 0:
data = resp.json() try:
token_data = data.get("data", {}) data = json.loads(output)
if token_data: token_data = data.get("data", {})
symbol = token_data.get("symbol", "N/A") if token_data:
name = token_data.get("name", "N/A") symbol = token_data.get("symbol", "N/A")
price = token_data.get("price", "N/A") name = token_data.get("name", "N/A")
mc = token_data.get("market_cap", "N/A") price = token_data.get("price", "N/A")
vol = token_data.get("volume_24h", "N/A") mc = token_data.get("market_cap", "N/A")
pairs = token_data.get("top_pairs", []) vol = token_data.get("volume_24h", "N/A")
pairs_text = "" pairs = token_data.get("top_pairs", [])
if pairs: pairs_text = ""
pairs_text = "\n**Top Pairs:**\n" if pairs:
for p in pairs[:3]: pairs_text = "\n**Top Pairs:**\n"
pairs_text += f"- {p.get('pair', 'N/A')}: ${p.get('liquidity', 'N/A'):,.0f} liquidity\n" for p in pairs[:3]:
response_text = f"**{symbol}** ({name})\n\nPrice: ${price}\nMarket Cap: ${mc:,.0f}\n24h Volume: ${vol:,.0f}{pairs_text}" pairs_text += f"- {p.get('pair', 'N/A')}: ${p.get('liquidity', 'N/A'):,.0f} liquidity\n"
else: response_text = f"**{symbol}** ({name})\n\nPrice: ${price}\nMarket Cap: ${mc:,.0f}\n24h Volume: ${vol:,.0f}{pairs_text}"
response_text = f"Token not found: {address}" else:
response_text = (
f"Token not found: {address}"
)
except json.JSONDecodeError:
response_text = "Failed to parse token data."
else: else:
response_text = f"Failed to get token details: {resp.status_code}" response_text = (
f"Failed to get token details: {output}"
)
return { return {
"response": response_text, "response": response_text,
@@ -417,40 +407,43 @@ class ConversationalAgent:
elif func_name == "get_price": elif func_name == "get_price":
token_ids = args.get("token_ids", "") token_ids = args.get("token_ids", "")
import os tokens_list = token_ids.replace(",", " ").split()
import asyncio if not tokens_list:
from ...core.config import get_settings response_text = "No token IDs provided."
settings = get_settings()
os.environ["AVE_API_KEY"] = settings.AVE_API_KEY
os.environ["API_PLAN"] = settings.AVE_API_PLAN
from ave.http import api_post
tokens_list = [t.strip() for t in token_ids.split(",")]
resp = asyncio.run(
api_post(
"/tokens/price", {"token_ids": tokens_list}
)
)
if resp.status_code == 200:
data = resp.json()
prices = data.get("data", {})
if prices:
price_text = "**Token Prices:**\n"
for token_id, price_data in prices.items():
price = price_data.get("price", "N/A")
change_24h = price_data.get(
"token_price_change_24h", "N/A"
)
price_text += f"- {token_id}: ${price} (24h: {change_24h}%)\n"
response_text = price_text
else:
response_text = "No price data available."
else: else:
response_text = ( code, output = self._call_ave_script(
f"Failed to get prices: {resp.status_code}" "price", ["--tokens"] + tokens_list
) )
if code == 0:
try:
data = json.loads(output)
prices = data.get("data", {})
if prices:
price_text = "**Token Prices:**\n"
for (
token_id,
price_data,
) in prices.items():
price = price_data.get(
"price", "N/A"
)
change_24h = price_data.get(
"token_price_change_24h", "N/A"
)
price_text += f"- {token_id}: ${price} (24h: {change_24h}%)\n"
response_text = price_text
else:
response_text = (
"No price data available."
)
except json.JSONDecodeError:
response_text = (
"Failed to parse price data."
)
else:
response_text = (
f"Failed to get prices: {output}"
)
return { return {
"response": response_text, "response": response_text,
@@ -464,56 +457,45 @@ class ConversationalAgent:
address = args.get("address", "") address = args.get("address", "")
chain = args.get("chain", "bsc") chain = args.get("chain", "bsc")
import os code, output = self._call_ave_script(
import asyncio "risk", ["--address", address, "--chain", chain]
from ...core.config import get_settings
settings = get_settings()
os.environ["AVE_API_KEY"] = settings.AVE_API_KEY
os.environ["API_PLAN"] = settings.AVE_API_PLAN
from ave.http import api_get
resp = asyncio.run(
api_get(f"/contracts/{address}-{chain}")
) )
if resp.status_code == 200: if code == 0:
data = resp.json() try:
risk_data = data.get("data", {}) data = json.loads(output)
if risk_data: risk_data = data.get("data", {})
is_honeypot = risk_data.get( if risk_data:
"is_honeypot", "unknown" is_honeypot = risk_data.get(
) "is_honeypot", "unknown"
buy_tax = risk_data.get("buy_tax", "N/A")
sell_tax = risk_data.get("sell_tax", "N/A")
status = risk_data.get("status", "unknown")
risk_text = (
f"**Risk Analysis for {address}**\n\n"
)
risk_text += f"- Status: {status}\n"
risk_text += f"- Honeypot: {is_honeypot}\n"
risk_text += f"- Buy Tax: {buy_tax}%\n"
risk_text += f"- Sell Tax: {sell_tax}%\n"
if is_honeypot.lower() == "true":
risk_text += "\n⚠️ **Warning: This token appears to be a honeypot. Do not buy!**"
elif (
float(buy_tax or 0) > 10
or float(sell_tax or 0) > 10
):
risk_text += "\n⚠️ **Warning: High tax detected. Trade with caution!**"
else:
risk_text += (
"\n✅ This token appears safe to trade."
) )
response_text = risk_text buy_tax = risk_data.get("buy_tax", "N/A")
else: sell_tax = risk_data.get("sell_tax", "N/A")
response_text = ( status = risk_data.get("status", "unknown")
f"No risk data available for {address}" risk_text = (
) f"**Risk Analysis for {address}**\n\n"
)
risk_text += f"- Status: {status}\n"
risk_text += f"- Honeypot: {is_honeypot}\n"
risk_text += f"- Buy Tax: {buy_tax}%\n"
risk_text += f"- Sell Tax: {sell_tax}%\n"
if is_honeypot.lower() == "true":
risk_text += "\n⚠️ **Warning: This token appears to be a honeypot. Do not buy!**"
elif (
float(buy_tax or 0) > 10
or float(sell_tax or 0) > 10
):
risk_text += "\n⚠️ **Warning: High tax detected. Trade with caution!**"
else:
risk_text += "\n✅ This token appears safe to trade."
response_text = risk_text
else:
response_text = (
f"No risk data available for {address}"
)
except json.JSONDecodeError:
response_text = "Failed to parse risk data."
else: else:
response_text = ( response_text = f"Failed to get risk data: {output}"
f"Failed to get risk data: {resp.status_code}"
)
return { return {
"response": response_text, "response": response_text,
@@ -603,44 +585,40 @@ class ConversationalAgent:
keyword = args.get("keyword", "") keyword = args.get("keyword", "")
limit = args.get("limit", 10) limit = args.get("limit", 10)
# Execute the tool using ave-cloud-skill # Execute the tool using ave-cloud-skill CLI
import os code, output = self._call_ave_script(
import asyncio "search",
from ...core.config import get_settings [
"--keyword",
settings = get_settings() keyword,
os.environ["AVE_API_KEY"] = settings.AVE_API_KEY "--chain",
os.environ["API_PLAN"] = settings.AVE_API_PLAN "bsc",
"--limit",
from ave.http import api_get str(limit),
],
resp = asyncio.run(
api_get(
"/tokens",
{"keyword": keyword, "limit": limit, "chain": "bsc"},
)
) )
if resp.status_code == 200: if code == 0:
data = resp.json() try:
tokens = data.get("data", {}).get("tokens", []) data = json.loads(output)
if tokens: tokens = data.get("data", {}).get("tokens", [])
token_list = "" if tokens:
for t in tokens[:limit]: token_list = ""
addr = t.get("token", "") for t in tokens[:limit]:
symbol = t.get("symbol", "") addr = t.get("token", "")
name = t.get("name", "") symbol = t.get("symbol", "")
price_change = t.get( name = t.get("name", "")
"token_price_change_24h", "N/A" price_change = t.get(
) "token_price_change_24h", "N/A"
mc = t.get("market_cap", "N/A") )
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: ${mc:,.0f} - 24h: {price_change}%\n" mc = t.get("market_cap", "N/A")
response_text = f"Here are the search results for '{keyword}' on BSC:\n\n{token_list}\nWould you like me to set up a strategy for any of these?" token_list += f"- **{symbol}** ({name}): `{addr}` - MC: ${mc:,.0f} - 24h: {price_change}%\n"
else: response_text = f"Here are the search results for '{keyword}' on BSC:\n\n{token_list}\nWould you like me to set up a strategy for any of these?"
response_text = f"No tokens found for '{keyword}'. Try a different keyword." else:
response_text = f"No tokens found for '{keyword}'. Try a different keyword."
except json.JSONDecodeError:
response_text = "Failed to parse search results."
else: else:
response_text = ( response_text = f"Failed to search tokens: {output}"
f"Failed to search tokens: {resp.status_code}"
)
strategy_update = None strategy_update = None
@@ -666,33 +644,23 @@ class ConversationalAgent:
# Search for token if name is found # Search for token if name is found
if strategy_needs_confirmation and token_name: if strategy_needs_confirmation and token_name:
try: try:
from ..ave.client import AveCloudClient code, output = self._call_ave_script(
from ...core.config import get_settings "search",
["--keyword", token_name, "--chain", "bsc", "--limit", "5"],
settings = get_settings()
ave_client = AveCloudClient(
api_key=settings.AVE_API_KEY, plan=settings.AVE_API_PLAN
) )
# Run async search in sync context if code == 0:
import asyncio data = json.loads(output)
tokens = data.get("data", {}).get("tokens", [])
tokens = asyncio.run( if tokens:
ave_client.get_tokens( token_search_results = [
query=token_name, chain="bsc", limit=5 {
) "symbol": t.get("symbol", ""),
) "name": t.get("name", ""),
if tokens: "address": t.get("token", ""),
token_search_results = [ "chain": t.get("chain", "bsc"),
{ }
"symbol": t.get("symbol", ""), for t in tokens
"name": t.get("name", ""), ]
"address": t.get(
"token", ""
), # trending API uses "token" for contract address
"chain": t.get("chain", "bsc"),
}
for t in tokens
]
except Exception as e: except Exception as e:
print(f"Token search error: {e}") print(f"Token search error: {e}")
@@ -1096,6 +1064,40 @@ Would you like me to adjust the strategy parameters based on these results?"""
print(f"Error updating strategy: {e}") print(f"Error updating strategy: {e}")
return False return False
def _call_ave_script(self, command: str, args: list) -> tuple[int, str]:
"""Call an ave-cloud-skill CLI script and return (status_code, stdout)."""
import json
import os
import subprocess
from ...core.config import get_settings
settings = get_settings()
repo_root = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
)
ave_skill_path = os.path.join(
repo_root, "ave-cloud-skill", "scripts", "ave_data_rest.py"
)
env = os.environ.copy()
env["AVE_API_KEY"] = settings.AVE_API_KEY
env["API_PLAN"] = settings.AVE_API_PLAN
env["AVE_USE_DOCKER"] = "false"
try:
result = subprocess.run(
["python3", ave_skill_path, command] + args,
capture_output=True,
text=True,
env=env,
timeout=30,
)
return result.returncode, result.stdout
except subprocess.TimeoutExpired:
return 1, "Error: Command timed out"
except Exception as e:
return 1, f"Error: {str(e)}"
def get_conversational_agent( def get_conversational_agent(
api_key: str = None, model: str = None, bot_id: str = None api_key: str = None, model: str = None, bot_id: str = None