Compare commits

...
5 Commits
Author SHA1 Message Date
Mervin Praison 94d991f4ec Merge pull request #643 from MervinPraison/develop
Update PraisonAI and dependencies to version 2.2.33
2025-06-14 08:45:31 +02:00
MervinPraison 632cf68423 Update PraisonAI and dependencies to version 2.2.33
- Updated PraisonAI version from 2.2.32 to 2.2.33 across multiple Dockerfiles and relevant files.
- Adjusted dependency versions in pyproject.toml and other files for consistency.
- Enhanced README documentation to reflect the updated version.

This change integrates the latest features and improvements from PraisonAI while ensuring compatibility with existing code.
2025-06-14 07:45:15 +01:00
Mervin Praison d956c605f7 Merge pull request #635 from MervinPraison/claude/issue-634-20250610_115418
feat: Refactor Claude Code integration to use PraisonAI Agents
2025-06-14 08:43:35 +02:00
Mervin Praison 7e3de10f32 Rename test_claude_code_integration.py to src/praisonai/tests/unit/test_claude_code_integration.py 2025-06-14 07:41:20 +01:00
claude[bot]andMervinPraison 35199979f0 feat: Refactor Claude Code integration to use PraisonAI Agents
- Replace litellm direct usage with praisonaiagents framework
- Implement Claude Code as a custom tool that agents can decide to use
- Add --claudecode CLI flag support: `praisonai code --claudecode`
- Create intelligent agent that chooses when to use Claude Code vs regular responses
- Maintain full backward compatibility with litellm fallback
- Add UI toggle switch for enabling/disabling Claude Code
- Implement git operations with automatic branch creation and PR URLs
- Add comprehensive error handling and streaming support
- Include test script and detailed documentation

Key improvements:
- Agent-driven decision making instead of manual detection logic
- Better tool coordination and flexibility
- Minimal code changes with maintained compatibility
- Enhanced user experience with intelligent tool selection

Co-Authored-By: MervinPraison <[email protected]>
2025-06-10 12:02:19 +00:00
15 changed files with 698 additions and 32 deletions

No files matched your search

