Skip to content

Commit 86e76b7

Browse files
committed
Release v3.9.32
1 parent b18d600 commit 86e76b7

File tree

8 files changed

+86
-30
lines changed

8 files changed

+86
-30
lines changed

docker/Dockerfile.chat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=3.9.31" \
19+
"praisonai>=3.9.32" \
2020
"praisonai[chat]" \
2121
"embedchain[github,youtube]"
2222

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
2020
# Install Python packages (using latest versions)
2121
RUN pip install --no-cache-dir \
2222
praisonai_tools \
23-
"praisonai>=3.9.31" \
23+
"praisonai>=3.9.32" \
2424
"praisonai[ui]" \
2525
"praisonai[chat]" \
2626
"praisonai[realtime]" \

docker/Dockerfile.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=3.9.31" \
19+
"praisonai>=3.9.32" \
2020
"praisonai[ui]" \
2121
"praisonai[crewai]"
2222

src/praisonai/praisonai.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ class Praisonai < Formula
33

44
desc "AI tools for various AI applications"
55
homepage "https://github.com/MervinPraison/PraisonAI"
6-
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.31.tar.gz"
7-
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.31.tar.gz | shasum -a 256`.split.first
6+
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.32.tar.gz"
7+
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.32.tar.gz | shasum -a 256`.split.first
88
license "MIT"
99

1010
depends_on "[email protected]"

src/praisonai/praisonai/deploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def create_dockerfile(self):
5757
file.write("FROM python:3.11-slim\n")
5858
file.write("WORKDIR /app\n")
5959
file.write("COPY . .\n")
60-
file.write("RUN pip install flask praisonai==3.9.31 gunicorn markdown\n")
60+
file.write("RUN pip install flask praisonai==3.9.32 gunicorn markdown\n")
6161
file.write("EXPOSE 8080\n")
6262
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
6363

src/praisonai/praisonai/recipe/core.py

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,43 @@ def _load_recipe(name: str, offline: bool = False) -> Optional[RecipeConfig]:
660660
return None
661661

662662

663+
def _check_package_installed(package_name: str) -> bool:
664+
"""
665+
Check if a Python package is installed using importlib.metadata.
666+
667+
This is more reliable than trying to import the package because:
668+
1. Package names often differ from import names (e.g., tavily-python -> tavily)
669+
2. importlib.metadata checks the actual installed packages
670+
3. No side effects from importing modules
671+
672+
Args:
673+
package_name: The pip package name (e.g., 'tavily-python', 'pillow')
674+
675+
Returns:
676+
True if package is installed, False otherwise
677+
"""
678+
try:
679+
from importlib.metadata import distributions
680+
681+
# Normalize package name for comparison (pip normalizes - and _ and case)
682+
normalized = package_name.lower().replace("-", "_").replace(".", "_")
683+
684+
for dist in distributions():
685+
dist_name = dist.metadata.get("Name", "").lower().replace("-", "_").replace(".", "_")
686+
if dist_name == normalized:
687+
return True
688+
689+
return False
690+
except Exception:
691+
# Fallback: try to import with common name transformations
692+
try:
693+
import_name = package_name.replace("-", "_")
694+
__import__(import_name)
695+
return True
696+
except ImportError:
697+
return False
698+
699+
663700
def _check_dependencies(recipe_config: RecipeConfig) -> Dict[str, Any]:
664701
"""Check if recipe dependencies are satisfied."""
665702
result = {
@@ -670,28 +707,11 @@ def _check_dependencies(recipe_config: RecipeConfig) -> Dict[str, Any]:
670707
"external": [],
671708
}
672709

673-
# Common package name to import name mappings
674-
PACKAGE_IMPORT_MAP = {
675-
"tavily-python": "tavily",
676-
"google-generativeai": "google.generativeai",
677-
"openai-whisper": "whisper",
678-
"python-dotenv": "dotenv",
679-
"pillow": "PIL",
680-
"opencv-python": "cv2",
681-
"scikit-learn": "sklearn",
682-
"beautifulsoup4": "bs4",
683-
"pyyaml": "yaml",
684-
}
685-
686710
# Check Python packages
687711
for pkg in recipe_config.get_required_packages():
688-
# Get the correct import name
689-
import_name = PACKAGE_IMPORT_MAP.get(pkg, pkg.replace("-", "_"))
690-
try:
691-
__import__(import_name)
692-
result["packages"].append({"name": pkg, "available": True})
693-
except ImportError:
694-
result["packages"].append({"name": pkg, "available": False})
712+
available = _check_package_installed(pkg)
713+
result["packages"].append({"name": pkg, "available": available})
714+
if not available:
695715
result["all_satisfied"] = False
696716

697717
# Check environment variables
@@ -808,6 +828,9 @@ def _execute_recipe(
808828
workflow_config, merged_config, tool_registry, options
809829
)
810830
elif "steps" in workflow_config:
831+
# Pass the workflow file path for proper execution
832+
workflow_file_path = template_path / workflow_file if template_path else None
833+
merged_config["_workflow_file"] = str(workflow_file_path) if workflow_file_path else None
811834
return _execute_steps_workflow(
812835
workflow_config, merged_config, tool_registry, options
813836
)
@@ -900,9 +923,35 @@ def _execute_steps_workflow(
900923
tool_registry: Any,
901924
options: Dict[str, Any],
902925
) -> Any:
903-
"""Execute a steps-based workflow."""
904-
# For now, convert to simple execution
905-
return {"message": "Steps workflow executed", "config": config}
926+
"""
927+
Execute a steps-based workflow using praisonaiagents Workflow.
928+
929+
This properly executes the workflow with all features:
930+
- include steps (modular recipes)
931+
- loop steps (parallel/sequential)
932+
- output_variable
933+
- agent execution
934+
"""
935+
from praisonaiagents.workflows import YAMLWorkflowParser
936+
937+
# Get the workflow file path from config if available
938+
workflow_file = config.get("_workflow_file")
939+
940+
if workflow_file:
941+
# Use YAMLWorkflowParser to properly parse and execute the workflow
942+
# This handles include steps, loops, variables, tools, etc.
943+
parser = YAMLWorkflowParser(tool_registry=tool_registry)
944+
workflow = parser.parse_file(workflow_file)
945+
return workflow.start()
946+
947+
# Fallback: Create workflow from config dict using parser
948+
from praisonaiagents import Workflow
949+
workflow = Workflow(
950+
name=workflow_config.get("name", "RecipeWorkflow"),
951+
steps=workflow_config.get("steps", []),
952+
variables=workflow_config.get("variables", {}),
953+
)
954+
return workflow.start()
906955

907956

908957
def _execute_simple_agent(

src/praisonai/praisonai/templates/security.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,15 @@ def validate_template_directory(self, directory: Path) -> List[str]:
250250
errors = []
251251
total_size = 0
252252

253+
# Directories to skip during validation
254+
SKIP_DIRS = {"__pycache__", ".git", ".svn", ".hg", "node_modules", ".venv", "venv"}
255+
253256
for file_path in directory.rglob("*"):
254257
if file_path.is_file():
258+
# Skip files in excluded directories
259+
if any(skip_dir in file_path.parts for skip_dir in SKIP_DIRS):
260+
continue
261+
255262
# Check path safety
256263
if not self.validate_path(str(file_path.relative_to(directory))):
257264
errors.append(f"Unsafe path: {file_path.relative_to(directory)}")

src/praisonai/praisonai/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.9.31"
1+
__version__ = "3.9.32"

0 commit comments

Comments
 (0)