mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-11 11:41:38 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b1b3d3b3e | ||
|
|
59107addc3 |
No files matched your search
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.6.5" \
|
||||
"praisonai>=2.6.7" \
|
||||
"praisonai[chat]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.6.5" \
|
||||
"praisonai>=2.6.7" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[chat]" \
|
||||
"praisonai[realtime]" \
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.6.5" \
|
||||
"praisonai>=2.6.7" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
"""
|
||||
Example: Using pandas as a custom tool with PraisonAI Agent
|
||||
|
||||
This example shows how to wrap pandas functions as tools
|
||||
that can be used with Agent().
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
from io import StringIO
|
||||
|
||||
# Define pandas wrapper tools
|
||||
def analyze_csv_data(csv_data: str) -> str:
|
||||
"""Analyze CSV data using pandas DataFrame.
|
||||
|
||||
Args:
|
||||
csv_data: CSV-formatted string data
|
||||
|
||||
Returns:
|
||||
Analysis summary including shape, columns, and statistics
|
||||
"""
|
||||
df = pd.read_csv(StringIO(csv_data))
|
||||
summary = f"""DataFrame Analysis:
|
||||
- Shape: {df.shape[0]} rows, {df.shape[1]} columns
|
||||
- Columns: {list(df.columns)}
|
||||
- Data Types: {dict(df.dtypes)}
|
||||
- Summary Statistics:
|
||||
{df.describe().to_string()}"""
|
||||
return summary
|
||||
|
||||
|
||||
def filter_dataframe(csv_data: str, column: str, condition: str, value: str) -> str:
|
||||
"""Filter a DataFrame based on a condition.
|
||||
|
||||
Args:
|
||||
csv_data: CSV-formatted string data
|
||||
column: Column name to filter on
|
||||
condition: Condition type ('equals', 'greater', 'less', 'contains')
|
||||
value: Value to compare against
|
||||
|
||||
Returns:
|
||||
Filtered data as CSV string
|
||||
"""
|
||||
df = pd.read_csv(StringIO(csv_data))
|
||||
|
||||
if condition == 'equals':
|
||||
filtered = df[df[column] == value]
|
||||
elif condition == 'greater':
|
||||
filtered = df[df[column] > float(value)]
|
||||
elif condition == 'less':
|
||||
filtered = df[df[column] < float(value)]
|
||||
elif condition == 'contains':
|
||||
filtered = df[df[column].str.contains(value, na=False)]
|
||||
else:
|
||||
return f"Unknown condition: {condition}"
|
||||
|
||||
return filtered.to_csv(index=False)
|
||||
|
||||
|
||||
def calculate_statistics(csv_data: str, column: str) -> str:
|
||||
"""Calculate statistics for a specific column.
|
||||
|
||||
Args:
|
||||
csv_data: CSV-formatted string data
|
||||
column: Column name to analyze
|
||||
|
||||
Returns:
|
||||
Statistics summary for the column
|
||||
"""
|
||||
df = pd.read_csv(StringIO(csv_data))
|
||||
|
||||
if column not in df.columns:
|
||||
return f"Column '{column}' not found. Available: {list(df.columns)}"
|
||||
|
||||
col = df[column]
|
||||
|
||||
if pd.api.types.is_numeric_dtype(col):
|
||||
stats = f"""Statistics for '{column}':
|
||||
- Count: {col.count()}
|
||||
- Mean: {col.mean():.2f}
|
||||
- Std: {col.std():.2f}
|
||||
- Min: {col.min()}
|
||||
- Max: {col.max()}
|
||||
- Median: {col.median()}"""
|
||||
else:
|
||||
stats = f"""Statistics for '{column}':
|
||||
- Count: {col.count()}
|
||||
- Unique: {col.nunique()}
|
||||
- Top: {col.mode().iloc[0] if len(col.mode()) > 0 else 'N/A'}
|
||||
- Sample values: {list(col.head(3))}"""
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test data
|
||||
test_csv = """name,age,salary,department
|
||||
Alice,30,50000,Engineering
|
||||
Bob,25,45000,Marketing
|
||||
Charlie,35,60000,Engineering
|
||||
Diana,28,52000,Sales
|
||||
Eve,32,55000,Marketing"""
|
||||
|
||||
print("=== Test: analyze_csv_data ===")
|
||||
print(analyze_csv_data(test_csv))
|
||||
print()
|
||||
|
||||
print("=== Test: filter_dataframe ===")
|
||||
print(filter_dataframe(test_csv, "age", "greater", "28"))
|
||||
print()
|
||||
|
||||
print("=== Test: calculate_statistics ===")
|
||||
print(calculate_statistics(test_csv, "salary"))
|
||||
print()
|
||||
|
||||
# Example with Agent (requires praisonaiagents)
|
||||
print("=== Agent Usage Example ===")
|
||||
print("""
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
name="data_analyst",
|
||||
role="Data Analyst",
|
||||
goal="Analyze data using pandas tools",
|
||||
tools=[analyze_csv_data, filter_dataframe, calculate_statistics]
|
||||
)
|
||||
|
||||
result = agent.start("Analyze this data and find the average salary")
|
||||
""")
|
||||
@@ -3,8 +3,8 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.6.5.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.6.5.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.6.7.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.6.7.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -82,6 +82,9 @@ class TemplatesHandler:
|
||||
"cache": self.cmd_cache,
|
||||
"run": self.cmd_run,
|
||||
"init": self.cmd_init,
|
||||
"add": self.cmd_add,
|
||||
"add-sources": self.cmd_add_sources,
|
||||
"remove-sources": self.cmd_remove_sources,
|
||||
"help": lambda _: self._print_help() or 0,
|
||||
}
|
||||
|
||||
@@ -109,6 +112,9 @@ class TemplatesHandler:
|
||||
cache list List cached templates
|
||||
run <template> Run a template directly
|
||||
init <name> Initialize a project from template
|
||||
add <source> Add template from GitHub or local path
|
||||
add-sources <src> Add a template source to persistent config
|
||||
remove-sources Remove a template source from config
|
||||
|
||||
[bold]Options:[/bold]
|
||||
--offline Use only cached templates (no network)
|
||||
@@ -122,6 +128,8 @@ class TemplatesHandler:
|
||||
praisonai templates info transcript-generator
|
||||
praisonai templates install github:MervinPraison/agent-recipes/transcript-generator
|
||||
praisonai templates run transcript-generator ./audio.mp3
|
||||
praisonai templates add github:user/repo/my-template
|
||||
praisonai templates add-sources github:MervinPraison/Agent-Recipes
|
||||
praisonai init my-project --template transcript-generator
|
||||
"""
|
||||
try:
|
||||
@@ -744,6 +752,189 @@ class TemplatesHandler:
|
||||
i += 1
|
||||
|
||||
return config
|
||||
|
||||
def _get_templates_config_path(self):
|
||||
"""Get the path to the templates config file."""
|
||||
config_dir = Path.home() / ".praison"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
return config_dir / "templates_sources.yaml"
|
||||
|
||||
def _load_templates_config(self) -> Dict[str, Any]:
|
||||
"""Load templates config from file."""
|
||||
import yaml
|
||||
config_path = self._get_templates_config_path()
|
||||
if config_path.exists():
|
||||
with open(config_path, 'r') as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
return {"sources": []}
|
||||
|
||||
def _save_templates_config(self, config: Dict[str, Any]):
|
||||
"""Save templates config to file."""
|
||||
import yaml
|
||||
config_path = self._get_templates_config_path()
|
||||
with open(config_path, 'w') as f:
|
||||
yaml.dump(config, f, default_flow_style=False)
|
||||
|
||||
def cmd_add(self, args: List[str]) -> int:
|
||||
"""
|
||||
Add template from GitHub or local path.
|
||||
|
||||
Args:
|
||||
args: [source] - github:user/repo/template or local path
|
||||
"""
|
||||
if not args:
|
||||
print("[red]Usage: praisonai templates add <source>[/red]")
|
||||
print(" source: github:user/repo/template or local path")
|
||||
return 1
|
||||
|
||||
source = args[0]
|
||||
|
||||
# Check if it's a local directory
|
||||
if source.startswith("./") or source.startswith("/"):
|
||||
path = Path(source).resolve()
|
||||
if path.exists() and path.is_dir():
|
||||
# Check for TEMPLATE.yaml
|
||||
template_yaml = path / "TEMPLATE.yaml"
|
||||
if not template_yaml.exists():
|
||||
print(f"[red]Not a valid template: {path} (missing TEMPLATE.yaml)[/red]")
|
||||
return 1
|
||||
|
||||
# Copy to ~/.praison/templates/
|
||||
templates_dir = Path.home() / ".praison" / "templates"
|
||||
templates_dir.mkdir(parents=True, exist_ok=True)
|
||||
dest = templates_dir / path.name
|
||||
|
||||
if dest.exists():
|
||||
shutil.rmtree(dest)
|
||||
shutil.copytree(path, dest)
|
||||
|
||||
print(f"\n✅ Added template: {path.name}")
|
||||
print(f" Copied to: {dest}")
|
||||
return 0
|
||||
else:
|
||||
print(f"[red]Directory not found: {source}[/red]")
|
||||
return 1
|
||||
|
||||
# Check if it's a GitHub reference
|
||||
elif source.startswith("github:"):
|
||||
github_path = source[7:] # Remove "github:"
|
||||
parts = github_path.split("/")
|
||||
if len(parts) < 3:
|
||||
print("[red]Invalid GitHub format. Use: github:user/repo/template-name[/red]")
|
||||
return 1
|
||||
|
||||
user, repo = parts[0], parts[1]
|
||||
template_path = "/".join(parts[2:])
|
||||
|
||||
# Download from GitHub
|
||||
import urllib.request
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
try:
|
||||
# Download repo as zip
|
||||
zip_url = f"https://github.com/{user}/{repo}/archive/refs/heads/main.zip"
|
||||
print(f"Downloading from: {zip_url}")
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
zip_path = Path(tmpdir) / "repo.zip"
|
||||
urllib.request.urlretrieve(zip_url, zip_path)
|
||||
|
||||
# Extract
|
||||
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(tmpdir)
|
||||
|
||||
# Find the template
|
||||
extracted_dir = Path(tmpdir) / f"{repo}-main"
|
||||
template_src = extracted_dir / template_path
|
||||
|
||||
if not template_src.exists():
|
||||
# Try common paths
|
||||
for alt_path in [
|
||||
extracted_dir / "agent_recipes" / "templates" / template_path,
|
||||
extracted_dir / "templates" / template_path,
|
||||
]:
|
||||
if alt_path.exists():
|
||||
template_src = alt_path
|
||||
break
|
||||
|
||||
if not template_src.exists():
|
||||
print(f"[red]Template not found: {template_path}[/red]")
|
||||
return 1
|
||||
|
||||
# Copy to ~/.praison/templates/
|
||||
templates_dir = Path.home() / ".praison" / "templates"
|
||||
templates_dir.mkdir(parents=True, exist_ok=True)
|
||||
dest = templates_dir / template_src.name
|
||||
|
||||
if dest.exists():
|
||||
shutil.rmtree(dest)
|
||||
shutil.copytree(template_src, dest)
|
||||
|
||||
print(f"\n✅ Added template from GitHub: {user}/{repo}/{template_path}")
|
||||
print(f" Saved to: {dest}")
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
print(f"[red]Failed to download from GitHub: {e}[/red]")
|
||||
return 1
|
||||
|
||||
else:
|
||||
print(f"[red]Unknown source format: {source}[/red]")
|
||||
print("Use: github:user/repo/template or ./local-path")
|
||||
return 1
|
||||
|
||||
def cmd_add_sources(self, args: List[str]) -> int:
|
||||
"""
|
||||
Add a template source to persistent config.
|
||||
|
||||
Args:
|
||||
args: [source] - github:user/repo or URL
|
||||
"""
|
||||
if not args:
|
||||
print("[red]Usage: praisonai templates add-sources <source>[/red]")
|
||||
return 1
|
||||
|
||||
source = args[0]
|
||||
config = self._load_templates_config()
|
||||
|
||||
if "sources" not in config:
|
||||
config["sources"] = []
|
||||
|
||||
if source in config["sources"]:
|
||||
print(f"[yellow]Source '{source}' already in config[/yellow]")
|
||||
return 0
|
||||
|
||||
config["sources"].append(source)
|
||||
self._save_templates_config(config)
|
||||
|
||||
print(f"\n✅ Added template source: {source}")
|
||||
print(f" Config saved to: {self._get_templates_config_path()}")
|
||||
return 0
|
||||
|
||||
def cmd_remove_sources(self, args: List[str]) -> int:
|
||||
"""
|
||||
Remove a template source from persistent config.
|
||||
|
||||
Args:
|
||||
args: [source] - source to remove
|
||||
"""
|
||||
if not args:
|
||||
print("[red]Usage: praisonai templates remove-sources <source>[/red]")
|
||||
return 1
|
||||
|
||||
source = args[0]
|
||||
config = self._load_templates_config()
|
||||
|
||||
if "sources" not in config or source not in config["sources"]:
|
||||
print(f"[yellow]Source '{source}' not found in config[/yellow]")
|
||||
return 1
|
||||
|
||||
config["sources"].remove(source)
|
||||
self._save_templates_config(config)
|
||||
|
||||
print(f"\n✅ Removed template source: {source}")
|
||||
return 0
|
||||
|
||||
|
||||
def import_time():
|
||||
|
||||
@@ -31,7 +31,7 @@ class ToolsHandler(CommandHandler):
|
||||
return "tools"
|
||||
|
||||
def get_actions(self) -> List[str]:
|
||||
return ["list", "info", "search", "doctor", "resolve", "discover", "show-sources", "help"]
|
||||
return ["list", "info", "search", "doctor", "resolve", "discover", "show-sources", "add", "add-sources", "remove-sources", "help"]
|
||||
|
||||
def get_help_text(self) -> str:
|
||||
return """
|
||||
@@ -44,6 +44,14 @@ Tools Commands:
|
||||
praisonai tools resolve <name> - Resolve a tool name to its source
|
||||
praisonai tools discover - Discover tools from installed packages
|
||||
praisonai tools show-sources - Show all tool sources for a template
|
||||
praisonai tools add <source> - Add tools from package, file, or GitHub
|
||||
praisonai tools add-sources <source> - Add a tool source to persistent config
|
||||
praisonai tools remove-sources <source> - Remove a tool source from config
|
||||
|
||||
Add Examples:
|
||||
praisonai tools add pandas - Wrap pandas functions as tools
|
||||
praisonai tools add ./my_tools.py - Add local tools file
|
||||
praisonai tools add github:user/repo - Add tools from GitHub
|
||||
|
||||
Built-in tools include: internet_search, calculator, file operations, etc.
|
||||
"""
|
||||
@@ -129,6 +137,13 @@ Built-in tools include: internet_search, calculator, file operations, etc.
|
||||
for name in uncategorized[:10]: # Limit to 10
|
||||
self.print_status(f" • {name}", "info")
|
||||
|
||||
# Show added tool sources from config
|
||||
config = self._load_config()
|
||||
if config.get("sources"):
|
||||
self.print_status("\n Added Sources (use with Agent):", "info")
|
||||
for source in config["sources"]:
|
||||
self.print_status(f" • {source}", "info")
|
||||
|
||||
return list(tools.keys())
|
||||
|
||||
def action_info(self, args: List[str], **kwargs) -> Dict[str, Any]:
|
||||
@@ -447,9 +462,219 @@ Built-in tools include: internet_search, calculator, file operations, etc.
|
||||
|
||||
return sources
|
||||
|
||||
def _get_config_path(self):
|
||||
"""Get the path to the tools config file."""
|
||||
from pathlib import Path
|
||||
config_dir = Path.home() / ".praison"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
return config_dir / "tools_sources.yaml"
|
||||
|
||||
def _load_config(self) -> Dict[str, Any]:
|
||||
"""Load tools config from file."""
|
||||
config_path = self._get_config_path()
|
||||
if config_path.exists():
|
||||
import yaml
|
||||
with open(config_path, 'r') as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
return {"sources": []}
|
||||
|
||||
def _save_config(self, config: Dict[str, Any]):
|
||||
"""Save tools config to file."""
|
||||
import yaml
|
||||
config_path = self._get_config_path()
|
||||
with open(config_path, 'w') as f:
|
||||
yaml.dump(config, f, default_flow_style=False)
|
||||
|
||||
def action_add(self, args: List[str], **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Add tools from package, file, or GitHub.
|
||||
|
||||
Args:
|
||||
args: [source] - package name, file path, or github:user/repo
|
||||
|
||||
Examples:
|
||||
praisonai tools add pandas
|
||||
praisonai tools add ./my_tools.py
|
||||
praisonai tools add github:user/repo/tools
|
||||
"""
|
||||
if not args:
|
||||
self.print_status("Usage: praisonai tools add <source>", "error")
|
||||
self.print_status(" source: package name, file path, or github:user/repo", "info")
|
||||
return {"success": False, "error": "No source provided"}
|
||||
|
||||
source = args[0]
|
||||
result = {"source": source, "success": False, "tools": []}
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Check if it's a local file
|
||||
if source.startswith("./") or source.startswith("/") or source.endswith(".py"):
|
||||
path = Path(source).resolve()
|
||||
if path.exists():
|
||||
# Copy to ~/.praison/tools/
|
||||
tools_dir = Path.home() / ".praison" / "tools"
|
||||
tools_dir.mkdir(parents=True, exist_ok=True)
|
||||
dest = tools_dir / path.name
|
||||
|
||||
import shutil
|
||||
shutil.copy(path, dest)
|
||||
|
||||
self.print_status(f"\n✅ Added tools file: {path.name}", "success")
|
||||
self.print_status(f" Copied to: {dest}", "info")
|
||||
|
||||
# Discover tools in the file
|
||||
try:
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location("tools_module", dest)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
tools = [n for n in dir(module) if not n.startswith('_') and callable(getattr(module, n, None))]
|
||||
result["tools"] = tools
|
||||
self.print_status(f" Found {len(tools)} tools: {', '.join(tools[:5])}", "info")
|
||||
except Exception as e:
|
||||
self.print_status(f" Warning: Could not inspect tools: {e}", "warning")
|
||||
|
||||
result["success"] = True
|
||||
return result
|
||||
else:
|
||||
self.print_status(f"File not found: {source}", "error")
|
||||
return result
|
||||
|
||||
# Check if it's a GitHub reference
|
||||
elif source.startswith("github:"):
|
||||
github_path = source[7:] # Remove "github:"
|
||||
parts = github_path.split("/")
|
||||
if len(parts) < 2:
|
||||
self.print_status("Invalid GitHub format. Use: github:user/repo/path", "error")
|
||||
return result
|
||||
|
||||
user, repo = parts[0], parts[1]
|
||||
path = "/".join(parts[2:]) if len(parts) > 2 else ""
|
||||
|
||||
# Download from GitHub
|
||||
import urllib.request
|
||||
|
||||
if path:
|
||||
raw_url = f"https://raw.githubusercontent.com/{user}/{repo}/main/{path}"
|
||||
if not path.endswith(".py"):
|
||||
raw_url += "/tools.py"
|
||||
else:
|
||||
raw_url = f"https://raw.githubusercontent.com/{user}/{repo}/main/tools.py"
|
||||
|
||||
try:
|
||||
self.print_status(f"Downloading from: {raw_url}", "info")
|
||||
|
||||
tools_dir = Path.home() / ".praison" / "tools"
|
||||
tools_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
filename = f"{user}_{repo}_{path.replace('/', '_')}.py" if path else f"{user}_{repo}_tools.py"
|
||||
dest = tools_dir / filename
|
||||
|
||||
urllib.request.urlretrieve(raw_url, dest)
|
||||
|
||||
self.print_status(f"\n✅ Added tools from GitHub: {user}/{repo}", "success")
|
||||
self.print_status(f" Saved to: {dest}", "info")
|
||||
|
||||
result["success"] = True
|
||||
return result
|
||||
except Exception as e:
|
||||
self.print_status(f"Failed to download from GitHub: {e}", "error")
|
||||
return result
|
||||
|
||||
# Assume it's a package name - but warn that packages need wrapper tools
|
||||
else:
|
||||
try:
|
||||
import importlib
|
||||
module = importlib.import_module(source)
|
||||
|
||||
# Get callable functions from the module
|
||||
tools = [n for n in dir(module) if not n.startswith('_') and callable(getattr(module, n, None))]
|
||||
|
||||
self.print_status(f"\n⚠️ Package '{source}' is installed but NOT directly usable as tools", "warning")
|
||||
self.print_status(f" Found {len(tools)} callable items in package", "info")
|
||||
self.print_status("", "info")
|
||||
self.print_status(" To use this package with agents, create wrapper tools:", "info")
|
||||
self.print_status(" 1. Create a file: ~/.praison/tools/my_tools.py", "info")
|
||||
self.print_status(" 2. Define wrapper functions with docstrings", "info")
|
||||
self.print_status(" 3. Tools will be auto-discovered", "info")
|
||||
self.print_status("", "info")
|
||||
self.print_status(" Example wrapper:", "info")
|
||||
self.print_status(f" def my_{source}_tool(data: str) -> str:", "info")
|
||||
self.print_status(f' """Use {source} to process data."""', "info")
|
||||
self.print_status(f" import {source}", "info")
|
||||
self.print_status(" # Your logic here", "info")
|
||||
self.print_status(" return result", "info")
|
||||
|
||||
result["success"] = True
|
||||
result["tools"] = tools[:10]
|
||||
result["note"] = "Package requires wrapper tools"
|
||||
return result
|
||||
except ImportError:
|
||||
self.print_status(f"Package '{source}' not found. Install with: pip install {source}", "error")
|
||||
return result
|
||||
|
||||
def action_add_sources(self, args: List[str], **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Add a tool source to persistent config.
|
||||
|
||||
Args:
|
||||
args: [source] - package name, file path, or github:user/repo
|
||||
"""
|
||||
if not args:
|
||||
self.print_status("Usage: praisonai tools add-sources <source>", "error")
|
||||
return {"success": False, "error": "No source provided"}
|
||||
|
||||
source = args[0]
|
||||
config = self._load_config()
|
||||
|
||||
if "sources" not in config:
|
||||
config["sources"] = []
|
||||
|
||||
if source in config["sources"]:
|
||||
self.print_status(f"Source '{source}' already in config", "warning")
|
||||
return {"success": True, "already_exists": True}
|
||||
|
||||
config["sources"].append(source)
|
||||
self._save_config(config)
|
||||
|
||||
self.print_status(f"\n✅ Added tool source: {source}", "success")
|
||||
self.print_status(f" Config saved to: {self._get_config_path()}", "info")
|
||||
|
||||
return {"success": True, "source": source}
|
||||
|
||||
def action_remove_sources(self, args: List[str], **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
Remove a tool source from persistent config.
|
||||
|
||||
Args:
|
||||
args: [source] - source to remove
|
||||
"""
|
||||
if not args:
|
||||
self.print_status("Usage: praisonai tools remove-sources <source>", "error")
|
||||
return {"success": False, "error": "No source provided"}
|
||||
|
||||
source = args[0]
|
||||
config = self._load_config()
|
||||
|
||||
if "sources" not in config or source not in config["sources"]:
|
||||
self.print_status(f"Source '{source}' not found in config", "warning")
|
||||
return {"success": False, "not_found": True}
|
||||
|
||||
config["sources"].remove(source)
|
||||
self._save_config(config)
|
||||
|
||||
self.print_status(f"\n✅ Removed tool source: {source}", "success")
|
||||
|
||||
return {"success": True, "source": source}
|
||||
|
||||
def execute(self, action: str, action_args: List[str], **kwargs) -> Any:
|
||||
"""Execute tools command action."""
|
||||
# Handle hyphenated action names
|
||||
if action == "show-sources":
|
||||
return self.action_show_sources(action_args, **kwargs)
|
||||
elif action == "add-sources":
|
||||
return self.action_add_sources(action_args, **kwargs)
|
||||
elif action == "remove-sources":
|
||||
return self.action_remove_sources(action_args, **kwargs)
|
||||
return super().execute(action, action_args, **kwargs)
|
||||
@@ -57,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.6.5 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.6.7 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "2.6.5"
|
||||
__version__ = "2.6.7"
|
||||
Reference in new issue
Block a user