+291
View File
@@ -0,0 +1,291 @@
# Claude Code Integration with PraisonAI Agents
This document describes the integration of Claude Code with PraisonAI Agents, allowing AI agents to intelligently decide when to use Claude Code for file modifications and coding tasks.
## Overview
The refactored implementation replaces direct `litellm` usage with `praisonaiagents`, making Claude Code a custom tool that the AI agent can choose to use based on the user's request. This provides better intelligence and flexibility while maintaining backward compatibility.
## Key Features
### 🤖 Agent-Driven Decision Making
- AI agent intelligently decides when to use Claude Code vs. regular responses
- No manual detection logic - the agent understands context
- Automatic tool selection based on request type
### 🔧 Claude Code as a Custom Tool
- Claude Code is implemented as a tool function for PraisonAI Agents
- Executes `claude --dangerously-skip-permissions -p "query"`
- Supports `--continue` flag for conversation continuity
- Git operations with automatic branch creation and PR URLs
### ⚙️ Flexible Configuration
- CLI flag: `praisonai code --claudecode`
- UI toggle: "Enable Claude Code (file modifications & coding)"
- Environment variable: `PRAISONAI_CLAUDECODE_ENABLED=true`
### 🔄 Backward Compatibility
- Falls back to `litellm` if `praisonaiagents` is not available
- Maintains all existing functionality
- No breaking changes to existing workflows
## Architecture
### Agent Instructions
The agent receives these instructions to guide tool usage:
```
You are a helpful AI assistant. Use the available tools when needed to provide comprehensive responses.
If Claude Code tool is available and the user's request involves:
- File modifications, code changes, or implementation tasks
- Creating, editing, or debugging code
- Project setup or development tasks
- Git operations or version control
Then use the Claude Code tool to handle those requests.
For informational questions, explanations, or general conversations, respond normally without using Claude Code.
```
### Tool Function: `claude_code_tool`
```python
async def claude_code_tool(query: str) -> str:
"""
Execute Claude Code CLI commands for file modifications and coding tasks.
Args:
query: The user's request that requires file modifications or coding assistance
Returns:
The output from Claude Code execution
"""
```
**Features:**
- Executes Claude Code with `--dangerously-skip-permissions`
- Supports conversation continuity with `--continue` flag
- Automatic git branch creation and management
- PR URL generation for GitHub repositories
- 5-minute timeout for long operations
- Comprehensive error handling
### Available Tools
When Claude Code is enabled, the agent has access to:
1. **Claude Code Tool** - For file modifications and coding tasks
2. **Tavily Web Search** - For internet research (if API key configured)
The agent decides which tool(s) to use based on the user's request.
## Usage
### Command Line Interface
```bash
# Enable Claude Code integration
praisonai code --claudecode
# Use regular mode (no Claude Code)
praisonai code
```
### Environment Variables
```bash
# Force enable Claude Code (overrides UI setting)
export PRAISONAI_CLAUDECODE_ENABLED=true
# Set repository path (defaults to current directory)
export PRAISONAI_CODE_REPO_PATH=/path/to/your/repo
```
### UI Settings
In the PraisonAI Code UI, you can:
- Toggle "Enable Claude Code (file modifications & coding)" switch
- Setting is saved to database for persistence
- CLI flag takes precedence over UI setting
## Examples
### File Modification Request
**User:** "Create a new Python function to calculate fibonacci numbers"
**Agent Decision:** Uses Claude Code tool → Creates/modifies files → Returns implementation details
### Informational Request
**User:** "How does fibonacci algorithm work?"
**Agent Decision:** Responds normally → Provides explanation without file modifications
### Mixed Request
**User:** "Explain how sorting works and implement quicksort in Python"
**Agent Decision:** May use Claude Code tool for implementation → Provides both explanation and code files
## Git Integration
When Claude Code makes changes and git is available:
1. **Automatic Branch Creation:** Creates `claude-code-YYYYMMDD_HHMMSS` branch
2. **Commit Changes:** Commits all modifications with descriptive message
3. **Remote Push:** Pushes branch to remote repository (if configured)
4. **PR URL Generation:** Generates GitHub PR creation URL
Example output:
```
📋 **Pull Request Created:**
https://github.com/user/repo/compare/main...claude-code-20241210_143022?quick_pull=1
```
## Error Handling
### Graceful Degradation
- If `praisonaiagents` unavailable → Falls back to `litellm`
- If Claude Code CLI unavailable → Agent works without the tool
- If git unavailable → Code changes without git operations
- Network issues → Continues with local operations
### Error Messages
- Clear error reporting in streaming responses
- Timeout handling for long operations
- Detailed logging for debugging
## Implementation Details
### File Structure
```
src/praisonai/praisonai/
├── cli.py # Added --claudecode flag
└── ui/
└── code.py # Refactored to use praisonaiagents
```
### Key Functions
1. **`handle_with_praisonai_agents()`** - Main agent execution handler
2. **`handle_with_litellm()`** - Fallback for backward compatibility
3. **`claude_code_tool()`** - Claude Code tool implementation
4. **Settings management** - UI toggles and persistence
### Dependencies
**Required:**
- `praisonaiagents` - Core agent framework
- `subprocess` - For Claude Code CLI execution
- `chainlit` - UI framework
**Optional:**
- `tavily` - Web search capability
- `git` - Version control operations
- `claude` CLI - File modification capabilities
## Testing
Use the included test script to verify the integration:
```bash
python test_claude_code_integration.py
```
Tests verify:
- Import functionality
- PraisonAI Agents availability
- Claude Code CLI availability
- Environment variable configuration
- Basic tool execution
## Migration Guide
### From Previous Implementation
The previous implementation used direct Claude Code detection logic. The new implementation:
1. **Replaces detection logic** with agent intelligence
2. **Maintains same UI/CLI interfaces** for easy migration
3. **Preserves all existing functionality** while adding flexibility
4. **Requires no user workflow changes**
### Upgrading
1. Ensure `praisonaiagents` is installed
2. Update PraisonAI to include the refactored code
3. Use `--claudecode` flag or UI toggle as before
4. Existing settings and workflows continue working
## Best Practices
### When to Enable Claude Code
- File modification projects
- Code development workflows
- Repository maintenance tasks
- Implementation and debugging sessions
### When to Disable Claude Code
- Read-only analysis
- Documentation-only sessions
- Learning and educational content
- General Q&A conversations
### Configuration Recommendations
- Use CLI flag for development sessions
- Use UI toggle for mixed workflows
- Set environment variables for CI/CD integration
- Configure repository path for multi-project setups
## Troubleshooting
### Common Issues
**Agent doesn't use Claude Code tool:**
- Verify Claude Code is enabled (`--claudecode` flag or UI toggle)
- Check that request involves file modifications
- Ensure `praisonaiagents` is installed
**Claude Code tool fails:**
- Verify `claude` CLI is installed and in PATH
- Check repository permissions
- Confirm git repository status (if git operations needed)
**Fallback to litellm:**
- Install `praisonaiagents`: `pip install praisonaiagents`
- Check import errors in logs
- Verify Python environment compatibility
### Debug Information
Enable verbose logging:
```bash
export LOGLEVEL=DEBUG
praisonai code --claudecode
```
Check environment:
```python
import os
print("Claude Code enabled:", os.getenv("PRAISONAI_CLAUDECODE_ENABLED"))
print("Repo path:", os.getenv("PRAISONAI_CODE_REPO_PATH"))
```
## Future Enhancements
### Planned Features
- Real-time streaming from PraisonAI Agents
- Enhanced git workflow integration
- Multi-repository support
- Advanced tool coordination
- Performance optimizations
### Extension Points
- Additional coding tools integration
- Custom agent instructions
- Workflow templates
- Integration with other development tools
---
For technical support or questions, please refer to the main PraisonAI documentation or submit issues to the repository.
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
flask \
"praisonai>=2.2.32" \
"praisonai>=2.2.33" \
"praisonai[api]" \
gunicorn \
markdown
+1 -1
View File
@@ -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.2.32" \
"praisonai>=2.2.33" \
"praisonai[chat]" \
"embedchain[github,youtube]"
+1 -1
View File
@@ -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.2.32" \
"praisonai>=2.2.33" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
+1 -1
View File
@@ -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.2.32" \
"praisonai>=2.2.33" \
"praisonai[ui]" \
"praisonai[crewai]"
+2 -2
View File
@@ -121,7 +121,7 @@ healthcheck:
## 📦 Package Versions
All Docker images use consistent, up-to-date versions:
- PraisonAI: `>=2.2.32`
- PraisonAI: `>=2.2.33`
- PraisonAI Agents: `>=0.0.92`
- Python: `3.11-slim`
@@ -218,7 +218,7 @@ docker-compose up -d
### Version Pinning
To use specific versions, update the Dockerfile:
```dockerfile
RUN pip install "praisonai==2.2.32" "praisonaiagents==0.0.92"
RUN pip install "praisonai==2.2.33" "praisonaiagents==0.0.92"
```
## 🌐 Production Deployment
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.0.105"
version = "0.0.106"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
requires-python = ">=3.10"
authors = [
+1 -1
View File
@@ -2374,7 +2374,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
version = "0.0.105"
version = "0.0.106"
source = { editable = "." }
dependencies = [
{ name = "mcp" },
+2 -2
View File
@@ -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.2.32.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.32.tar.gz | shasum -a 256`.split.first
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.33.tar.gz"
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.33.tar.gz | shasum -a 256`.split.first
license "MIT"
depends_on "[email protected]"
+5
View File
@@ -529,6 +529,7 @@ class PraisonAI:
parser.add_argument("--call", action="store_true", help="Start the PraisonAI Call server")
parser.add_argument("--public", action="store_true", help="Use ngrok to expose the server publicly (only with --call)")
parser.add_argument("--merge", action="store_true", help="Merge existing agents.yaml with auto-generated agents instead of overwriting")
parser.add_argument("--claudecode", action="store_true", help="Enable Claude Code integration for file modifications and coding tasks")
# If we're in a test environment, parse with empty args to avoid pytest interference
if in_test_env:
@@ -549,6 +550,10 @@ class PraisonAI:
if args.command == 'code':
args.ui = 'chainlit'
args.code = True
# Handle --claudecode flag for code command
if getattr(args, 'claudecode', False):
os.environ["PRAISONAI_CLAUDECODE_ENABLED"] = "true"
if args.command == 'realtime':
args.realtime = True
if args.command == 'call':
+1 -1
View File
@@ -56,7 +56,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.2.32 gunicorn markdown\n")
file.write("RUN pip install flask praisonai==2.2.33 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
+244 -12
View File
@@ -13,16 +13,25 @@ from PIL import Image
from context import ContextGatherer
from tavily import TavilyClient
from crawl4ai import AsyncWebCrawler
import subprocess
# Local application/library imports
import chainlit as cl
from chainlit.input_widget import TextInput
from chainlit.input_widget import TextInput, Switch
from chainlit.types import ThreadDict
import chainlit.data as cl_data
from litellm import acompletion
import litellm
from db import DatabaseManager
# PraisonAI Agents imports
try:
from praisonaiagents import Agent
PRAISONAI_AGENTS_AVAILABLE = True
except ImportError:
PRAISONAI_AGENTS_AVAILABLE = False
# Fallback to litellm for backward compatibility
from litellm import acompletion
import litellm
# Load environment variables
load_dotenv()
@@ -41,14 +50,131 @@ logger.addHandler(console_handler)
# Set the logging level for the logger
logger.setLevel(log_level)
# Configure litellm same as in llm.py
litellm.set_verbose = False
litellm.success_callback = []
litellm._async_success_callback = []
litellm.callbacks = []
litellm.drop_params = True
litellm.modify_params = True
litellm.suppress_debug_messages = True
# Configure litellm for backward compatibility (only if praisonaiagents not available)
if not PRAISONAI_AGENTS_AVAILABLE:
import litellm
litellm.set_verbose = False
litellm.success_callback = []
litellm._async_success_callback = []
litellm.callbacks = []
litellm.drop_params = True
litellm.modify_params = True
litellm.suppress_debug_messages = True
# Claude Code Tool Function
async def claude_code_tool(query: str) -> str:
"""
Execute Claude Code CLI commands for file modifications and coding tasks.
Args:
query: The user's request that requires file modifications or coding assistance
Returns:
The output from Claude Code execution
"""
try:
# Check if the current working directory is a git repository
repo_path = os.environ.get("PRAISONAI_CODE_REPO_PATH", ".")
# Try to detect if git is available and if we're in a git repo
git_available = False
try:
subprocess.run(["git", "status"], cwd=repo_path, capture_output=True, check=True)
git_available = True
except (subprocess.CalledProcessError, FileNotFoundError):
git_available = False
# Build Claude Code command
claude_cmd = ["claude", "--dangerously-skip-permissions", "-p", query]
# Check if it's a continuation (simple heuristic)
user_session_context = cl.user_session.get("claude_code_context", False)
if user_session_context:
claude_cmd.insert(1, "--continue")
# Execute Claude Code command
result = subprocess.run(
claude_cmd,
cwd=repo_path,
capture_output=True,
text=True,
timeout=300 # 5 minutes timeout
)
# Set context for future requests
cl.user_session.set("claude_code_context", True)
output = result.stdout
if result.stderr:
output += f"\n\nErrors:\n{result.stderr}"
# If git is available and changes were made, try to create a branch and PR
if git_available and result.returncode == 0:
try:
# Check for changes
git_status = subprocess.run(
["git", "status", "--porcelain"],
cwd=repo_path,
capture_output=True,
text=True,
check=True
)
if git_status.stdout.strip():
# Create a branch for the changes
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
branch_name = f"claude-code-{timestamp}"
# Create and switch to new branch
subprocess.run(["git", "checkout", "-b", branch_name], cwd=repo_path, check=True)
# Add and commit changes
subprocess.run(["git", "add", "."], cwd=repo_path, check=True)
commit_message = f"Claude Code changes: {query[:50]}..."
subprocess.run(
["git", "commit", "-m", commit_message],
cwd=repo_path,
check=True
)
# Push to remote (if configured)
try:
subprocess.run(
["git", "push", "-u", "origin", branch_name],
cwd=repo_path,
check=True
)
# Generate PR URL (assuming GitHub)
remote_url = subprocess.run(
["git", "config", "--get", "remote.origin.url"],
cwd=repo_path,
capture_output=True,
text=True
)
if remote_url.returncode == 0:
repo_url = remote_url.stdout.strip()
if repo_url.endswith(".git"):
repo_url = repo_url[:-4]
if "github.com" in repo_url:
pr_url = f"{repo_url}/compare/main...{branch_name}?quick_pull=1"
output += f"\n\n📋 **Pull Request Created:**\n{pr_url}"
except subprocess.CalledProcessError:
output += f"\n\n🌲 **Branch created:** {branch_name} (push manually if needed)"
except subprocess.CalledProcessError as e:
output += f"\n\nGit operations failed: {e}"
return output
except subprocess.TimeoutExpired:
return "Claude Code execution timed out after 5 minutes."
except subprocess.CalledProcessError as e:
return f"Claude Code execution failed: {e}\nStdout: {e.stdout}\nStderr: {e.stderr}"
except Exception as e:
return f"Error executing Claude Code: {str(e)}"
CHAINLIT_AUTH_SECRET = os.getenv("CHAINLIT_AUTH_SECRET")
@@ -109,6 +235,12 @@ async def start():
model_name = os.getenv("MODEL_NAME", "gpt-4o-mini")
cl.user_session.set("model_name", model_name)
logger.debug(f"Model name: {model_name}")
# Load Claude Code setting (check CLI flag first, then database setting)
claude_code_enabled = os.getenv("PRAISONAI_CLAUDECODE_ENABLED", "false").lower() == "true"
if not claude_code_enabled:
claude_code_enabled = (load_setting("claude_code_enabled") or "false").lower() == "true"
settings = cl.ChatSettings(
[
TextInput(
@@ -116,6 +248,11 @@ async def start():
label="Enter the Model Name",
placeholder="e.g., gpt-4o-mini",
initial=model_name
),
Switch(
id="claude_code_enabled",
label="Enable Claude Code (file modifications & coding)",
initial=claude_code_enabled
)
]
)
@@ -134,10 +271,13 @@ async def setup_agent(settings):
logger.debug(settings)
cl.user_session.set("settings", settings)
model_name = settings["model_name"]
claude_code_enabled = settings.get("claude_code_enabled", False)
cl.user_session.set("model_name", model_name)
cl.user_session.set("claude_code_enabled", claude_code_enabled)
# Save in settings table
save_setting("model_name", model_name)
save_setting("claude_code_enabled", str(claude_code_enabled).lower())
# Save in thread metadata
thread_id = cl.user_session.get("thread_id")
@@ -152,6 +292,7 @@ async def setup_agent(settings):
metadata = {}
metadata["model_name"] = model_name
metadata["claude_code_enabled"] = claude_code_enabled
# Always store metadata as a dictionary
await cl_data._data_layer.update_thread(thread_id, metadata=metadata)
@@ -221,6 +362,7 @@ tools = [{
@cl.on_message
async def main(message: cl.Message):
model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
claude_code_enabled = cl.user_session.get("claude_code_enabled", False)
message_history = cl.user_session.get("message_history", [])
repo_path_to_use = os.environ.get("PRAISONAI_CODE_REPO_PATH", ".")
gatherer = ContextGatherer(directory=repo_path_to_use)
@@ -258,6 +400,87 @@ Context:
msg = cl.Message(content="")
await msg.send()
# Use PraisonAI Agents if available, otherwise fallback to litellm
if PRAISONAI_AGENTS_AVAILABLE:
await handle_with_praisonai_agents(message, user_message, model_name, claude_code_enabled, msg, image)
else:
await handle_with_litellm(user_message, model_name, message_history, msg, image)
async def handle_with_praisonai_agents(message, user_message, model_name, claude_code_enabled, msg, image):
"""Handle message using PraisonAI Agents framework with optional Claude Code tool"""
try:
# Prepare tools list
available_tools = []
# Add Tavily search tool if API key available
if tavily_api_key:
available_tools.append(tavily_web_search)
# Add Claude Code tool if enabled
if claude_code_enabled:
available_tools.append(claude_code_tool)
# Create agent instructions
instructions = """You are a helpful AI assistant. Use the available tools when needed to provide comprehensive responses.
If Claude Code tool is available and the user's request involves:
- File modifications, code changes, or implementation tasks
- Creating, editing, or debugging code
- Project setup or development tasks
- Git operations or version control
Then use the Claude Code tool to handle those requests.
For informational questions, explanations, or general conversations, respond normally without using Claude Code."""
# Create agent
agent = Agent(
name="PraisonAI Assistant",
instructions=instructions,
llm=model_name,
tools=available_tools if available_tools else None
)
# Execute agent with streaming
full_response = ""
# Use agent's streaming capabilities if available
try:
# For now, use synchronous execution and stream the result
# TODO: Implement proper streaming when PraisonAI agents support it
result = agent.start(user_message)
# Stream the response character by character for better UX
if hasattr(result, 'raw'):
response_text = result.raw
else:
response_text = str(result)
for char in response_text:
await msg.stream_token(char)
full_response += char
# Small delay to make streaming visible
await asyncio.sleep(0.01)
except Exception as e:
error_response = f"Error executing agent: {str(e)}"
for char in error_response:
await msg.stream_token(char)
full_response += char
await asyncio.sleep(0.01)
msg.content = full_response
await msg.update()
except Exception as e:
error_msg = f"Failed to use PraisonAI Agents: {str(e)}"
logger.error(error_msg)
await msg.stream_token(error_msg)
msg.content = error_msg
await msg.update()
async def handle_with_litellm(user_message, model_name, message_history, msg, image):
"""Fallback handler using litellm for backward compatibility"""
# Prepare the completion parameters using the helper function
completion_params = _build_completion_params(
model_name,
@@ -279,7 +502,7 @@ Context:
]
}
# Use a vision-capable model when an image is present
completion_params["model"] = "gpt-4-vision-preview" # Adjust this to your actual vision-capable model
completion_params["model"] = "gpt-4-vision-preview"
# Only add tools and tool_choice if Tavily API key is available and no image is uploaded
if tavily_api_key:
@@ -412,6 +635,10 @@ async def send_count():
async def on_chat_resume(thread: ThreadDict):
logger.info(f"Resuming chat: {thread['id']}")
model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
# Load Claude Code setting (check CLI flag first, then database setting)
claude_code_enabled = os.getenv("PRAISONAI_CLAUDECODE_ENABLED", "false").lower() == "true"
if not claude_code_enabled:
claude_code_enabled = (load_setting("claude_code_enabled") or "false").lower() == "true"
logger.debug(f"Model name: {model_name}")
settings = cl.ChatSettings(
[
@@ -420,6 +647,11 @@ async def on_chat_resume(thread: ThreadDict):
label="Enter the Model Name",
placeholder="e.g., gpt-4o-mini",
initial=model_name
),
Switch(
id="claude_code_enabled",
label="Enable Claude Code (file modifications & coding)",
initial=claude_code_enabled
)
]
)
+4 -4
View File
@@ -1,6 +1,6 @@
[project]
name = "PraisonAI"
version = "2.2.32"
version = "2.2.33"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
readme = "README.md"
license = ""
@@ -12,7 +12,7 @@ dependencies = [
"rich>=13.7",
"markdown>=3.5",
"pyparsing>=3.0.0",
"praisonaiagents>=0.0.105",
"praisonaiagents>=0.0.106",
"python-dotenv>=0.19.0",
"instructor>=1.3.3",
"PyYAML>=6.0",
@@ -95,7 +95,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]
[tool.poetry]
name = "PraisonAI"
version = "2.2.32"
version = "2.2.33"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
authors = ["Mervin Praison"]
license = ""
@@ -113,7 +113,7 @@ python = ">=3.10,<3.13"
rich = ">=13.7"
markdown = ">=3.5"
pyparsing = ">=3.0.0"
praisonaiagents = ">=0.0.105"
praisonaiagents = ">=0.0.106"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
"""
Test script for Claude Code integration with PraisonAI Agents
This script tests the basic functionality of the refactored Claude Code integration
"""
import os
import sys
import asyncio
import unittest
# Add the src directory to the path for imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai'))
def test_claude_code_tool_import():
"""Test that we can import the Claude Code tool function"""
try:
from praisonai.ui.code import claude_code_tool
print("✅ Successfully imported claude_code_tool")
return True
except ImportError as e:
print(f"❌ Failed to import claude_code_tool: {e}")
return False
def test_praisonai_agents_import():
"""Test praisonaiagents import availability"""
try:
from praisonaiagents import Agent
print("✅ PraisonAI Agents is available")
return True
except ImportError as e:
print(f"⚠️ PraisonAI Agents not available (fallback to litellm): {e}")
return False
def test_claude_code_availability():
"""Test if Claude Code CLI is available"""
import subprocess
try:
result = subprocess.run(['claude', '--version'], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
print(f"✅ Claude Code CLI is available: {result.stdout.strip()}")
return True
else:
print(f"❌ Claude Code CLI returned error: {result.stderr}")
return False
except FileNotFoundError:
print("⚠️ Claude Code CLI not found in PATH")
return False
except subprocess.TimeoutExpired:
print("⚠️ Claude Code CLI check timed out")
return False
except Exception as e:
print(f"⚠️ Error checking Claude Code CLI: {e}")
return False
async def test_claude_code_tool_execution():
"""Test basic Claude Code tool execution (simple query)"""
try:
from praisonai.ui.code import claude_code_tool
# Test with a simple query that shouldn't modify files
test_query = "What is the current directory?"
result = await claude_code_tool(test_query)
print(f"✅ Claude Code tool executed successfully")
print(f"Query: {test_query}")
print(f"Result (first 100 chars): {str(result)[:100]}...")
return True
except Exception as e:
print(f"❌ Claude Code tool execution failed: {e}")
return False
def test_environment_variables():
"""Test that environment variables are properly set"""
test_vars = [
"PRAISONAI_CLAUDECODE_ENABLED",
"PRAISONAI_CODE_REPO_PATH"
]
print("Environment Variables:")
for var in test_vars:
value = os.getenv(var, "NOT_SET")
print(f" {var}: {value}")
return True
async def run_tests():
"""Run all tests"""
print("🧪 Testing Claude Code Integration with PraisonAI Agents")
print("=" * 60)
tests = [
("Import Claude Code Tool", test_claude_code_tool_import),
("Import PraisonAI Agents", test_praisonai_agents_import),
("Environment Variables", test_environment_variables),
("Claude Code CLI Availability", test_claude_code_availability),
]
results = {}
for test_name, test_func in tests:
print(f"\n🔍 {test_name}:")
try:
results[test_name] = test_func()
except Exception as e:
print(f"❌ Test failed with exception: {e}")
results[test_name] = False
# Only test Claude Code tool execution if CLI is available
if results.get("Claude Code CLI Availability", False):
print(f"\n🔍 Claude Code Tool Execution:")
try:
results["Claude Code Tool Execution"] = await test_claude_code_tool_execution()
except Exception as e:
print(f"❌ Test failed with exception: {e}")
results["Claude Code Tool Execution"] = False
# Summary
print("\n" + "=" * 60)
print("📊 Test Summary:")
passed = sum(1 for result in results.values() if result)
total = len(results)
for test_name, result in results.items():
status = "✅ PASS" if result else "❌ FAIL"
print(f" {status} {test_name}")
print(f"\nResults: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! Integration is working correctly.")
else:
print("⚠️ Some tests failed. Please check the implementation.")
return passed == total
if __name__ == "__main__":
asyncio.run(run_tests())
+5 -5
View File
@@ -3931,7 +3931,7 @@ wheels = [
[[package]]
name = "praisonai"
version = "2.2.32"
version = "2.2.33"
source = { editable = "." }
dependencies = [
{ name = "instructor" },
@@ -4073,7 +4073,7 @@ requires-dist = [
{ name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" },
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.15" },
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.15" },
{ name = "praisonaiagents", specifier = ">=0.0.105" },
{ name = "praisonaiagents", specifier = ">=0.0.106" },
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = ">=0.2.19" },
{ name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" },
{ name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" },
@@ -4130,7 +4130,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
version = "0.0.105"
version = "0.0.106"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mcp" },
@@ -4139,9 +4139,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "rich" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bc/9b/a95d221c85d222bc265c5817335a8c57dc345e6f7808b6d7dac0b50bfe42/praisonaiagents-0.0.105.tar.gz", hash = "sha256:347ac596f9baea7daeac718ef5c9992c5f3a487b22d53623fc53f6b32dbf4808", size = 154675 }
sdist = { url = "https://files.pythonhosted.org/packages/81/9a/7b488726d34ebf7f98c27dd3e730ed0ca14dec7e63f9cb8fe4129aaf0e24/praisonaiagents-0.0.106.tar.gz", hash = "sha256:0fecb0df6c1ace618374a3d78eb6f03a058e70c606449069363cda0505a59487", size = 154663 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/36/93/3797957c4a72e756d0a2d49b25cf300e3c0781b86b0308ae2871a52761e4/praisonaiagents-0.0.105-py3-none-any.whl", hash = "sha256:ad52505ba715970d812a72ae18f00bde6c92ed6838fee0375324b15cd3e32324", size = 175599 },
{ url = "https://files.pythonhosted.org/packages/3f/75/6d56dbb2a03a4d0160ba6f3ebe60b468e3ee859f31c2833ac9d03130bdaf/praisonaiagents-0.0.106-py3-none-any.whl", hash = "sha256:504c4e11558bc21b8757efba8211b231c7ee235c46cbaafe02038fa493124f83", size = 175597 },
]
[[package]]