Skip to content

feat: Add human-in-the-loop approval system for dangerous tool operations#566

Merged
MervinPraison merged 4 commits into
mainfrom
claude/issue-12-20250601_032826
Jun 2, 2025
Merged

feat: Add human-in-the-loop approval system for dangerous tool operations#566
MervinPraison merged 4 commits into
mainfrom
claude/issue-12-20250601_032826

Conversation

@MervinPraison

@MervinPraison MervinPraison commented Jun 1, 2025

Copy link
Copy Markdown
Owner

Implements human approval framework for dangerous operations like shell commands, code execution, and file operations to enhance security and user control.

Key features:

  • @require_approval decorator for marking dangerous tools
  • Risk-based approval (critical, high, medium, low)
  • Console approval interface with rich formatting
  • Custom approval callbacks for automated policies
  • Async/sync support for all workflows
  • Runtime configuration of approval requirements

Resolves: #12

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Introduced a human-in-the-loop approval system for executing potentially dangerous operations, including file, shell, and Python code actions.
    • Added risk-level classification (critical, high, medium, low) for tools, with customizable approval prompts for high-risk actions.
    • Provided support for both synchronous and asynchronous approval workflows.
    • Enabled runtime configuration of which tools require approval and their risk levels.
  • Bug Fixes

    • Dangerous operations are now properly gated by approval checks, preventing unauthorized execution.
  • Tests

    • Added comprehensive unit and integration tests covering approval prompts, callback logic, decorator enforcement, and agent integration.
    • Included interactive and automated test suites for various approval scenarios.
  • Documentation

    • Added example scripts demonstrating human approval workflows and configuration options.

…ions

Implements human approval framework for dangerous operations like shell commands,
code execution, and file operations to enhance security and user control.

Key features:
- @require_approval decorator for marking dangerous tools  
- Risk-based approval (critical, high, medium, low)
- Console approval interface with rich formatting
- Custom approval callbacks for automated policies
- Async/sync support for all workflows
- Runtime configuration of approval requirements

Protected operations:
- Critical: execute_command, kill_process, execute_code
- High: write_file, delete_file, move_file, copy_file
- Medium: evaluate, crawl, scrape_page

Files modified:
- New approval.py module with core framework
- Enhanced main.py with approval callback support
- Modified agent.py to check approvals before tool execution
- Added @require_approval decorators to dangerous tools
- Comprehensive example and test implementations

Resolves: #12

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: MervinPraison <MervinPraison@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 1, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

A comprehensive human-in-the-loop approval framework is introduced for PraisonAI agents, enforcing explicit approval before executing potentially dangerous operations. This includes decorators for risk classification, customizable approval callbacks, synchronous and asynchronous support, runtime configuration, and extensive tests and examples demonstrating integration with agent tools for Python execution, file, and shell operations.

Changes

File(s) Change Summary
examples/python/general/human_approval_example.py Added a detailed example script demonstrating human-in-the-loop approval for agent operations.
src/praisonai-agents/praisonaiagents/approval.py New module implementing approval decorators, risk levels, callback system, and approval management functions.
src/praisonai-agents/praisonaiagents/agent/agent.py Integrated approval checks into tool execution (sync/async) in the Agent class.
src/praisonai-agents/praisonaiagents/main.py Added global approval callback registry and registration function.
src/praisonai-agents/praisonaiagents/tools/file_tools.py Applied require_approval decorator to all file-modifying methods (write, copy, move, delete).
src/praisonai-agents/praisonaiagents/tools/python_tools.py Applied require_approval decorator to Python code execution method.
src/praisonai-agents/praisonaiagents/tools/shell_tools.py Applied require_approval decorator to shell command and process-killing methods.
src/praisonai/tests/unit/test_approval_basic.py Added comprehensive unit tests for approval decorators, callbacks, and integration with tools and agents.
src/praisonai/tests/unit/test_approval_interactive.py Added interactive and non-interactive tests for approval prompts and callback logic.
src/praisonai/tests/unit/test_approval_agent_integration.py Added integration tests for agent tool execution with approval system.
src/praisonai/tests/unit/test_decorator_enforcement.py Added test to verify decorator enforcement when tools are called directly.
src/praisonai/tests/unit/test_decorator_simple.py Added unit test for improved decorator, context management, and callback scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Agent
    participant ApprovalSystem
    participant Tool

    User->>Agent: Initiate task (e.g., run Python code)
    Agent->>ApprovalSystem: Check if approval required for tool
    alt Approval required
        ApprovalSystem->>User: Prompt for approval (console/async/callback)
        User-->>ApprovalSystem: Approve or Deny
        ApprovalSystem->>Agent: Return approval decision
        alt Approved
            Agent->>Tool: Execute tool with arguments
            Tool-->>Agent: Return result
        else Denied
            Agent-->>User: Report denial, abort execution
        end
    else No approval required
        Agent->>Tool: Execute tool
        Tool-->>Agent: Return result
    end
    Agent-->>User: Return result or error
Loading

Assessment against linked issues

Objective Addressed Explanation
Add human-in-the-loop approval for running Python functions and dangerous agent operations (#12)
Provide risk classification and customizable approval callbacks for agent tool execution (#12)
Support both synchronous and asynchronous approval flows for agent operations (#12)
Enable runtime configuration and testing of approval requirements and integration (#12)

Assessment against linked issues: Out-of-scope changes

No out-of-scope functional code changes were identified. All changes are directly related to implementing, integrating, or testing the human approval system for agent operations as described in the linked issue.

Poem

🐇
In burrows deep, a rabbit spies
Approval prompts before it tries.
With tools in paw, it seeks consent,
For Python code or files are meant
To run with care, not reckless cheer—
Now humans guide what agents steer!
🌱✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @MervinPraison, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello team, Gemini here providing a summary of this pull request. This PR introduces a crucial human-in-the-loop approval system for potentially dangerous tool operations executed by agents. The primary goal is to enhance security and provide users with explicit control over actions like executing shell commands, running code, or performing file system modifications. The implementation includes a new approval module, integration points within the Agent class for both sync and async execution, decorators to mark tools requiring approval, a default console-based approval interface using rich, support for custom approval callbacks, and runtime configuration options for approval requirements. A comprehensive example and basic tests are also included.

Highlights

  • Human-in-the-Loop Approval: Introduces a framework requiring human approval before agents execute certain predefined 'dangerous' tool functions.
  • Risk Level Classification: Tools are assigned risk levels (critical, high, medium, low) to help prioritize and inform approval decisions.
  • Flexible Approval Callbacks: Provides a default console-based interactive approval prompt and allows registering custom callbacks for automated policies or alternative interfaces. Supports modifying tool arguments during approval.
  • Sync and Async Support: The approval flow is integrated into both synchronous (execute_tool) and asynchronous (execute_tool_async) agent execution paths.
  • Runtime Configuration: Approval requirements can be added or removed dynamically at runtime using dedicated functions.
  • Tool Decorators: Uses the @require_approval decorator to easily mark specific tool functions and assign their risk level.

Changelog

Click here to see the changelog
  • examples/python/general/human_approval_example.py
    • Added a new example script demonstrating the human approval system.
    • Includes examples of default console approval, custom callback implementation, and manual requirement configuration.
    • Shows how to use the system with both sync and async agent processes.
  • src/praisonai-agents/praisonaiagents/agent/agent.py
    • Imported necessary functions and the global approval callback from the new approval and main modules (around lines 19-20).
    • Integrated approval check and flow into the synchronous execute_tool method (around lines 574-598).
    • Integrated approval check and flow into the asynchronous execute_tool_async method (around lines 1449-1461).
  • src/praisonai-agents/praisonaiagents/approval.py
    • Added a new module containing the core logic for the human approval framework.
    • Defines global registries for required tools and risk levels.
    • Introduces the ApprovalDecision class and set_approval_callback function.
    • Implements the @require_approval decorator.
    • Provides console_approval_callback as the default interactive handler using rich.
    • Implements the async request_approval function to manage the approval flow, including handling sync callbacks in an executor.
    • Defines default dangerous tools and functions for runtime configuration (add_approval_requirement, remove_approval_requirement).
  • src/praisonai-agents/praisonaiagents/main.py
    • Added a global approval_callback variable (around line 47).
    • Added register_approval_callback function to set the global callback (around lines 74-81).
    • Exported new approval-related items in __all__ (around lines 53-57).
  • src/praisonai-agents/praisonaiagents/tools/file_tools.py
    • Imported the require_approval decorator (around line 19).
    • Applied @require_approval(risk_level="high") to write_file (line 45), copy_file (line 139), move_file (line 162), and delete_file (line 185).
  • src/praisonai-agents/praisonaiagents/tools/python_tools.py
    • Imported the require_approval decorator (around line 18).
    • Applied @require_approval(risk_level="critical") to execute_code (line 40).
  • src/praisonai-agents/praisonaiagents/tools/shell_tools.py
    • Imported the require_approval decorator (around line 16).
    • Applied @require_approval(risk_level="critical") to execute_command (line 35) and kill_process (line 151).
  • test_approval_basic.py
    • Added a new basic test script to verify the core components of the approval system.
    • Tests imports, the ApprovalDecision class, requirement configuration functions, and default dangerous tool configuration.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Agent plans a risky deed,
A human eye is what we need.
'Execute?' it asks with dread,
'Approve' or 'Deny' is said.
Safety first, the code agreed.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a robust human-in-the-loop approval system for dangerous tool operations. The core logic is well-implemented in the new approval.py module, and the integration into the agent's tool execution flow covers both synchronous and asynchronous paths. The use of rich for console interactions and the dynamic configuration options are excellent additions. The provided example script is very helpful for understanding and testing the new functionality.

One critical area for attention is ensuring the custom approval callback registered via the main API is consistently applied in both sync and async tool executions. Additionally, enhancing test coverage for the end-to-end approval flow would further solidify this feature.

Summary of Findings

  • Inconsistent Custom Approval Callback Usage (Async vs. Sync): The custom approval callback registered via praisonaiagents.main.register_approval_callback is correctly used by the synchronous agent.execute_tool path but not by the asynchronous agent.execute_tool_async path. The async path relies on praisonaiagents.approval.request_approval, which uses praisonaiagents.approval.approval_callback. This can lead to the custom callback being ignored in async scenarios.
  • Test Coverage for Approval Flow: The current tests in test_approval_basic.py cover basic imports and configuration. It's recommended to add integration tests that mock user input or the approval callback to verify the end-to-end approval flow within an agent's tool execution.

Merge Readiness

This pull request introduces a significant and well-implemented security feature. However, there is a high-severity issue regarding the consistent application of custom approval callbacks in asynchronous scenarios that should be addressed before merging. Additionally, considering enhancements to test coverage would be beneficial. I am unable to approve pull requests, but I recommend that these changes be made and then the PR be reviewed again before merging.

Comment on lines +74 to +81
def register_approval_callback(callback_fn):
"""Register a global approval callback function for dangerous tool operations.

Args:
callback_fn: Function that takes (function_name, arguments, risk_level) and returns ApprovalDecision
"""
global approval_callback
approval_callback = callback_fn

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

It appears there's a potential inconsistency in how the custom approval callback is applied between synchronous and asynchronous tool executions.

This register_approval_callback function sets praisonaiagents.main.approval_callback.

  • The synchronous Agent.execute_tool method correctly uses this main.approval_callback.
  • However, the asynchronous Agent.execute_tool_async method calls praisonaiagents.approval.request_approval, which in turn uses praisonaiagents.approval.approval_callback (a different global variable from the approval module itself).

This means a callback registered via main.register_approval_callback might not be invoked during asynchronous tool operations, potentially falling back to the default console approval.

Could we ensure that main.register_approval_callback also updates the callback used by the approval module, perhaps by calling approval.set_approval_callback within this function? This would ensure consistent behavior.

def register_approval_callback(callback_fn):
    """Register a global approval callback function for dangerous tool operations.
    
    Args:
        callback_fn: Function that takes (function_name, arguments, risk_level) and returns ApprovalDecision
    """
    global approval_callback
    approval_callback = callback_fn
    # Ensure the approval module also uses this callback for consistency in async paths
    from . import approval as approval_module
    if hasattr(approval_module, 'set_approval_callback'):
        approval_module.set_approval_callback(callback_fn)

Comment thread test_approval_basic.py Outdated
Comment on lines +12 to +142
def test_imports():
"""Test that all the new approval imports work correctly."""
try:
print("Testing approval module import...")
from praisonaiagents.approval import (
require_approval,
ApprovalDecision,
console_approval_callback,
request_approval,
is_approval_required,
get_risk_level,
add_approval_requirement,
remove_approval_requirement
)
print("✅ Approval module imports successful")

print("Testing main module approval functions...")
from praisonaiagents.main import register_approval_callback, approval_callback
print("✅ Main module approval functions imported successfully")

print("Testing agent modifications...")
from praisonaiagents.agent import Agent
print("✅ Agent class imports successfully")

print("Testing tool decorators...")
from praisonaiagents.tools.shell_tools import ShellTools
from praisonaiagents.tools.python_tools import PythonTools
from praisonaiagents.tools.file_tools import FileTools
print("✅ Tool classes with decorators imported successfully")

return True

except ImportError as e:
print(f"❌ Import error: {e}")
return False
except Exception as e:
print(f"❌ Unexpected error: {e}")
return False

def test_approval_decision():
"""Test the ApprovalDecision class."""
try:
from praisonaiagents.approval import ApprovalDecision

# Test approved decision
decision = ApprovalDecision(approved=True, reason="Test approval")
assert decision.approved == True
assert decision.reason == "Test approval"
print("✅ ApprovalDecision class works correctly")

return True
except Exception as e:
print(f"❌ ApprovalDecision test failed: {e}")
return False

def test_approval_requirements():
"""Test approval requirement configuration."""
try:
from praisonaiagents.approval import (
add_approval_requirement,
remove_approval_requirement,
is_approval_required,
get_risk_level
)

# Test adding requirement
add_approval_requirement("test_function", "high")
assert is_approval_required("test_function") == True
assert get_risk_level("test_function") == "high"

# Test removing requirement
remove_approval_requirement("test_function")
assert is_approval_required("test_function") == False
assert get_risk_level("test_function") is None

print("✅ Approval requirement configuration works correctly")
return True

except Exception as e:
print(f"❌ Approval requirements test failed: {e}")
return False

def test_default_dangerous_tools():
"""Test that default dangerous tools are configured."""
try:
from praisonaiagents.approval import is_approval_required, get_risk_level

# Check some default dangerous tools
dangerous_tools = ["execute_command", "execute_code", "write_file", "delete_file"]

for tool in dangerous_tools:
if is_approval_required(tool):
risk = get_risk_level(tool)
print(f"✅ {tool} requires approval (risk: {risk})")
else:
print(f"⚠️ {tool} does not require approval")

return True

except Exception as e:
print(f"❌ Default dangerous tools test failed: {e}")
return False

def main():
"""Run all basic tests."""
print("🧪 Basic Human Approval System Tests")
print("=" * 40)

tests = [
("Import Tests", test_imports),
("ApprovalDecision Tests", test_approval_decision),
("Approval Requirements Tests", test_approval_requirements),
("Default Dangerous Tools Tests", test_default_dangerous_tools)
]

passed = 0
total = len(tests)

for test_name, test_func in tests:
print(f"\n📋 Running {test_name}...")
if test_func():
passed += 1

print(f"\n📊 Test Results: {passed}/{total} tests passed")

if passed == total:
print("🎉 All basic tests passed! Human approval system is working.")
else:
print("❌ Some tests failed. Check the implementation.")

return passed == total

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The basic tests for the approval system are a good start, covering imports and configuration aspects. To further ensure the robustness of this critical security feature, would it be beneficial to add integration tests?

For instance, tests could:

  • Simulate an agent attempting to execute a dangerous tool.
  • Mock the input() function for console_approval_callback or provide a mock custom approval callback.
  • Verify that the approval flow is triggered correctly.
  • Check that operations are allowed or denied based on the (mocked) user's decision.
  • Test the modification of arguments via ApprovalDecision.modified_args.

This would help confirm that the end-to-end approval mechanism works as expected within the agent lifecycle.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (14)
src/praisonai-agents/praisonaiagents/main.py (2)

46-47: Consider renaming global variable to follow naming convention.

The global variable works correctly but doesn't follow Python naming conventions for module-level constants.

Consider renaming to follow the UPPER_CASE convention:

-# Global approval callback registry
-approval_callback = None
+# Global approval callback registry
+APPROVAL_CALLBACK = None

And update the function accordingly:

-    global approval_callback
-    approval_callback = callback_fn
+    global APPROVAL_CALLBACK
+    APPROVAL_CALLBACK = callback_fn
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 47-47: Constant name "approval_callback" doesn't conform to UPPER_CASE naming style

(C0103)


74-82: Function implementation is correct with minor style suggestion.

The register_approval_callback function correctly implements the global callback registration mechanism.

Consider shortening the docstring line to meet the 100-character limit:

-        callback_fn: Function that takes (function_name, arguments, risk_level) and returns ApprovalDecision
+        callback_fn: Function that returns ApprovalDecision for tool approval requests
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 78-78: Line too long (108/100)

(C0301)


[warning] 80-80: Using the global statement

(W0603)

test_approval_basic.py (2)

94-114: Clean up imports and improve readability.

The test validates important default configurations correctly.

Minor style improvement:

 def test_default_dangerous_tools():
     """Test that default dangerous tools are configured."""
     try:
-        from praisonaiagents.approval import is_approval_required, get_risk_level
-        
         # Check some default dangerous tools
         dangerous_tools = ["execute_command", "execute_code", "write_file", "delete_file"]
-        
         for tool in dangerous_tools:
             if is_approval_required(tool):
                 risk = get_risk_level(tool)
                 print(f"✅ {tool} requires approval (risk: {risk})")
             else:
                 print(f"⚠️  {tool} does not require approval")
-        
         return True
-        
     except Exception as e:
         print(f"❌ Default dangerous tools test failed: {e}")
         return False
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 98-98: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 108-108: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[warning] 111-111: Catching too general exception Exception

(W0718)


[error] 97-97: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 97-97: Import outside toplevel (praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level)

(C0415)


144-146: Add missing final newline.

The script structure is good but missing the final newline.

Add a final newline at the end of the file:

 if __name__ == "__main__":
     success = main()
     sys.exit(0 if success else 1)
+
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 146-146: Final newline missing

(C0304)


[convention] 145-145: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

src/praisonai-agents/praisonaiagents/agent/agent.py (3)

574-599: Fix formatting issues and improve logging efficiency.

The approval checking logic is well-implemented with proper error handling and decision processing. However, there are some formatting and code quality issues to address:

Apply this diff to fix the formatting and logging issues:

-        # Check if approval is required for this tool
-        from ..approval import is_approval_required, console_approval_callback, get_risk_level
-        if is_approval_required(function_name):
-            risk_level = get_risk_level(function_name)
-            logging.info(f"Tool {function_name} requires approval (risk level: {risk_level})")
-            
-            # Use global approval callback or default console callback
-            callback = approval_callback or console_approval_callback
-            
-            try:
-                decision = callback(function_name, arguments, risk_level)
-                if not decision.approved:
-                    error_msg = f"Tool execution denied: {decision.reason}"
-                    logging.warning(error_msg)
-                    return {"error": error_msg, "approval_denied": True}
-                
-                # Use modified arguments if provided
-                if decision.modified_args:
-                    arguments = decision.modified_args
-                    logging.info(f"Using modified arguments: {arguments}")
-                    
-            except Exception as e:
-                error_msg = f"Error during approval process: {str(e)}"
-                logging.error(error_msg)
-                return {"error": error_msg, "approval_error": True}
+        # Check if approval is required for this tool
+        from ..approval import is_approval_required, console_approval_callback, get_risk_level
+        if is_approval_required(function_name):
+            risk_level = get_risk_level(function_name)
+            logging.info("Tool %s requires approval (risk level: %s)", function_name, risk_level)
+
+            # Use global approval callback or default console callback
+            callback = approval_callback or console_approval_callback
+
+            try:
+                decision = callback(function_name, arguments, risk_level)
+                if not decision.approved:
+                    error_msg = f"Tool execution denied: {decision.reason}"
+                    logging.warning(error_msg)
+                    return {"error": error_msg, "approval_denied": True}
+
+                # Use modified arguments if provided
+                if decision.modified_args:
+                    arguments = decision.modified_args
+                    logging.info("Using modified arguments: %s", arguments)
+
+            except Exception as e:
+                error_msg = f"Error during approval process: {str(e)}"
+                logging.error(error_msg)
+                return {"error": error_msg, "approval_error": True}
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 579-579: Trailing whitespace

(C0303)


[convention] 582-582: Trailing whitespace

(C0303)


[convention] 589-589: Trailing whitespace

(C0303)


[convention] 594-594: Trailing whitespace

(C0303)


[convention] 575-575: Import outside toplevel (approval.is_approval_required, approval.console_approval_callback, approval.get_risk_level)

(C0415)


[warning] 578-578: Use lazy % formatting in logging functions

(W1203)


[warning] 595-595: Catching too general exception Exception

(W0718)


[warning] 593-593: Use lazy % formatting in logging functions

(W1203)


1448-1462: Fix formatting issues and improve logging efficiency in async method.

The async approval checking logic is correctly implemented and mirrors the synchronous version appropriately. However, similar formatting and logging issues need to be addressed:

Apply this diff to fix the formatting and logging issues:

-            
-            # Check if approval is required for this tool
-            from ..approval import is_approval_required, request_approval
-            if is_approval_required(function_name):
-                decision = await request_approval(function_name, arguments)
-                if not decision.approved:
-                    error_msg = f"Tool execution denied: {decision.reason}"
-                    logging.warning(error_msg)
-                    return {"error": error_msg, "approval_denied": True}
-                
-                # Use modified arguments if provided
-                if decision.modified_args:
-                    arguments = decision.modified_args
-                    logging.info(f"Using modified arguments: {arguments}")
-            
+
+            # Check if approval is required for this tool
+            from ..approval import is_approval_required, request_approval
+            if is_approval_required(function_name):
+                decision = await request_approval(function_name, arguments)
+                if not decision.approved:
+                    error_msg = f"Tool execution denied: {decision.reason}"
+                    logging.warning(error_msg)
+                    return {"error": error_msg, "approval_denied": True}
+
+                # Use modified arguments if provided
+                if decision.modified_args:
+                    arguments = decision.modified_args
+                    logging.info("Using modified arguments: %s", arguments)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1448-1448: Trailing whitespace

(C0303)


[convention] 1457-1457: Trailing whitespace

(C0303)


[convention] 1462-1462: Trailing whitespace

(C0303)


[convention] 1450-1450: Import outside toplevel (approval.is_approval_required, approval.request_approval)

(C0415)


[warning] 1461-1461: Use lazy % formatting in logging functions

(W1203)


574-599: Consider moving approval imports to module level for better performance.

The current implementation imports approval functions inside the methods, which could impact performance if these methods are called frequently. Consider moving the imports to the module level for better efficiency.

Move the approval imports to the top of the file with the other imports:

 from ..main import (
     display_error,
     display_tool_call,
     display_instruction,
     display_interaction,
     display_generating,
     display_self_reflection,
     ReflectionOutput,
     client,
     adisplay_instruction,
     approval_callback
 )
+from ..approval import is_approval_required, console_approval_callback, get_risk_level, request_approval
 import inspect
 import uuid
 from dataclasses import dataclass

Then update the method implementations to remove the local imports:

         # Check if approval is required for this tool
-        from ..approval import is_approval_required, console_approval_callback, get_risk_level
         if is_approval_required(function_name):
             # Check if approval is required for this tool
-            from ..approval import is_approval_required, request_approval
             if is_approval_required(function_name):

Also applies to: 1448-1462

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 579-579: Trailing whitespace

(C0303)


[convention] 582-582: Trailing whitespace

(C0303)


[convention] 589-589: Trailing whitespace

(C0303)


[convention] 594-594: Trailing whitespace

(C0303)


[convention] 575-575: Import outside toplevel (approval.is_approval_required, approval.console_approval_callback, approval.get_risk_level)

(C0415)


[warning] 578-578: Use lazy % formatting in logging functions

(W1203)


[warning] 595-595: Catching too general exception Exception

(W0718)


[warning] 593-593: Use lazy % formatting in logging functions

(W1203)

examples/python/general/human_approval_example.py (3)

34-59: Remove unnecessary f-string prefix.

The function logic is excellent, demonstrating automated approval policies. However, there's a minor syntax issue.

Apply this diff to fix the f-string without placeholders:

-    print(f"\n🔒 CUSTOM APPROVAL REQUIRED")
+    print("\n🔒 CUSTOM APPROVAL REQUIRED")
🧰 Tools
🪛 Ruff (0.11.9)

39-39: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[convention] 34-34: Line too long (103/100)

(C0301)


[convention] 43-43: Trailing whitespace

(C0303)


[convention] 48-48: Trailing whitespace

(C0303)


[convention] 51-51: Trailing whitespace

(C0303)


[convention] 56-56: Trailing whitespace

(C0303)


[warning] 39-39: Using an f-string that does not have any interpolated variables

(W1309)


119-122: Remove unnecessary f-string prefix.

Apply this diff to fix the f-string without placeholders:

-        print(f"\n✅ Process completed successfully!")
+        print("\n✅ Process completed successfully!")
🧰 Tools
🪛 Ruff (0.11.9)

120-120: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[warning] 120-120: Using an f-string that does not have any interpolated variables

(W1309)


198-204: Add missing final newline and clean up formatting.

The demo conclusion is well-structured with clear takeaways. However, there are formatting issues throughout the file.

Add a newline at the end of the file and consider running a formatter to remove trailing whitespace throughout the file. Many lines have trailing spaces that should be removed for cleaner code.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 204-204: Final newline missing

(C0304)

src/praisonai-agents/praisonaiagents/approval.py (4)

27-33: Consider using dataclass for ApprovalDecision.

The class structure is correct, but could benefit from modern Python features.

Consider converting to a dataclass for better type hints and cleaner syntax:

+from dataclasses import dataclass, field
+
-class ApprovalDecision:
-    """Result of an approval request"""
-    def __init__(self, approved: bool, modified_args: Optional[Dict[str, Any]] = None, reason: str = ""):
-        self.approved = approved
-        self.modified_args = modified_args or {}
-        self.reason = reason
+@dataclass
+class ApprovalDecision:
+    """Result of an approval request"""
+    approved: bool
+    modified_args: Dict[str, Any] = field(default_factory=dict)
+    reason: str = ""
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 29-29: Line too long (105/100)

(C0301)


[refactor] 27-27: Too few public methods (0/2)

(R0903)


86-96: Remove unnecessary f-string prefix.

The console display implementation is excellent with good formatting and truncation logic.

Apply this diff to fix the f-string without placeholders:

-    tool_info += f"[bold]Arguments:[/]\n"
+    tool_info += "[bold]Arguments:[/]\n"
🧰 Tools
🪛 Ruff (0.11.9)

88-88: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[convention] 89-89: Trailing whitespace

(C0303)


[convention] 96-96: Trailing whitespace

(C0303)


[warning] 88-88: Using an f-string that does not have any interpolated variables

(W1309)


125-158: Excellent async/sync callback handling.

The function properly handles both synchronous and asynchronous approval callbacks, using run_in_executor to prevent blocking the event loop for sync callbacks. The error handling is comprehensive.

Consider using lazy formatting for the logging statement on line 156 to follow logging best practices:

-        logging.error(f"Error in approval callback: {e}")
+        logging.error("Error in approval callback: %s", e)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 138-138: Trailing whitespace

(C0303)


[convention] 140-140: Trailing whitespace

(C0303)


[convention] 143-143: Trailing whitespace

(C0303)


[convention] 151-151: Line too long (103/100)

(C0301)


[convention] 152-152: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[warning] 155-155: Catching too general exception Exception

(W0718)


[warning] 156-156: Use lazy % formatting in logging functions

(W1203)


159-204: Well-designed configuration system with sensible defaults.

The default dangerous tools are appropriately categorized by risk level, and the helper functions provide good flexibility for runtime configuration.

Add a newline at the end of the file to follow standard file formatting conventions.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 165-165: Trailing whitespace

(C0303)


[convention] 172-172: Trailing whitespace

(C0303)


[convention] 204-204: Final newline missing

(C0304)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a9fa87 and ca6be70.

📒 Files selected for processing (8)
  • examples/python/general/human_approval_example.py (1 hunks)
  • src/praisonai-agents/praisonaiagents/agent/agent.py (3 hunks)
  • src/praisonai-agents/praisonaiagents/approval.py (1 hunks)
  • src/praisonai-agents/praisonaiagents/main.py (2 hunks)
  • src/praisonai-agents/praisonaiagents/tools/file_tools.py (5 hunks)
  • src/praisonai-agents/praisonaiagents/tools/python_tools.py (2 hunks)
  • src/praisonai-agents/praisonaiagents/tools/shell_tools.py (3 hunks)
  • test_approval_basic.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/praisonai-agents/praisonaiagents/tools/python_tools.py (1)
src/praisonai-agents/praisonaiagents/approval.py (1)
  • require_approval (42-67)
src/praisonai-agents/praisonaiagents/tools/shell_tools.py (1)
src/praisonai-agents/praisonaiagents/approval.py (1)
  • require_approval (42-67)
test_approval_basic.py (3)
src/praisonai-agents/praisonaiagents/approval.py (8)
  • require_approval (42-67)
  • ApprovalDecision (27-32)
  • console_approval_callback (69-123)
  • request_approval (125-157)
  • is_approval_required (195-197)
  • get_risk_level (199-201)
  • add_approval_requirement (185-188)
  • remove_approval_requirement (190-193)
src/praisonai-agents/praisonaiagents/main.py (1)
  • register_approval_callback (74-81)
src/praisonai-agents/praisonaiagents/agent/agent.py (1)
  • Agent (205-1827)
src/praisonai-agents/praisonaiagents/agent/agent.py (1)
src/praisonai-agents/praisonaiagents/approval.py (4)
  • is_approval_required (195-197)
  • console_approval_callback (69-123)
  • get_risk_level (199-201)
  • request_approval (125-157)
examples/python/general/human_approval_example.py (3)
src/praisonai-agents/praisonaiagents/agent/agent.py (2)
  • Agent (205-1827)
  • run (1436-1438)
src/praisonai-agents/praisonaiagents/main.py (1)
  • register_approval_callback (74-81)
src/praisonai-agents/praisonaiagents/approval.py (4)
  • console_approval_callback (69-123)
  • ApprovalDecision (27-32)
  • add_approval_requirement (185-188)
  • remove_approval_requirement (190-193)
src/praisonai-agents/praisonaiagents/tools/file_tools.py (1)
src/praisonai-agents/praisonaiagents/approval.py (1)
  • require_approval (42-67)
src/praisonai-agents/praisonaiagents/approval.py (1)
src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py (1)
  • get_event_loop (22-28)
🪛 Pylint (3.3.7)
src/praisonai-agents/praisonaiagents/main.py

[convention] 47-47: Constant name "approval_callback" doesn't conform to UPPER_CASE naming style

(C0103)


[convention] 78-78: Line too long (108/100)

(C0301)


[warning] 80-80: Using the global statement

(W0603)

test_approval_basic.py

[convention] 9-9: Trailing whitespace

(C0303)


[convention] 27-27: Trailing whitespace

(C0303)


[convention] 31-31: Trailing whitespace

(C0303)


[convention] 35-35: Trailing whitespace

(C0303)


[convention] 38-38: Trailing whitespace

(C0303)


[convention] 41-41: Trailing whitespace

(C0303)


[convention] 43-43: Trailing whitespace

(C0303)


[convention] 55-55: Trailing whitespace

(C0303)


[convention] 61-61: Trailing whitespace

(C0303)


[convention] 76-76: Trailing whitespace

(C0303)


[convention] 81-81: Trailing whitespace

(C0303)


[convention] 86-86: Trailing whitespace

(C0303)


[convention] 89-89: Trailing whitespace

(C0303)


[convention] 98-98: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 108-108: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 126-126: Trailing whitespace

(C0303)


[convention] 129-129: Trailing whitespace

(C0303)


[convention] 134-134: Trailing whitespace

(C0303)


[convention] 136-136: Trailing whitespace

(C0303)


[convention] 141-141: Trailing whitespace

(C0303)


[convention] 146-146: Final newline missing

(C0304)


[warning] 47-47: Catching too general exception Exception

(W0718)


[convention] 16-25: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.ApprovalDecision, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.request_approval, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level, praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement)

(C0415)


[convention] 29-29: Import outside toplevel (praisonaiagents.main.register_approval_callback, praisonaiagents.main.approval_callback)

(C0415)


[convention] 33-33: Import outside toplevel (praisonaiagents.agent.Agent)

(C0415)


[convention] 37-37: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[convention] 38-38: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[convention] 39-39: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[warning] 16-25: Unused require_approval imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused ApprovalDecision imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused console_approval_callback imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused request_approval imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused is_approval_required imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused get_risk_level imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused add_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused remove_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)


[warning] 29-29: Unused approval_callback imported from praisonaiagents.main

(W0611)


[warning] 33-33: Unused Agent imported from praisonaiagents.agent

(W0611)


[warning] 37-37: Unused ShellTools imported from praisonaiagents.tools.shell_tools

(W0611)


[warning] 38-38: Unused PythonTools imported from praisonaiagents.tools.python_tools

(W0611)


[warning] 39-39: Unused FileTools imported from praisonaiagents.tools.file_tools

(W0611)


[warning] 63-63: Catching too general exception Exception

(W0718)


[error] 54-54: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 54-54: Import outside toplevel (praisonaiagents.approval.ApprovalDecision)

(C0415)


[convention] 58-58: Comparison 'decision.approved == True' should be 'decision.approved is True' if checking for the singleton value True, or 'decision.approved' if testing for truthiness

(C0121)


[warning] 90-90: Catching too general exception Exception

(W0718)


[error] 70-75: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 70-75: Import outside toplevel (praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level)

(C0415)


[convention] 79-79: Comparison 'is_approval_required('test_function') == True' should be 'is_approval_required('test_function') is True' if checking for the singleton value True, or 'is_approval_required('test_function')' if testing for truthiness

(C0121)


[convention] 84-84: Comparison 'is_approval_required('test_function') == False' should be 'is_approval_required('test_function') is False' if checking for the singleton value False, or 'not is_approval_required('test_function')' if testing for falsiness

(C0121)


[warning] 111-111: Catching too general exception Exception

(W0718)


[error] 97-97: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 97-97: Import outside toplevel (praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level)

(C0415)


[convention] 145-145: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

src/praisonai-agents/praisonaiagents/agent/agent.py

[convention] 579-579: Trailing whitespace

(C0303)


[convention] 582-582: Trailing whitespace

(C0303)


[convention] 589-589: Trailing whitespace

(C0303)


[convention] 594-594: Trailing whitespace

(C0303)


[convention] 575-575: Import outside toplevel (approval.is_approval_required, approval.console_approval_callback, approval.get_risk_level)

(C0415)


[warning] 578-578: Use lazy % formatting in logging functions

(W1203)


[warning] 595-595: Catching too general exception Exception

(W0718)


[warning] 593-593: Use lazy % formatting in logging functions

(W1203)


[convention] 1448-1448: Trailing whitespace

(C0303)


[convention] 1457-1457: Trailing whitespace

(C0303)


[convention] 1462-1462: Trailing whitespace

(C0303)


[convention] 1450-1450: Import outside toplevel (approval.is_approval_required, approval.request_approval)

(C0415)


[warning] 1461-1461: Use lazy % formatting in logging functions

(W1203)

examples/python/general/human_approval_example.py

[convention] 25-25: Trailing whitespace

(C0303)


[convention] 34-34: Line too long (103/100)

(C0301)


[convention] 43-43: Trailing whitespace

(C0303)


[convention] 48-48: Trailing whitespace

(C0303)


[convention] 51-51: Trailing whitespace

(C0303)


[convention] 56-56: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 68-68: Trailing whitespace

(C0303)


[convention] 73-73: Trailing whitespace

(C0303)


[convention] 82-82: Trailing whitespace

(C0303)


[convention] 106-106: Trailing whitespace

(C0303)


[convention] 113-113: Trailing whitespace

(C0303)


[convention] 117-117: Trailing whitespace

(C0303)


[convention] 129-129: Trailing whitespace

(C0303)


[convention] 132-132: Trailing whitespace

(C0303)


[convention] 136-136: Trailing whitespace

(C0303)


[convention] 140-140: Trailing whitespace

(C0303)


[convention] 148-148: Trailing whitespace

(C0303)


[convention] 151-151: Trailing whitespace

(C0303)


[convention] 155-155: Trailing whitespace

(C0303)


[convention] 160-160: Trailing whitespace

(C0303)


[convention] 167-167: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 182-182: Trailing whitespace

(C0303)


[convention] 185-185: Trailing whitespace

(C0303)


[convention] 188-188: Trailing whitespace

(C0303)


[convention] 197-197: Trailing whitespace

(C0303)


[convention] 204-204: Final newline missing

(C0304)


[error] 21-21: Unable to import 'praisonaiagents'

(E0401)


[error] 22-22: Unable to import 'praisonaiagents.tools'

(E0401)


[error] 23-23: Unable to import 'praisonaiagents.main'

(E0401)


[error] 24-29: Unable to import 'praisonaiagents.approval'

(E0401)


[warning] 39-39: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 124-124: Catching too general exception Exception

(W0718)


[warning] 120-120: Using an f-string that does not have any interpolated variables

(W1309)


[error] 142-142: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 142-142: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 177-177: Catching too general exception Exception

(W0718)


[warning] 23-23: Unused register_approval_callback imported from praisonaiagents.main

(W0611)

src/praisonai-agents/praisonaiagents/approval.py

[convention] 29-29: Line too long (105/100)

(C0301)


[convention] 52-52: Trailing whitespace

(C0303)


[convention] 56-56: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 66-66: Trailing whitespace

(C0303)


[convention] 69-69: Line too long (114/100)

(C0301)


[convention] 75-75: Trailing whitespace

(C0303)


[convention] 84-84: Trailing whitespace

(C0303)


[convention] 89-89: Trailing whitespace

(C0303)


[convention] 96-96: Trailing whitespace

(C0303)


[convention] 103-103: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[convention] 117-117: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 140-140: Trailing whitespace

(C0303)


[convention] 143-143: Trailing whitespace

(C0303)


[convention] 151-151: Line too long (103/100)

(C0301)


[convention] 152-152: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 165-165: Trailing whitespace

(C0303)


[convention] 172-172: Trailing whitespace

(C0303)


[convention] 204-204: Final newline missing

(C0304)


[refactor] 27-27: Too few public methods (0/2)

(R0903)


[warning] 39-39: Using the global statement

(W0603)


[refactor] 62-65: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 88-88: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 121-121: Catching too general exception Exception

(W0718)


[refactor] 111-116: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 155-155: Catching too general exception Exception

(W0718)


[warning] 156-156: Use lazy % formatting in logging functions

(W1203)


[warning] 14-14: Unused Text imported from rich.text

(W0611)

🪛 Ruff (0.11.9)
test_approval_basic.py

17-17: praisonaiagents.approval.require_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


18-18: praisonaiagents.approval.ApprovalDecision imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


19-19: praisonaiagents.approval.console_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


20-20: praisonaiagents.approval.request_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


21-21: praisonaiagents.approval.is_approval_required imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


22-22: praisonaiagents.approval.get_risk_level imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


23-23: praisonaiagents.approval.add_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


24-24: praisonaiagents.approval.remove_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


29-29: praisonaiagents.main.register_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


29-29: praisonaiagents.main.approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


33-33: praisonaiagents.agent.Agent imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


37-37: praisonaiagents.tools.shell_tools.ShellTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


38-38: praisonaiagents.tools.python_tools.PythonTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


39-39: praisonaiagents.tools.file_tools.FileTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


58-58: Avoid equality comparisons to True; use if decision.approved: for truth checks

Replace with decision.approved

(E712)


79-79: Avoid equality comparisons to True; use if is_approval_required("test_function"): for truth checks

Replace with is_approval_required("test_function")

(E712)


84-84: Avoid equality comparisons to False; use if not is_approval_required("test_function"): for false checks

Replace with not is_approval_required("test_function")

(E712)

examples/python/general/human_approval_example.py

23-23: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)


39-39: f-string without any placeholders

Remove extraneous f prefix

(F541)


120-120: f-string without any placeholders

Remove extraneous f prefix

(F541)

src/praisonai-agents/praisonaiagents/approval.py

14-14: rich.text.Text imported but unused

Remove unused import: rich.text.Text

(F401)


88-88: f-string without any placeholders

Remove extraneous f prefix

(F541)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: quick-test
  • GitHub Check: test-core (3.11)
🔇 Additional comments (15)
src/praisonai-agents/praisonaiagents/tools/python_tools.py (2)

18-18: Import statement looks good.

The import of require_approval from the approval module is properly placed and follows the existing import structure.


40-40: Excellent security enhancement with appropriate risk level.

Adding the @require_approval(risk_level="critical") decorator to the execute_code method is a crucial security improvement. Code execution is indeed a critical risk operation that should require explicit human approval before proceeding.

src/praisonai-agents/praisonaiagents/tools/shell_tools.py (3)

16-16: Import statement is correctly placed.

The import of require_approval follows the proper import structure and integrates well with existing imports.


35-35: Critical security improvement for shell command execution.

Adding the @require_approval(risk_level="critical") decorator to execute_command is essential for security. Shell command execution poses significant risks and absolutely should require human approval.


151-151: Appropriate security measure for process termination.

The @require_approval(risk_level="critical") decorator on kill_process is well-justified. Process termination can have severe system impacts and requiring approval is a prudent security measure.

src/praisonai-agents/praisonaiagents/main.py (1)

53-58: Exports are properly configured.

The addition of approval-related exports to __all__ is correctly implemented and maintains the module's public API.

src/praisonai-agents/praisonaiagents/tools/file_tools.py (5)

19-19: LGTM: Approval system import added correctly.

The import statement properly brings in the require_approval decorator from the approval module to enable human-in-the-loop approval for dangerous file operations.


44-46: LGTM: Write operation properly protected with approval.

The write_file method is correctly decorated with @require_approval(risk_level="high"), which is appropriate since writing files can overwrite existing content and potentially cause data loss. The decorator placement above the method definition follows Python conventions.

🧰 Tools
🪛 Pylint (3.3.7)

[warning] 46-46: Redefining name 'content' from outer scope (line 235)

(W0621)


138-140: LGTM: Copy operation properly protected with approval.

The copy_file method is correctly decorated with @require_approval(risk_level="high"), which is appropriate since copying files can overwrite existing files at the destination. The risk level aligns with other file modification operations.


161-163: LGTM: Move operation properly protected with approval.

The move_file method is correctly decorated with @require_approval(risk_level="high"), which is appropriate since moving files can overwrite existing files and remove files from their original location. The risk level is consistent with other destructive file operations.


184-186: LGTM: Delete operation properly protected with approval.

The delete_file method is correctly decorated with @require_approval(risk_level="high"), which is appropriate since deleting files is irreversible and can cause data loss. The risk level matches other potentially destructive file operations.

src/praisonai-agents/praisonaiagents/agent/agent.py (1)

19-21: LGTM: Approval callback import added correctly.

The import of approval_callback from the main module enables access to the global approval callback configuration, which is necessary for the approval system integration.

examples/python/general/human_approval_example.py (2)

19-29: LGTM! Well-organized imports.

The imports are properly structured and include all necessary components for demonstrating the approval system.

🧰 Tools
🪛 Ruff (0.11.9)

23-23: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)

🪛 Pylint (3.3.7)

[convention] 25-25: Trailing whitespace

(C0303)


[error] 21-21: Unable to import 'praisonaiagents'

(E0401)


[error] 22-22: Unable to import 'praisonaiagents.tools'

(E0401)


[error] 23-23: Unable to import 'praisonaiagents.main'

(E0401)


[error] 24-29: Unable to import 'praisonaiagents.approval'

(E0401)


[warning] 23-23: Unused register_approval_callback imported from praisonaiagents.main

(W0611)


127-145: Good demonstration of dynamic approval configuration.

This function effectively shows how to add and remove approval requirements at runtime, which is valuable for users who need to customize the approval system.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 129-129: Trailing whitespace

(C0303)


[convention] 132-132: Trailing whitespace

(C0303)


[convention] 136-136: Trailing whitespace

(C0303)


[convention] 140-140: Trailing whitespace

(C0303)


[error] 142-142: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 142-142: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)

src/praisonai-agents/praisonaiagents/approval.py (1)

42-68: Well-designed decorator pattern.

The decorator effectively marks tools for approval while preserving their original behavior. The actual approval enforcement happens in the Agent class, which is a good separation of concerns.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 52-52: Trailing whitespace

(C0303)


[convention] 56-56: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 66-66: Trailing whitespace

(C0303)


[refactor] 62-65: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

Comment thread test_approval_basic.py Outdated
Comment on lines +51 to +66
def test_approval_decision():
"""Test the ApprovalDecision class."""
try:
from praisonaiagents.approval import ApprovalDecision

# Test approved decision
decision = ApprovalDecision(approved=True, reason="Test approval")
assert decision.approved == True
assert decision.reason == "Test approval"
print("✅ ApprovalDecision class works correctly")

return True
except Exception as e:
print(f"❌ ApprovalDecision test failed: {e}")
return False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix boolean comparison and move imports to top level.

The test logic is correct but needs style improvements.

Apply these fixes:

 def test_approval_decision():
     """Test the ApprovalDecision class."""
     try:
-        from praisonaiagents.approval import ApprovalDecision
-        
         # Test approved decision
         decision = ApprovalDecision(approved=True, reason="Test approval")
-        assert decision.approved == True
+        assert decision.approved
         assert decision.reason == "Test approval"
         print("✅ ApprovalDecision class works correctly")
-        
         return True
     except Exception as e:
         print(f"❌ ApprovalDecision test failed: {e}")
         return False

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.11.9)

58-58: Avoid equality comparisons to True; use if decision.approved: for truth checks

Replace with decision.approved

(E712)

🪛 Pylint (3.3.7)

[convention] 55-55: Trailing whitespace

(C0303)


[convention] 61-61: Trailing whitespace

(C0303)


[warning] 63-63: Catching too general exception Exception

(W0718)


[error] 54-54: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 54-54: Import outside toplevel (praisonaiagents.approval.ApprovalDecision)

(C0415)


[convention] 58-58: Comparison 'decision.approved == True' should be 'decision.approved is True' if checking for the singleton value True, or 'decision.approved' if testing for truthiness

(C0121)

🤖 Prompt for AI Agents
In test_approval_basic.py around lines 51 to 66, the test function compares
booleans using '== True', which is unnecessary and should be simplified to
direct boolean checks. Also, move the import statement for ApprovalDecision to
the top of the file outside the test function to follow best practices. Update
the assertions to use direct boolean evaluation and relocate the import
accordingly.

Comment thread test_approval_basic.py Outdated
Comment on lines +67 to +93
def test_approval_requirements():
"""Test approval requirement configuration."""
try:
from praisonaiagents.approval import (
add_approval_requirement,
remove_approval_requirement,
is_approval_required,
get_risk_level
)

# Test adding requirement
add_approval_requirement("test_function", "high")
assert is_approval_required("test_function") == True
assert get_risk_level("test_function") == "high"

# Test removing requirement
remove_approval_requirement("test_function")
assert is_approval_required("test_function") == False
assert get_risk_level("test_function") is None

print("✅ Approval requirement configuration works correctly")
return True

except Exception as e:
print(f"❌ Approval requirements test failed: {e}")
return False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix boolean comparisons and improve code style.

The test logic is sound but needs boolean comparison fixes.

Apply these improvements:

 def test_approval_requirements():
     """Test approval requirement configuration."""
     try:
-        from praisonaiagents.approval import (
-            add_approval_requirement,
-            remove_approval_requirement,
-            is_approval_required,
-            get_risk_level
-        )
-        
         # Test adding requirement
         add_approval_requirement("test_function", "high")
-        assert is_approval_required("test_function") == True
+        assert is_approval_required("test_function")
         assert get_risk_level("test_function") == "high"
-        
         # Test removing requirement
         remove_approval_requirement("test_function")
-        assert is_approval_required("test_function") == False
+        assert not is_approval_required("test_function")
         assert get_risk_level("test_function") is None
-        
         print("✅ Approval requirement configuration works correctly")
         return True
-        
     except Exception as e:
         print(f"❌ Approval requirements test failed: {e}")
         return False

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.11.9)

79-79: Avoid equality comparisons to True; use if is_approval_required("test_function"): for truth checks

Replace with is_approval_required("test_function")

(E712)


84-84: Avoid equality comparisons to False; use if not is_approval_required("test_function"): for false checks

Replace with not is_approval_required("test_function")

(E712)

🪛 Pylint (3.3.7)

[convention] 76-76: Trailing whitespace

(C0303)


[convention] 81-81: Trailing whitespace

(C0303)


[convention] 86-86: Trailing whitespace

(C0303)


[convention] 89-89: Trailing whitespace

(C0303)


[warning] 90-90: Catching too general exception Exception

(W0718)


[error] 70-75: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 70-75: Import outside toplevel (praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level)

(C0415)


[convention] 79-79: Comparison 'is_approval_required('test_function') == True' should be 'is_approval_required('test_function') is True' if checking for the singleton value True, or 'is_approval_required('test_function')' if testing for truthiness

(C0121)


[convention] 84-84: Comparison 'is_approval_required('test_function') == False' should be 'is_approval_required('test_function') is False' if checking for the singleton value False, or 'not is_approval_required('test_function')' if testing for falsiness

(C0121)

🤖 Prompt for AI Agents
In test_approval_basic.py around lines 67 to 93, the boolean comparisons should
be fixed by using explicit True or False checks with 'is' instead of '=='.
Update the assertions to use 'is True' or 'is False' for clarity and
correctness. Also, improve code style by ensuring consistent spacing and
removing unnecessary comments or redundant code to make the test cleaner and
more readable.

Comment thread test_approval_basic.py Outdated
Comment on lines +12 to +50
def test_imports():
"""Test that all the new approval imports work correctly."""
try:
print("Testing approval module import...")
from praisonaiagents.approval import (
require_approval,
ApprovalDecision,
console_approval_callback,
request_approval,
is_approval_required,
get_risk_level,
add_approval_requirement,
remove_approval_requirement
)
print("✅ Approval module imports successful")

print("Testing main module approval functions...")
from praisonaiagents.main import register_approval_callback, approval_callback
print("✅ Main module approval functions imported successfully")

print("Testing agent modifications...")
from praisonaiagents.agent import Agent
print("✅ Agent class imports successfully")

print("Testing tool decorators...")
from praisonaiagents.tools.shell_tools import ShellTools
from praisonaiagents.tools.python_tools import PythonTools
from praisonaiagents.tools.file_tools import FileTools
print("✅ Tool classes with decorators imported successfully")

return True

except ImportError as e:
print(f"❌ Import error: {e}")
return False
except Exception as e:
print(f"❌ Unexpected error: {e}")
return False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor import testing to follow best practices.

The test logic is sound but has several style issues that should be addressed.

Consider this refactored approach to fix the import issues and style problems:

+# Move imports to top level
+import sys
+import os
+
+# Add the src directory to Python path  
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
+
+# Import all modules at top level
+try:
+    from praisonaiagents.approval import (
+        require_approval,
+        ApprovalDecision,
+        console_approval_callback,
+        request_approval,
+        is_approval_required,
+        get_risk_level,
+        add_approval_requirement,
+        remove_approval_requirement
+    )
+    from praisonaiagents.main import register_approval_callback, approval_callback
+    from praisonaiagents.agent import Agent
+    from praisonaiagents.tools.shell_tools import ShellTools
+    from praisonaiagents.tools.python_tools import PythonTools
+    from praisonaiagents.tools.file_tools import FileTools
+    IMPORTS_AVAILABLE = True
+except ImportError as e:
+    IMPORTS_AVAILABLE = False
+    IMPORT_ERROR = e

 def test_imports():
     """Test that all the new approval imports work correctly."""
-    try:
-        print("Testing approval module import...")
-        from praisonaiagents.approval import (
-            require_approval,
-            ApprovalDecision,
-            console_approval_callback,
-            request_approval,
-            is_approval_required,
-            get_risk_level,
-            add_approval_requirement,
-            remove_approval_requirement
-        )
-        print("✅ Approval module imports successful")
-        
-        print("Testing main module approval functions...")
-        from praisonaiagents.main import register_approval_callback, approval_callback
-        print("✅ Main module approval functions imported successfully")
-        
-        print("Testing agent modifications...")
-        from praisonaiagents.agent import Agent
-        print("✅ Agent class imports successfully")
-        
-        print("Testing tool decorators...")
-        from praisonaiagents.tools.shell_tools import ShellTools
-        from praisonaiagents.tools.python_tools import PythonTools  
-        from praisonaiagents.tools.file_tools import FileTools
-        print("✅ Tool classes with decorators imported successfully")
-        
+    if IMPORTS_AVAILABLE:
+        print("✅ All approval system imports successful")
         return True
-        
-    except ImportError as e:
-        print(f"❌ Import error: {e}")
+    else:
+        print(f"❌ Import error: {IMPORT_ERROR}")
         return False
-    except Exception as e:
-        print(f"❌ Unexpected error: {e}")
-        return False
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_imports():
"""Test that all the new approval imports work correctly."""
try:
print("Testing approval module import...")
from praisonaiagents.approval import (
require_approval,
ApprovalDecision,
console_approval_callback,
request_approval,
is_approval_required,
get_risk_level,
add_approval_requirement,
remove_approval_requirement
)
print("✅ Approval module imports successful")
print("Testing main module approval functions...")
from praisonaiagents.main import register_approval_callback, approval_callback
print("✅ Main module approval functions imported successfully")
print("Testing agent modifications...")
from praisonaiagents.agent import Agent
print("✅ Agent class imports successfully")
print("Testing tool decorators...")
from praisonaiagents.tools.shell_tools import ShellTools
from praisonaiagents.tools.python_tools import PythonTools
from praisonaiagents.tools.file_tools import FileTools
print("✅ Tool classes with decorators imported successfully")
return True
except ImportError as e:
print(f"❌ Import error: {e}")
return False
except Exception as e:
print(f"❌ Unexpected error: {e}")
return False
import sys
import os
# Add the src directory to Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
# Import all modules at top level
try:
from praisonaiagents.approval import (
require_approval,
ApprovalDecision,
console_approval_callback,
request_approval,
is_approval_required,
get_risk_level,
add_approval_requirement,
remove_approval_requirement
)
from praisonaiagents.main import register_approval_callback, approval_callback
from praisonaiagents.agent import Agent
from praisonaiagents.tools.shell_tools import ShellTools
from praisonaiagents.tools.python_tools import PythonTools
from praisonaiagents.tools.file_tools import FileTools
IMPORTS_AVAILABLE = True
except ImportError as e:
IMPORTS_AVAILABLE = False
IMPORT_ERROR = e
def test_imports():
"""Test that all the new approval imports work correctly."""
if IMPORTS_AVAILABLE:
print("✅ All approval system imports successful")
return True
else:
print(f"❌ Import error: {IMPORT_ERROR}")
return False
🧰 Tools
🪛 Ruff (0.11.9)

17-17: praisonaiagents.approval.require_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


18-18: praisonaiagents.approval.ApprovalDecision imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


19-19: praisonaiagents.approval.console_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


20-20: praisonaiagents.approval.request_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


21-21: praisonaiagents.approval.is_approval_required imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


22-22: praisonaiagents.approval.get_risk_level imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


23-23: praisonaiagents.approval.add_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


24-24: praisonaiagents.approval.remove_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


29-29: praisonaiagents.main.register_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


29-29: praisonaiagents.main.approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


33-33: praisonaiagents.agent.Agent imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


37-37: praisonaiagents.tools.shell_tools.ShellTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


38-38: praisonaiagents.tools.python_tools.PythonTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


39-39: praisonaiagents.tools.file_tools.FileTools imported but unused; consider using importlib.util.find_spec to test for availability

(F401)

🪛 Pylint (3.3.7)

[convention] 27-27: Trailing whitespace

(C0303)


[convention] 31-31: Trailing whitespace

(C0303)


[convention] 35-35: Trailing whitespace

(C0303)


[convention] 38-38: Trailing whitespace

(C0303)


[convention] 41-41: Trailing whitespace

(C0303)


[convention] 43-43: Trailing whitespace

(C0303)


[warning] 47-47: Catching too general exception Exception

(W0718)


[convention] 16-25: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.ApprovalDecision, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.request_approval, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level, praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement)

(C0415)


[convention] 29-29: Import outside toplevel (praisonaiagents.main.register_approval_callback, praisonaiagents.main.approval_callback)

(C0415)


[convention] 33-33: Import outside toplevel (praisonaiagents.agent.Agent)

(C0415)


[convention] 37-37: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[convention] 38-38: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[convention] 39-39: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[warning] 16-25: Unused require_approval imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused ApprovalDecision imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused console_approval_callback imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused request_approval imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused is_approval_required imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused get_risk_level imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused add_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 16-25: Unused remove_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)


[warning] 29-29: Unused approval_callback imported from praisonaiagents.main

(W0611)


[warning] 33-33: Unused Agent imported from praisonaiagents.agent

(W0611)


[warning] 37-37: Unused ShellTools imported from praisonaiagents.tools.shell_tools

(W0611)


[warning] 38-38: Unused PythonTools imported from praisonaiagents.tools.python_tools

(W0611)


[warning] 39-39: Unused FileTools imported from praisonaiagents.tools.file_tools

(W0611)

🤖 Prompt for AI Agents
In test_approval_basic.py around lines 12 to 50, the import testing function
uses print statements and broad exception handling which is not ideal for test
clarity and style. Refactor the test to use assert statements instead of prints,
remove the broad Exception catch, and only catch ImportError to fail the test if
imports fail. This will make the test cleaner, more idiomatic, and easier to
maintain.

Comment on lines +8 to +16
import logging
import asyncio
from typing import Dict, Set, Optional, Callable, Any, Literal
from functools import wraps
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich.prompt import Confirm

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused import.

Apply this diff to remove the unused import:

 from rich.console import Console
 from rich.panel import Panel
-from rich.text import Text
 from rich.prompt import Confirm
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import logging
import asyncio
from typing import Dict, Set, Optional, Callable, Any, Literal
from functools import wraps
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich.prompt import Confirm
import logging
import asyncio
from typing import Dict, Set, Optional, Callable, Any, Literal
from functools import wraps
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Confirm
🧰 Tools
🪛 Ruff (0.11.9)

14-14: rich.text.Text imported but unused

Remove unused import: rich.text.Text

(F401)

🪛 Pylint (3.3.7)

[warning] 14-14: Unused Text imported from rich.text

(W0611)

🤖 Prompt for AI Agents
In src/praisonai-agents/praisonaiagents/approval.py between lines 8 and 16, the
import 'wraps' from functools is not used anywhere in the code. Remove the line
importing 'wraps' to clean up unused imports and improve code clarity.

This commit deletes the outdated test_approval_basic.py file, which contained basic tests for the human approval system. The tests are no longer necessary as the functionality has been integrated into other components.

Files modified:
- Deleted test_approval_basic.py
This commit modifies the import paths in the test files for the approval agent to ensure they correctly reference the local development path. The changes streamline the path structure for better integration with the existing codebase.

Files modified:
- Updated import paths in test_approval_agent_integration.py
- Updated import paths in test_approval_basic.py
- Updated import paths in test_approval_interactive.py
This commit introduces a context-aware auto-approval mechanism for the approval system, allowing non-interactive execution in CI environments. It modifies the test files to include a skip condition for interactive approvals and updates the approval callback logic to support automatic approvals when user input is not required.

Files modified:
- Updated test_approval_agent_integration.py to include auto-approval logic
- Updated test_approval_basic.py to include skip condition for interactive tests
- Updated test_approval_interactive.py to include auto-approval logic
- Enhanced approval.py with context management for approval tracking
- Modified agent.py to prevent double approval in context

This change improves the usability of the approval system in automated workflows while maintaining security.
@MervinPraison MervinPraison merged commit c4d9ae2 into main Jun 2, 2025
7 of 8 checks passed
@MervinPraison MervinPraison deleted the claude/issue-12-20250601_032826 branch June 2, 2025 08:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
src/praisonai-agents/praisonaiagents/approval.py (1)

15-15: Remove unused import.

 from rich.console import Console
 from rich.panel import Panel
-from rich.text import Text
 from rich.prompt import Confirm
🧰 Tools
🪛 Ruff (0.11.9)

15-15: rich.text.Text imported but unused

Remove unused import: rich.text.Text

(F401)

🪛 Pylint (3.3.7)

[warning] 15-15: Unused Text imported from rich.text

(W0611)

🧹 Nitpick comments (16)
src/praisonai/tests/unit/test_decorator_enforcement.py (1)

35-35: Remove unused variable assignment.

The result variable is assigned but never used, which creates unnecessary code.

-            result = shell_tools.execute_command('echo "This should be denied"')
+            shell_tools.execute_command('echo "This should be denied"')
🧰 Tools
🪛 Ruff (0.11.9)

35-35: Local variable result is assigned to but never used

Remove assignment to unused variable result

(F841)

🪛 Pylint (3.3.7)

[warning] 35-35: Unused variable 'result'

(W0612)

src/praisonai/tests/unit/test_approval_basic.py (1)

44-44: Remove unused import.

The TOOL_RISK_LEVELS import is not used in this function.

     from praisonaiagents.approval import (
         add_approval_requirement, 
         remove_approval_requirement, 
         is_approval_required, 
         get_risk_level,
-        APPROVAL_REQUIRED_TOOLS,
-        TOOL_RISK_LEVELS
+        APPROVAL_REQUIRED_TOOLS
     )
🧰 Tools
🪛 Ruff (0.11.9)

44-44: praisonaiagents.approval.TOOL_RISK_LEVELS imported but unused

Remove unused import: praisonaiagents.approval.TOOL_RISK_LEVELS

(F401)

src/praisonai-agents/praisonaiagents/agent/agent.py (1)

1451-1465: Fix trailing whitespace and improve logging in async approval integration

The async approval integration follows the same pattern as the sync version, which is good for consistency.

Apply this diff to fix formatting issues:

-            
+
             # Check if approval is required for this tool
             from ..approval import is_approval_required, request_approval
             if is_approval_required(function_name):
                 decision = await request_approval(function_name, arguments)
                 if not decision.approved:
                     error_msg = f"Tool execution denied: {decision.reason}"
                     logging.warning(error_msg)
                     return {"error": error_msg, "approval_denied": True}
-                
+
                 # Use modified arguments if provided
                 if decision.modified_args:
                     arguments = decision.modified_args
-                    logging.info(f"Using modified arguments: {arguments}")
-            
+                    logging.info("Using modified arguments: %s", arguments)
+

Issues addressed:

  • Removed trailing whitespace (Pylint C0303)
  • Applied lazy logging formatting for consistency (Pylint W1203)
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 1451-1451: Trailing whitespace

(C0303)


[convention] 1460-1460: Trailing whitespace

(C0303)


[convention] 1465-1465: Trailing whitespace

(C0303)


[convention] 1453-1453: Import outside toplevel (approval.is_approval_required, approval.request_approval)

(C0415)


[warning] 1464-1464: Use lazy % formatting in logging functions

(W1203)

src/praisonai/tests/unit/test_approval_agent_integration.py (1)

1-318: Comprehensive test suite with formatting issues to fix

Excellent test coverage for the approval system integration! The test scenarios cover interactive approval, auto-approval, auto-denial, and multiple tool types (shell, Python, file operations). The structure is well-organized with a user-friendly CLI interface.

However, there are several formatting and import issues to clean up:

Issues to fix:

  1. Remove unused asyncio import (line 11)
  2. Extensive trailing whitespace throughout the file
  3. Missing final newline
  4. Unused parameters in callback functions

Apply this diff for key fixes:

 import sys
 import os
-import asyncio
 import pytest
         # Create auto-approval callback
-        def auto_approve_callback(function_name, arguments, risk_level):
+        def auto_approve_callback(function_name, _arguments, risk_level):
             print(f"🤖 Auto-approving {function_name} (risk: {risk_level})")
             return ApprovalDecision(approved=True, reason="Auto-approved for testing")
         # Create auto-denial callback
-        def auto_deny_callback(function_name, arguments, risk_level):
+        def auto_deny_callback(function_name, _arguments, risk_level):
             print(f"🚫 Auto-denying {function_name} (risk: {risk_level})")
             return ApprovalDecision(approved=False, reason="Auto-denied for testing")
         # Create auto-approval for this test
-        def auto_approve_callback(function_name, arguments, risk_level):
+        def auto_approve_callback(function_name, _arguments, risk_level):
             print(f"🤖 Auto-approving {function_name} (risk: {risk_level})")
             return ApprovalDecision(approved=True, reason="Auto-approved for testing")
         # Create auto-approval for this test
-        def auto_approve_callback(function_name, arguments, risk_level):
+        def auto_approve_callback(function_name, _arguments, risk_level):
             print(f"🤖 Auto-approving {function_name} (risk: {risk_level})")
             return ApprovalDecision(approved=True, reason="Auto-approved for testing")

Additional cleanup needed:

  • Remove trailing whitespace from all lines (too many to list individually)
  • Add final newline at end of file

Note: The import errors flagged by Pylint are expected in test files and can be ignored since they're testing the actual modules that exist in the codebase.

🧰 Tools
🪛 Ruff (0.11.9)

11-11: asyncio imported but unused

Remove unused import: asyncio

(F401)

🪛 Pylint (3.3.7)

[convention] 23-23: Trailing whitespace

(C0303)


[convention] 27-27: Line too long (111/100)

(C0301)


[convention] 28-28: Trailing whitespace

(C0303)


[convention] 37-37: Trailing whitespace

(C0303)


[convention] 46-46: Trailing whitespace

(C0303)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 51-51: Line too long (112/100)

(C0301)


[convention] 52-52: Trailing whitespace

(C0303)


[convention] 59-59: Trailing whitespace

(C0303)


[convention] 61-61: Trailing whitespace

(C0303)


[convention] 70-70: Trailing whitespace

(C0303)


[convention] 75-75: Trailing whitespace

(C0303)


[convention] 80-80: Trailing whitespace

(C0303)


[convention] 82-82: Trailing whitespace

(C0303)


[convention] 91-91: Trailing whitespace

(C0303)


[convention] 93-93: Line too long (109/100)

(C0301)


[convention] 94-94: Trailing whitespace

(C0303)


[convention] 99-99: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[convention] 115-115: Trailing whitespace

(C0303)


[convention] 120-120: Trailing whitespace

(C0303)


[convention] 122-122: Trailing whitespace

(C0303)


[convention] 131-131: Trailing whitespace

(C0303)


[convention] 134-134: Trailing whitespace

(C0303)


[convention] 141-141: Trailing whitespace

(C0303)


[convention] 143-143: Trailing whitespace

(C0303)


[convention] 152-152: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 162-162: Trailing whitespace

(C0303)


[convention] 164-164: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[convention] 182-182: Trailing whitespace

(C0303)


[convention] 187-187: Trailing whitespace

(C0303)


[convention] 189-189: Trailing whitespace

(C0303)


[convention] 198-198: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 208-208: Trailing whitespace

(C0303)


[convention] 210-210: Trailing whitespace

(C0303)


[convention] 219-219: Trailing whitespace

(C0303)


[convention] 226-226: Trailing whitespace

(C0303)


[convention] 229-229: Trailing whitespace

(C0303)


[convention] 233-233: Trailing whitespace

(C0303)


[convention] 240-240: Trailing whitespace

(C0303)


[convention] 242-242: Trailing whitespace

(C0303)


[convention] 253-253: Trailing whitespace

(C0303)


[convention] 263-263: Trailing whitespace

(C0303)


[convention] 266-266: Trailing whitespace

(C0303)


[convention] 279-279: Trailing whitespace

(C0303)


[convention] 288-288: Trailing whitespace

(C0303)


[convention] 295-295: Trailing whitespace

(C0303)


[convention] 303-303: Trailing whitespace

(C0303)


[convention] 311-311: Trailing whitespace

(C0303)


[convention] 318-318: Final newline missing

(C0304)


[warning] 62-62: Catching too general exception Exception

(W0718)


[error] 25-25: Unable to import 'praisonaiagents'

(E0401)


[convention] 25-25: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 26-26: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 26-26: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 27-27: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 27-27: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 34-34: Unused argument 'function_name'

(W0613)


[warning] 34-34: Unused argument 'arguments'

(W0613)


[warning] 34-34: Unused argument 'risk_level'

(W0613)


[warning] 102-102: Catching too general exception Exception

(W0718)


[error] 72-72: Unable to import 'praisonaiagents'

(E0401)


[convention] 72-72: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 73-73: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 73-73: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 74-74: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 74-74: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 77-77: Unused argument 'arguments'

(W0613)


[warning] 144-144: Catching too general exception Exception

(W0718)


[error] 112-112: Unable to import 'praisonaiagents'

(E0401)


[convention] 112-112: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 113-113: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 113-113: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 114-114: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 114-114: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 117-117: Unused argument 'arguments'

(W0613)


[warning] 190-190: Catching too general exception Exception

(W0718)


[error] 154-154: Unable to import 'praisonaiagents'

(E0401)


[convention] 154-154: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 155-155: Unable to import 'praisonaiagents.tools.python_tools'

(E0401)


[convention] 155-155: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[error] 156-156: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 156-156: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 159-159: Unused argument 'arguments'

(W0613)


[warning] 243-243: Catching too general exception Exception

(W0718)


[error] 200-200: Unable to import 'praisonaiagents'

(E0401)


[convention] 200-200: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 201-201: Unable to import 'praisonaiagents.tools.file_tools'

(E0401)


[convention] 201-201: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[error] 202-202: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 202-202: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 205-205: Unused argument 'arguments'

(W0613)


[warning] 314-314: Catching too general exception Exception

(W0718)


[refactor] 247-247: Too many statements (57/50)

(R0915)


[warning] 11-11: Unused import asyncio

(W0611)

examples/python/general/human_approval_example.py (8)

45-45: Remove unnecessary f-string prefix.

The string doesn't contain any placeholders.

-    print(f"\n🔒 CUSTOM APPROVAL REQUIRED")
+    print("\n🔒 CUSTOM APPROVAL REQUIRED")
🧰 Tools
🪛 Ruff (0.11.9)

45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


126-126: Remove unnecessary f-string prefix.

The string doesn't contain any placeholders.

-        print(f"\n✅ Process completed successfully!")
+        print("\n✅ Process completed successfully!")
🧰 Tools
🪛 Ruff (0.11.9)

126-126: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[warning] 126-126: Using an f-string that does not have any interpolated variables

(W1309)


1-210: Clean up trailing whitespace throughout the file.

Static analysis detected trailing whitespace on multiple lines. Consider configuring your editor to automatically remove trailing whitespace on save.

🧰 Tools
🪛 Ruff (0.11.9)

29-29: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)


45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)


126-126: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[convention] 25-25: Line too long (101/100)

(C0301)


[convention] 31-31: Trailing whitespace

(C0303)


[convention] 40-40: Line too long (103/100)

(C0301)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 54-54: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 68-68: Trailing whitespace

(C0303)


[convention] 74-74: Trailing whitespace

(C0303)


[convention] 79-79: Trailing whitespace

(C0303)


[convention] 88-88: Trailing whitespace

(C0303)


[convention] 112-112: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 123-123: Trailing whitespace

(C0303)


[convention] 135-135: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 142-142: Trailing whitespace

(C0303)


[convention] 146-146: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 161-161: Trailing whitespace

(C0303)


[convention] 166-166: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[convention] 188-188: Trailing whitespace

(C0303)


[convention] 191-191: Trailing whitespace

(C0303)


[convention] 194-194: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 210-210: Final newline missing

(C0304)


[error] 27-27: Unable to import 'praisonaiagents'

(E0401)


[convention] 27-27: Import "from praisonaiagents import Agent, Task, PraisonAIAgents" should be placed at the top of the module

(C0413)


[error] 28-28: Unable to import 'praisonaiagents.tools'

(E0401)


[convention] 28-28: Import "from praisonaiagents.tools import python_tools, file_tools, shell_tools" should be placed at the top of the module

(C0413)


[error] 29-29: Unable to import 'praisonaiagents.main'

(E0401)


[convention] 29-29: Import "from praisonaiagents.main import register_approval_callback" should be placed at the top of the module

(C0413)


[error] 30-35: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 30-35: Import "from praisonaiagents.approval import console_approval_callback, ApprovalDecision, add_approval_requirement, remove_approval_requirement" should be placed at the top of the module

(C0413)


[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 130-130: Catching too general exception Exception

(W0718)


[warning] 126-126: Using an f-string that does not have any interpolated variables

(W1309)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 183-183: Catching too general exception Exception

(W0718)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)


24-35: Fix import organization and remove unused import.

The imports have several issues that should be addressed:

  1. The register_approval_callback import is unused (as flagged by static analysis)
  2. Imports should be placed after the path modification for consistency
-from praisonaiagents.main import register_approval_callback
 from praisonaiagents.approval import (
-    console_approval_callback, 
+    console_approval_callback,
     ApprovalDecision,
     add_approval_requirement,
     remove_approval_requirement
 )

Also consider moving all praisonaiagents imports after the sys.path.append line for clarity.

🧰 Tools
🪛 Ruff (0.11.9)

29-29: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)

🪛 Pylint (3.3.7)

[convention] 25-25: Line too long (101/100)

(C0301)


[convention] 31-31: Trailing whitespace

(C0303)


[error] 27-27: Unable to import 'praisonaiagents'

(E0401)


[convention] 27-27: Import "from praisonaiagents import Agent, Task, PraisonAIAgents" should be placed at the top of the module

(C0413)


[error] 28-28: Unable to import 'praisonaiagents.tools'

(E0401)


[convention] 28-28: Import "from praisonaiagents.tools import python_tools, file_tools, shell_tools" should be placed at the top of the module

(C0413)


[error] 29-29: Unable to import 'praisonaiagents.main'

(E0401)


[convention] 29-29: Import "from praisonaiagents.main import register_approval_callback" should be placed at the top of the module

(C0413)


[error] 30-35: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 30-35: Import "from praisonaiagents.approval import console_approval_callback, ApprovalDecision, add_approval_requirement, remove_approval_requirement" should be placed at the top of the module

(C0413)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)


45-45: Remove unnecessary f-string prefixes.

Two f-strings don't contain any placeholders and should use regular strings for better performance and clarity.

-    print(f"\n🔒 CUSTOM APPROVAL REQUIRED")
+    print("\n🔒 CUSTOM APPROVAL REQUIRED")
-        print(f"\n✅ Process completed successfully!")
+        print("\n✅ Process completed successfully!")

Also applies to: 126-126

🧰 Tools
🪛 Ruff (0.11.9)

45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


76-78: Consider demonstrating the custom approval callback.

The custom approval callback is defined but commented out. Consider either:

  1. Uncommenting it to show its usage in the demo, or
  2. Adding a separate demo section that specifically showcases custom callbacks

This would make the example more comprehensive by actually demonstrating the custom approval logic in action.


148-148: Consider moving imports to module level.

The import inside the function should be moved to the top of the file for better organization and to avoid import-time side effects.

+from praisonaiagents.approval import APPROVAL_REQUIRED_TOOLS, TOOL_RISK_LEVELS

 def demo_manual_approval_configuration():
     """Demonstrate how to manually configure approval requirements."""
     
     # ... existing code ...
     
-    # Show current approval requirements
-    from praisonaiagents.approval import APPROVAL_REQUIRED_TOOLS, TOOL_RISK_LEVELS
     print(f"\nCurrent approval-required tools: {list(APPROVAL_REQUIRED_TOOLS)}")
🧰 Tools
🪛 Pylint (3.3.7)

[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


1-210: Address formatting issues flagged by static analysis.

The file has several formatting issues that should be cleaned up:

  1. Multiple trailing whitespace occurrences
  2. Missing final newline
  3. Some lines exceed 100 characters

Consider running a formatter like black or manually cleaning up the trailing whitespace and adding a final newline to improve code quality.

🧰 Tools
🪛 Ruff (0.11.9)

29-29: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)


45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)


126-126: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[convention] 25-25: Line too long (101/100)

(C0301)


[convention] 31-31: Trailing whitespace

(C0303)


[convention] 40-40: Line too long (103/100)

(C0301)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 54-54: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 68-68: Trailing whitespace

(C0303)


[convention] 74-74: Trailing whitespace

(C0303)


[convention] 79-79: Trailing whitespace

(C0303)


[convention] 88-88: Trailing whitespace

(C0303)


[convention] 112-112: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 123-123: Trailing whitespace

(C0303)


[convention] 135-135: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 142-142: Trailing whitespace

(C0303)


[convention] 146-146: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 161-161: Trailing whitespace

(C0303)


[convention] 166-166: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[convention] 188-188: Trailing whitespace

(C0303)


[convention] 191-191: Trailing whitespace

(C0303)


[convention] 194-194: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 210-210: Final newline missing

(C0304)


[error] 27-27: Unable to import 'praisonaiagents'

(E0401)


[convention] 27-27: Import "from praisonaiagents import Agent, Task, PraisonAIAgents" should be placed at the top of the module

(C0413)


[error] 28-28: Unable to import 'praisonaiagents.tools'

(E0401)


[convention] 28-28: Import "from praisonaiagents.tools import python_tools, file_tools, shell_tools" should be placed at the top of the module

(C0413)


[error] 29-29: Unable to import 'praisonaiagents.main'

(E0401)


[convention] 29-29: Import "from praisonaiagents.main import register_approval_callback" should be placed at the top of the module

(C0413)


[error] 30-35: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 30-35: Import "from praisonaiagents.approval import console_approval_callback, ApprovalDecision, add_approval_requirement, remove_approval_requirement" should be placed at the top of the module

(C0413)


[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 130-130: Catching too general exception Exception

(W0718)


[warning] 126-126: Using an f-string that does not have any interpolated variables

(W1309)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 183-183: Catching too general exception Exception

(W0718)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)

src/praisonai/tests/unit/test_approval_interactive.py (1)

287-287: Add missing final newline.

Files should end with a newline character.

 if __name__ == "__main__":
-    main() 
+    main()
+
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 287-287: Final newline missing

(C0304)

src/praisonai-agents/praisonaiagents/approval.py (3)

29-29: Avoid mutable default for ContextVar.

While it works in this case, using mutable defaults is generally discouraged. Consider using None as default and creating the set when needed.

-_approved_context: ContextVar[Set[str]] = ContextVar('approved_context', default=set())
+_approved_context: ContextVar[Optional[Set[str]]] = ContextVar('approved_context', default=None)

Then update the helper functions:

def mark_approved(tool_name: str):
    """Mark a tool as approved in the current context."""
    approved = _approved_context.get()
    if approved is None:
        approved = set()
    approved.add(tool_name)
    _approved_context.set(approved)

def is_already_approved(tool_name: str) -> bool:
    """Check if a tool is already approved in the current context."""
    approved = _approved_context.get()
    return approved is not None and tool_name in approved
🧰 Tools
🪛 Ruff (0.11.9)

29-29: Do not use mutable data structures for ContextVar defaults

(B039)


147-147: Remove unnecessary f-string prefix.

The string doesn't contain any placeholders.

-    tool_info += f"[bold]Arguments:[/]\n"
+    tool_info += "[bold]Arguments:[/]\n"
🧰 Tools
🪛 Ruff (0.11.9)

147-147: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[warning] 147-147: Using an f-string that does not have any interpolated variables

(W1309)


263-263: Add missing final newline.

Files should end with a newline character.

 # Initialize with defaults
-configure_default_approvals()
+configure_default_approvals()
+
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 263-263: Final newline missing

(C0304)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca6be70 and f581e52.

📒 Files selected for processing (8)
  • examples/python/general/human_approval_example.py (1 hunks)
  • src/praisonai-agents/praisonaiagents/agent/agent.py (3 hunks)
  • src/praisonai-agents/praisonaiagents/approval.py (1 hunks)
  • src/praisonai/tests/unit/test_approval_agent_integration.py (1 hunks)
  • src/praisonai/tests/unit/test_approval_basic.py (1 hunks)
  • src/praisonai/tests/unit/test_approval_interactive.py (1 hunks)
  • src/praisonai/tests/unit/test_decorator_enforcement.py (1 hunks)
  • src/praisonai/tests/unit/test_decorator_simple.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/praisonai-agents/praisonaiagents/approval.py (3)
src/praisonai-agents/praisonaiagents/agent/agent.py (1)
  • run (1439-1441)
src/praisonai-ts/src/utils/pretty-logger.ts (1)
  • warning (120-136)
src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py (1)
  • get_event_loop (22-28)
src/praisonai-agents/praisonaiagents/agent/agent.py (1)
src/praisonai-agents/praisonaiagents/approval.py (6)
  • is_approval_required (254-256)
  • console_approval_callback (128-182)
  • get_risk_level (258-260)
  • mark_approved (46-50)
  • ApprovalDecision (31-36)
  • request_approval (184-216)
🪛 Ruff (0.11.9)
src/praisonai/tests/unit/test_decorator_enforcement.py

35-35: Local variable result is assigned to but never used

Remove assignment to unused variable result

(F841)

src/praisonai/tests/unit/test_approval_basic.py

19-19: praisonaiagents.approval.require_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


20-20: praisonaiagents.approval.ApprovalDecision imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


21-21: praisonaiagents.approval.console_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


22-22: praisonaiagents.approval.request_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


23-23: praisonaiagents.approval.add_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


24-24: praisonaiagents.approval.remove_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


25-25: praisonaiagents.approval.is_approval_required imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


26-26: praisonaiagents.approval.get_risk_level imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


27-27: praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


28-28: praisonaiagents.approval.TOOL_RISK_LEVELS imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


44-44: praisonaiagents.approval.TOOL_RISK_LEVELS imported but unused

Remove unused import: praisonaiagents.approval.TOOL_RISK_LEVELS

(F401)


100-100: Local variable shell_tools is assigned to but never used

Remove assignment to unused variable shell_tools

(F841)


117-117: Local variable python_tools is assigned to but never used

Remove assignment to unused variable python_tools

(F841)


129-129: Local variable file_tools is assigned to but never used

Remove assignment to unused variable file_tools

(F841)


194-194: Local variable agent is assigned to but never used

Remove assignment to unused variable agent

(F841)

src/praisonai/tests/unit/test_approval_agent_integration.py

11-11: asyncio imported but unused

Remove unused import: asyncio

(F401)

examples/python/general/human_approval_example.py

29-29: praisonaiagents.main.register_approval_callback imported but unused

Remove unused import: praisonaiagents.main.register_approval_callback

(F401)


45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)


126-126: f-string without any placeholders

Remove extraneous f prefix

(F541)

src/praisonai-agents/praisonaiagents/approval.py

15-15: rich.text.Text imported but unused

Remove unused import: rich.text.Text

(F401)


29-29: Do not use mutable data structures for ContextVar defaults

(B039)


147-147: f-string without any placeholders

Remove extraneous f prefix

(F541)

src/praisonai/tests/unit/test_approval_interactive.py

11-11: asyncio imported but unused

Remove unused import: asyncio

(F401)

src/praisonai-agents/praisonaiagents/agent/agent.py

575-575: ..approval.ApprovalDecision imported but unused

Remove unused import: ..approval.ApprovalDecision

(F401)

🪛 Pylint (3.3.7)
src/praisonai/tests/unit/test_decorator_enforcement.py

[convention] 17-17: Trailing whitespace

(C0303)


[convention] 21-21: Trailing whitespace

(C0303)


[convention] 26-26: Trailing whitespace

(C0303)


[convention] 28-28: Trailing whitespace

(C0303)


[convention] 30-30: Trailing whitespace

(C0303)


[convention] 32-32: Trailing whitespace

(C0303)


[convention] 44-44: Trailing whitespace

(C0303)


[convention] 55-55: Final newline missing

(C0304)


[warning] 45-45: Catching too general exception Exception

(W0718)


[error] 19-19: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 19-19: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 20-20: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 20-20: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 23-23: Unused argument 'arguments'

(W0613)


[warning] 41-41: Catching too general exception Exception

(W0718)


[warning] 35-35: Unused variable 'result'

(W0612)


[convention] 50-50: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

src/praisonai/tests/unit/test_approval_basic.py

[convention] 39-39: Trailing whitespace

(C0303)


[convention] 40-40: Trailing whitespace

(C0303)


[convention] 41-41: Trailing whitespace

(C0303)


[convention] 46-46: Trailing whitespace

(C0303)


[convention] 48-48: Trailing whitespace

(C0303)


[convention] 54-54: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 62-62: Line too long (104/100)

(C0301)


[convention] 63-63: Line too long (101/100)

(C0301)


[convention] 65-65: Trailing whitespace

(C0303)


[convention] 72-72: Trailing whitespace

(C0303)


[convention] 74-74: Trailing whitespace

(C0303)


[convention] 80-80: Trailing whitespace

(C0303)


[convention] 82-82: Line too long (104/100)

(C0301)


[convention] 85-85: Trailing whitespace

(C0303)


[convention] 90-90: Trailing whitespace

(C0303)


[convention] 96-96: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 106-106: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[convention] 113-113: Trailing whitespace

(C0303)


[convention] 118-118: Trailing whitespace

(C0303)


[convention] 122-122: Trailing whitespace

(C0303)


[convention] 125-125: Trailing whitespace

(C0303)


[convention] 130-130: Trailing whitespace

(C0303)


[convention] 134-134: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 141-141: Trailing whitespace

(C0303)


[convention] 147-147: Trailing whitespace

(C0303)


[convention] 149-149: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 159-159: Trailing whitespace

(C0303)


[convention] 163-163: Trailing whitespace

(C0303)


[convention] 168-168: Trailing whitespace

(C0303)


[convention] 169-169: Trailing whitespace

(C0303)


[convention] 171-171: Trailing whitespace

(C0303)


[convention] 176-176: Trailing whitespace

(C0303)


[convention] 182-182: Trailing whitespace

(C0303)


[convention] 188-188: Trailing whitespace

(C0303)


[convention] 192-192: Trailing whitespace

(C0303)


[convention] 201-201: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 207-207: Trailing whitespace

(C0303)


[convention] 209-209: Trailing whitespace

(C0303)


[convention] 218-218: Trailing whitespace

(C0303)


[convention] 220-220: Trailing whitespace

(C0303)


[convention] 227-227: Trailing whitespace

(C0303)


[convention] 235-235: Trailing whitespace

(C0303)


[convention] 240-240: Trailing whitespace

(C0303)


[convention] 243-243: Trailing whitespace

(C0303)


[convention] 251-251: Trailing whitespace

(C0303)


[convention] 255-255: Trailing whitespace

(C0303)


[convention] 265-265: Final newline missing

(C0304)


[convention] 18-29: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.ApprovalDecision, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.request_approval, praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level, praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 18-29: Unused require_approval imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused ApprovalDecision imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused console_approval_callback imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused request_approval imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused add_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused remove_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused is_approval_required imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused get_risk_level imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused APPROVAL_REQUIRED_TOOLS imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused TOOL_RISK_LEVELS imported from praisonaiagents.approval

(W0611)


[error] 38-45: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 38-45: Import outside toplevel (praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level, praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 38-45: Unused TOOL_RISK_LEVELS imported from praisonaiagents.approval

(W0611)


[error] 71-71: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 71-71: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level)

(C0415)


[warning] 111-111: Catching too general exception Exception

(W0718)


[error] 99-99: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 99-99: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 103-103: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 103-103: Import outside toplevel (praisonaiagents.approval.is_approval_required)

(C0415)


[warning] 123-123: Catching too general exception Exception

(W0718)


[error] 116-116: Unable to import 'praisonaiagents.tools.python_tools'

(E0401)


[convention] 116-116: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[warning] 139-139: Catching too general exception Exception

(W0718)


[error] 128-128: Unable to import 'praisonaiagents.tools.file_tools'

(E0401)


[convention] 128-128: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[warning] 100-100: Unused variable 'shell_tools'

(W0612)


[warning] 117-117: Unused variable 'python_tools'

(W0612)


[warning] 129-129: Unused variable 'file_tools'

(W0612)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.request_approval, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 151-151: Unused argument 'arguments'

(W0613)


[warning] 156-156: Unused argument 'arguments'

(W0613)


[error] 161-161: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 161-161: Import outside toplevel (praisonaiagents.approval.set_approval_callback)

(C0415)


[warning] 210-210: Catching too general exception Exception

(W0718)


[error] 190-190: Unable to import 'praisonaiagents'

(E0401)


[convention] 190-190: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 191-191: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 191-191: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 205-205: Unable to import 'praisonaiagents.main'

(E0401)


[convention] 205-205: Import outside toplevel (praisonaiagents.main.approval_callback)

(C0415)


[warning] 194-194: Unused variable 'agent'

(W0612)


[warning] 232-232: Catching too general exception Exception

(W0718)


[refactor] 256-261: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[convention] 264-264: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

src/praisonai/tests/unit/test_approval_agent_integration.py

[convention] 23-23: Trailing whitespace

(C0303)


[convention] 27-27: Line too long (111/100)

(C0301)


[convention] 28-28: Trailing whitespace

(C0303)


[convention] 37-37: Trailing whitespace

(C0303)


[convention] 46-46: Trailing whitespace

(C0303)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 51-51: Line too long (112/100)

(C0301)


[convention] 52-52: Trailing whitespace

(C0303)


[convention] 59-59: Trailing whitespace

(C0303)


[convention] 61-61: Trailing whitespace

(C0303)


[convention] 70-70: Trailing whitespace

(C0303)


[convention] 75-75: Trailing whitespace

(C0303)


[convention] 80-80: Trailing whitespace

(C0303)


[convention] 82-82: Trailing whitespace

(C0303)


[convention] 91-91: Trailing whitespace

(C0303)


[convention] 93-93: Line too long (109/100)

(C0301)


[convention] 94-94: Trailing whitespace

(C0303)


[convention] 99-99: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 110-110: Trailing whitespace

(C0303)


[convention] 115-115: Trailing whitespace

(C0303)


[convention] 120-120: Trailing whitespace

(C0303)


[convention] 122-122: Trailing whitespace

(C0303)


[convention] 131-131: Trailing whitespace

(C0303)


[convention] 134-134: Trailing whitespace

(C0303)


[convention] 141-141: Trailing whitespace

(C0303)


[convention] 143-143: Trailing whitespace

(C0303)


[convention] 152-152: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 162-162: Trailing whitespace

(C0303)


[convention] 164-164: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[convention] 182-182: Trailing whitespace

(C0303)


[convention] 187-187: Trailing whitespace

(C0303)


[convention] 189-189: Trailing whitespace

(C0303)


[convention] 198-198: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 208-208: Trailing whitespace

(C0303)


[convention] 210-210: Trailing whitespace

(C0303)


[convention] 219-219: Trailing whitespace

(C0303)


[convention] 226-226: Trailing whitespace

(C0303)


[convention] 229-229: Trailing whitespace

(C0303)


[convention] 233-233: Trailing whitespace

(C0303)


[convention] 240-240: Trailing whitespace

(C0303)


[convention] 242-242: Trailing whitespace

(C0303)


[convention] 253-253: Trailing whitespace

(C0303)


[convention] 263-263: Trailing whitespace

(C0303)


[convention] 266-266: Trailing whitespace

(C0303)


[convention] 279-279: Trailing whitespace

(C0303)


[convention] 288-288: Trailing whitespace

(C0303)


[convention] 295-295: Trailing whitespace

(C0303)


[convention] 303-303: Trailing whitespace

(C0303)


[convention] 311-311: Trailing whitespace

(C0303)


[convention] 318-318: Final newline missing

(C0304)


[warning] 62-62: Catching too general exception Exception

(W0718)


[error] 25-25: Unable to import 'praisonaiagents'

(E0401)


[convention] 25-25: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 26-26: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 26-26: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 27-27: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 27-27: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 34-34: Unused argument 'function_name'

(W0613)


[warning] 34-34: Unused argument 'arguments'

(W0613)


[warning] 34-34: Unused argument 'risk_level'

(W0613)


[warning] 102-102: Catching too general exception Exception

(W0718)


[error] 72-72: Unable to import 'praisonaiagents'

(E0401)


[convention] 72-72: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 73-73: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 73-73: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 74-74: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 74-74: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 77-77: Unused argument 'arguments'

(W0613)


[warning] 144-144: Catching too general exception Exception

(W0718)


[error] 112-112: Unable to import 'praisonaiagents'

(E0401)


[convention] 112-112: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 113-113: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 113-113: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 114-114: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 114-114: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 117-117: Unused argument 'arguments'

(W0613)


[warning] 190-190: Catching too general exception Exception

(W0718)


[error] 154-154: Unable to import 'praisonaiagents'

(E0401)


[convention] 154-154: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 155-155: Unable to import 'praisonaiagents.tools.python_tools'

(E0401)


[convention] 155-155: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[error] 156-156: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 156-156: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 159-159: Unused argument 'arguments'

(W0613)


[warning] 243-243: Catching too general exception Exception

(W0718)


[error] 200-200: Unable to import 'praisonaiagents'

(E0401)


[convention] 200-200: Import outside toplevel (praisonaiagents.Agent)

(C0415)


[error] 201-201: Unable to import 'praisonaiagents.tools.file_tools'

(E0401)


[convention] 201-201: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[error] 202-202: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 202-202: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 205-205: Unused argument 'arguments'

(W0613)


[warning] 314-314: Catching too general exception Exception

(W0718)


[refactor] 247-247: Too many statements (57/50)

(R0915)


[warning] 11-11: Unused import asyncio

(W0611)

src/praisonai/tests/unit/test_decorator_simple.py

[convention] 16-16: Trailing whitespace

(C0303)


[convention] 22-22: Trailing whitespace

(C0303)


[convention] 25-25: Trailing whitespace

(C0303)


[convention] 30-30: Trailing whitespace

(C0303)


[convention] 32-32: Trailing whitespace

(C0303)


[convention] 35-35: Trailing whitespace

(C0303)


[convention] 38-38: Trailing whitespace

(C0303)


[convention] 40-40: Trailing whitespace

(C0303)


[convention] 46-46: Trailing whitespace

(C0303)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 51-51: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 65-65: Trailing whitespace

(C0303)


[convention] 67-67: Trailing whitespace

(C0303)


[convention] 73-73: Trailing whitespace

(C0303)


[convention] 76-76: Trailing whitespace

(C0303)


[convention] 81-81: Trailing whitespace

(C0303)


[convention] 83-83: Trailing whitespace

(C0303)


[convention] 101-101: Trailing whitespace

(C0303)


[convention] 102-102: Final newline missing

(C0304)


[warning] 84-84: Catching too general exception Exception

(W0718)


[convention] 18-21: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision, praisonaiagents.approval.mark_approved, praisonaiagents.approval.is_already_approved, praisonaiagents.approval.clear_approval_context)

(C0415)


[warning] 36-36: Unused argument 'function_name'

(W0613)


[warning] 36-36: Unused argument 'arguments'

(W0613)


[warning] 36-36: Unused argument 'risk_level'

(W0613)


[warning] 55-55: Catching too general exception Exception

(W0718)


[warning] 63-63: Unused argument 'function_name'

(W0613)


[warning] 63-63: Unused argument 'arguments'

(W0613)


[warning] 63-63: Unused argument 'risk_level'

(W0613)


[warning] 71-71: Catching too general exception Exception

(W0718)


[convention] 86-86: Import outside toplevel (traceback)

(C0415)


[convention] 91-91: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

examples/python/general/human_approval_example.py

[convention] 25-25: Line too long (101/100)

(C0301)


[convention] 31-31: Trailing whitespace

(C0303)


[convention] 40-40: Line too long (103/100)

(C0301)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 54-54: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 68-68: Trailing whitespace

(C0303)


[convention] 74-74: Trailing whitespace

(C0303)


[convention] 79-79: Trailing whitespace

(C0303)


[convention] 88-88: Trailing whitespace

(C0303)


[convention] 112-112: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 123-123: Trailing whitespace

(C0303)


[convention] 135-135: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 142-142: Trailing whitespace

(C0303)


[convention] 146-146: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 161-161: Trailing whitespace

(C0303)


[convention] 166-166: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[convention] 188-188: Trailing whitespace

(C0303)


[convention] 191-191: Trailing whitespace

(C0303)


[convention] 194-194: Trailing whitespace

(C0303)


[convention] 203-203: Trailing whitespace

(C0303)


[convention] 210-210: Final newline missing

(C0304)


[error] 27-27: Unable to import 'praisonaiagents'

(E0401)


[convention] 27-27: Import "from praisonaiagents import Agent, Task, PraisonAIAgents" should be placed at the top of the module

(C0413)


[error] 28-28: Unable to import 'praisonaiagents.tools'

(E0401)


[convention] 28-28: Import "from praisonaiagents.tools import python_tools, file_tools, shell_tools" should be placed at the top of the module

(C0413)


[error] 29-29: Unable to import 'praisonaiagents.main'

(E0401)


[convention] 29-29: Import "from praisonaiagents.main import register_approval_callback" should be placed at the top of the module

(C0413)


[error] 30-35: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 30-35: Import "from praisonaiagents.approval import console_approval_callback, ApprovalDecision, add_approval_requirement, remove_approval_requirement" should be placed at the top of the module

(C0413)


[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 130-130: Catching too general exception Exception

(W0718)


[warning] 126-126: Using an f-string that does not have any interpolated variables

(W1309)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 183-183: Catching too general exception Exception

(W0718)


[warning] 29-29: Unused register_approval_callback imported from praisonaiagents.main

(W0611)

src/praisonai-agents/praisonaiagents/approval.py

[convention] 33-33: Line too long (105/100)

(C0301)


[convention] 71-71: Trailing whitespace

(C0303)


[convention] 77-77: Trailing whitespace

(C0303)


[convention] 95-95: Trailing whitespace

(C0303)


[convention] 98-98: Trailing whitespace

(C0303)


[convention] 103-103: Trailing whitespace

(C0303)


[convention] 109-109: Trailing whitespace

(C0303)


[convention] 114-114: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 125-125: Trailing whitespace

(C0303)


[convention] 128-128: Line too long (114/100)

(C0301)


[convention] 134-134: Trailing whitespace

(C0303)


[convention] 143-143: Trailing whitespace

(C0303)


[convention] 148-148: Trailing whitespace

(C0303)


[convention] 155-155: Trailing whitespace

(C0303)


[convention] 162-162: Trailing whitespace

(C0303)


[convention] 169-169: Trailing whitespace

(C0303)


[convention] 176-176: Trailing whitespace

(C0303)


[convention] 197-197: Trailing whitespace

(C0303)


[convention] 199-199: Trailing whitespace

(C0303)


[convention] 202-202: Trailing whitespace

(C0303)


[convention] 210-210: Line too long (103/100)

(C0301)


[convention] 211-211: Trailing whitespace

(C0303)


[convention] 213-213: Trailing whitespace

(C0303)


[convention] 224-224: Trailing whitespace

(C0303)


[convention] 231-231: Trailing whitespace

(C0303)


[convention] 263-263: Final newline missing

(C0304)


[refactor] 31-31: Too few public methods (0/2)

(R0903)


[warning] 43-43: Using the global statement

(W0603)


[warning] 90-90: Catching too general exception Exception

(W0718)


[warning] 92-92: Use lazy % formatting in logging functions

(W1203)


[error] 96-96: Using variable 'decision' before assignment

(E0601)


[refactor] 121-124: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 147-147: Using an f-string that does not have any interpolated variables

(W1309)


[warning] 180-180: Catching too general exception Exception

(W0718)


[refactor] 170-175: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)


[warning] 214-214: Catching too general exception Exception

(W0718)


[warning] 215-215: Use lazy % formatting in logging functions

(W1203)


[warning] 15-15: Unused Text imported from rich.text

(W0611)

src/praisonai/tests/unit/test_approval_interactive.py

[convention] 22-22: Trailing whitespace

(C0303)


[convention] 25-25: Line too long (111/100)

(C0301)


[convention] 26-26: Trailing whitespace

(C0303)


[convention] 35-35: Trailing whitespace

(C0303)


[convention] 37-37: Trailing whitespace

(C0303)


[convention] 40-40: Trailing whitespace

(C0303)


[convention] 43-43: Trailing whitespace

(C0303)


[convention] 48-48: Trailing whitespace

(C0303)


[convention] 50-50: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 63-63: Line too long (111/100)

(C0301)


[convention] 64-64: Trailing whitespace

(C0303)


[convention] 73-73: Trailing whitespace

(C0303)


[convention] 75-75: Trailing whitespace

(C0303)


[convention] 78-78: Trailing whitespace

(C0303)


[convention] 85-85: Trailing whitespace

(C0303)


[convention] 87-87: Trailing whitespace

(C0303)


[convention] 92-92: Trailing whitespace

(C0303)


[convention] 94-94: Trailing whitespace

(C0303)


[convention] 104-104: Trailing whitespace

(C0303)


[convention] 107-107: Line too long (111/100)

(C0301)


[convention] 108-108: Trailing whitespace

(C0303)


[convention] 117-117: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 122-122: Trailing whitespace

(C0303)


[convention] 128-128: Trailing whitespace

(C0303)


[convention] 131-131: Trailing whitespace

(C0303)


[convention] 135-135: Trailing whitespace

(C0303)


[convention] 139-139: Line too long (109/100)

(C0301)


[convention] 142-142: Trailing whitespace

(C0303)


[convention] 144-144: Trailing whitespace

(C0303)


[convention] 153-153: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 162-162: Trailing whitespace

(C0303)


[convention] 164-164: Trailing whitespace

(C0303)


[convention] 166-166: Trailing whitespace

(C0303)


[convention] 169-169: Trailing whitespace

(C0303)


[convention] 174-174: Trailing whitespace

(C0303)


[convention] 176-176: Trailing whitespace

(C0303)


[convention] 185-185: Trailing whitespace

(C0303)


[convention] 189-189: Trailing whitespace

(C0303)


[convention] 194-194: Trailing whitespace

(C0303)


[convention] 196-196: Trailing whitespace

(C0303)


[convention] 198-198: Trailing whitespace

(C0303)


[convention] 201-201: Trailing whitespace

(C0303)


[convention] 208-208: Trailing whitespace

(C0303)


[convention] 210-210: Trailing whitespace

(C0303)


[convention] 222-222: Trailing whitespace

(C0303)


[convention] 232-232: Trailing whitespace

(C0303)


[convention] 235-235: Trailing whitespace

(C0303)


[convention] 248-248: Trailing whitespace

(C0303)


[convention] 255-255: Trailing whitespace

(C0303)


[convention] 262-262: Trailing whitespace

(C0303)


[convention] 272-272: Trailing whitespace

(C0303)


[convention] 280-280: Trailing whitespace

(C0303)


[convention] 287-287: Final newline missing

(C0304)


[warning] 51-51: Catching too general exception Exception

(W0718)


[error] 24-24: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 24-24: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 25-25: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 25-25: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 32-32: Unused argument 'function_name'

(W0613)


[warning] 32-32: Unused argument 'arguments'

(W0613)


[warning] 32-32: Unused argument 'risk_level'

(W0613)


[warning] 95-95: Catching too general exception Exception

(W0718)


[error] 62-62: Unable to import 'praisonaiagents.tools.python_tools'

(E0401)


[convention] 62-62: Import outside toplevel (praisonaiagents.tools.python_tools.PythonTools)

(C0415)


[error] 63-63: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 63-63: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 70-70: Unused argument 'function_name'

(W0613)


[warning] 70-70: Unused argument 'arguments'

(W0613)


[warning] 70-70: Unused argument 'risk_level'

(W0613)


[warning] 145-145: Catching too general exception Exception

(W0718)


[error] 106-106: Unable to import 'praisonaiagents.tools.file_tools'

(E0401)


[convention] 106-106: Import outside toplevel (praisonaiagents.tools.file_tools.FileTools)

(C0415)


[error] 107-107: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 107-107: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 114-114: Unused argument 'function_name'

(W0613)


[warning] 114-114: Unused argument 'arguments'

(W0613)


[warning] 114-114: Unused argument 'risk_level'

(W0613)


[warning] 177-177: Catching too general exception Exception

(W0718)


[error] 155-155: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 155-155: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 156-156: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 156-156: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 159-159: Unused argument 'arguments'

(W0613)


[warning] 211-211: Catching too general exception Exception

(W0718)


[error] 187-187: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 187-187: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 188-188: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 188-188: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 191-191: Unused argument 'arguments'

(W0613)


[warning] 283-283: Catching too general exception Exception

(W0718)


[refactor] 215-215: Too many statements (58/50)

(R0915)


[warning] 11-11: Unused import asyncio

(W0611)

src/praisonai-agents/praisonaiagents/agent/agent.py

[convention] 575-575: Line too long (127/100)

(C0301)


[convention] 579-579: Trailing whitespace

(C0303)


[convention] 582-582: Trailing whitespace

(C0303)


[convention] 589-589: Trailing whitespace

(C0303)


[convention] 592-592: Trailing whitespace

(C0303)


[convention] 597-597: Trailing whitespace

(C0303)


[convention] 575-575: Import outside toplevel (approval.is_approval_required, approval.console_approval_callback, approval.get_risk_level, approval.mark_approved, approval.ApprovalDecision)

(C0415)


[warning] 578-578: Use lazy % formatting in logging functions

(W1203)


[warning] 598-598: Catching too general exception Exception

(W0718)


[warning] 596-596: Use lazy % formatting in logging functions

(W1203)


[warning] 575-575: Unused ApprovalDecision imported from approval

(W0611)


[convention] 1451-1451: Trailing whitespace

(C0303)


[convention] 1460-1460: Trailing whitespace

(C0303)


[convention] 1465-1465: Trailing whitespace

(C0303)


[convention] 1453-1453: Import outside toplevel (approval.is_approval_required, approval.request_approval)

(C0415)


[warning] 1464-1464: Use lazy % formatting in logging functions

(W1203)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: quick-test
  • GitHub Check: test-core (3.11)
  • GitHub Check: quick-test
🔇 Additional comments (13)
src/praisonai/tests/unit/test_decorator_enforcement.py (1)

13-47: Test logic is well-structured and comprehensive.

The test correctly:

  • Sets up an auto-denial callback to ensure enforcement
  • Attempts direct tool execution outside agent context
  • Expects and catches the appropriate PermissionError
  • Provides clear success/failure feedback

This effectively validates that the decorator enforcement works at the tool level.

🧰 Tools
🪛 Ruff (0.11.9)

35-35: Local variable result is assigned to but never used

Remove assignment to unused variable result

(F841)

🪛 Pylint (3.3.7)

[convention] 17-17: Trailing whitespace

(C0303)


[convention] 21-21: Trailing whitespace

(C0303)


[convention] 26-26: Trailing whitespace

(C0303)


[convention] 28-28: Trailing whitespace

(C0303)


[convention] 30-30: Trailing whitespace

(C0303)


[convention] 32-32: Trailing whitespace

(C0303)


[convention] 44-44: Trailing whitespace

(C0303)


[warning] 45-45: Catching too general exception Exception

(W0718)


[error] 19-19: Unable to import 'praisonaiagents.tools.shell_tools'

(E0401)


[convention] 19-19: Import outside toplevel (praisonaiagents.tools.shell_tools.ShellTools)

(C0415)


[error] 20-20: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 20-20: Import outside toplevel (praisonaiagents.approval.set_approval_callback, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 23-23: Unused argument 'arguments'

(W0613)


[warning] 41-41: Catching too general exception Exception

(W0718)


[warning] 35-35: Unused variable 'result'

(W0612)

src/praisonai/tests/unit/test_approval_basic.py (3)

15-34: Excellent test structure for import validation.

The test_imports() function effectively verifies that all critical approval system components can be imported successfully. The imports within the function are intentional for testing import capabilities, not for actual usage.

🧰 Tools
🪛 Ruff (0.11.9)

19-19: praisonaiagents.approval.require_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


20-20: praisonaiagents.approval.ApprovalDecision imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


21-21: praisonaiagents.approval.console_approval_callback imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


22-22: praisonaiagents.approval.request_approval imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


23-23: praisonaiagents.approval.add_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


24-24: praisonaiagents.approval.remove_approval_requirement imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


25-25: praisonaiagents.approval.is_approval_required imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


26-26: praisonaiagents.approval.get_risk_level imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


27-27: praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS imported but unused; consider using importlib.util.find_spec to test for availability

(F401)


28-28: praisonaiagents.approval.TOOL_RISK_LEVELS imported but unused; consider using importlib.util.find_spec to test for availability

(F401)

🪛 Pylint (3.3.7)

[convention] 18-29: Import outside toplevel (praisonaiagents.approval.require_approval, praisonaiagents.approval.ApprovalDecision, praisonaiagents.approval.console_approval_callback, praisonaiagents.approval.request_approval, praisonaiagents.approval.add_approval_requirement, praisonaiagents.approval.remove_approval_requirement, praisonaiagents.approval.is_approval_required, praisonaiagents.approval.get_risk_level, praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


[warning] 18-29: Unused require_approval imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused ApprovalDecision imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused console_approval_callback imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused request_approval imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused add_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused remove_approval_requirement imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused is_approval_required imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused get_risk_level imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused APPROVAL_REQUIRED_TOOLS imported from praisonaiagents.approval

(W0611)


[warning] 18-29: Unused TOOL_RISK_LEVELS imported from praisonaiagents.approval

(W0611)


144-183: Comprehensive async approval callback testing.

The async test function thoroughly validates:

  • Denial callback behavior with proper error messaging
  • Approval callback functionality
  • Auto-approval for non-dangerous tools
  • Proper ApprovalDecision object handling

This ensures the callback system works correctly in asynchronous contexts.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 147-147: Trailing whitespace

(C0303)


[convention] 149-149: Trailing whitespace

(C0303)


[convention] 154-154: Trailing whitespace

(C0303)


[convention] 159-159: Trailing whitespace

(C0303)


[convention] 163-163: Trailing whitespace

(C0303)


[convention] 168-168: Trailing whitespace

(C0303)


[convention] 169-169: Trailing whitespace

(C0303)


[convention] 171-171: Trailing whitespace

(C0303)


[convention] 176-176: Trailing whitespace

(C0303)


[convention] 182-182: Trailing whitespace

(C0303)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.request_approval, praisonaiagents.approval.ApprovalDecision)

(C0415)


[warning] 151-151: Unused argument 'arguments'

(W0613)


[warning] 156-156: Unused argument 'arguments'

(W0613)


[error] 161-161: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 161-161: Import outside toplevel (praisonaiagents.approval.set_approval_callback)

(C0415)


214-261: Well-designed test orchestration and reporting.

The main() function provides:

  • Systematic execution of all test categories
  • Proper async test handling with asyncio.run()
  • Clear summary reporting with pass/fail counts
  • Appropriate exit codes for CI/CD integration
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 218-218: Trailing whitespace

(C0303)


[convention] 220-220: Trailing whitespace

(C0303)


[convention] 227-227: Trailing whitespace

(C0303)


[convention] 235-235: Trailing whitespace

(C0303)


[convention] 240-240: Trailing whitespace

(C0303)


[convention] 243-243: Trailing whitespace

(C0303)


[convention] 251-251: Trailing whitespace

(C0303)


[convention] 255-255: Trailing whitespace

(C0303)


[warning] 232-232: Catching too general exception Exception

(W0718)


[refactor] 256-261: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

src/praisonai/tests/unit/test_decorator_simple.py (2)

27-82: Excellent comprehensive testing of decorator context management.

The test thoroughly validates:

  • Decorator application and function marking
  • Denial behavior without approval context
  • Successful execution with approval context via mark_approved()
  • Auto-approval callback functionality
  • Context persistence verification with is_already_approved()

This provides excellent coverage of the improved decorator's context management capabilities.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 30-30: Trailing whitespace

(C0303)


[convention] 32-32: Trailing whitespace

(C0303)


[convention] 35-35: Trailing whitespace

(C0303)


[convention] 38-38: Trailing whitespace

(C0303)


[convention] 40-40: Trailing whitespace

(C0303)


[convention] 46-46: Trailing whitespace

(C0303)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 51-51: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 60-60: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[convention] 65-65: Trailing whitespace

(C0303)


[convention] 67-67: Trailing whitespace

(C0303)


[convention] 73-73: Trailing whitespace

(C0303)


[convention] 76-76: Trailing whitespace

(C0303)


[convention] 81-81: Trailing whitespace

(C0303)


[warning] 36-36: Unused argument 'function_name'

(W0613)


[warning] 36-36: Unused argument 'arguments'

(W0613)


[warning] 36-36: Unused argument 'risk_level'

(W0613)


[warning] 55-55: Catching too general exception Exception

(W0718)


[warning] 63-63: Unused argument 'function_name'

(W0613)


[warning] 63-63: Unused argument 'arguments'

(W0613)


[warning] 63-63: Unused argument 'risk_level'

(W0613)


[warning] 71-71: Catching too general exception Exception

(W0718)


90-101: Clear and informative test reporting.

The test provides excellent feedback including:

  • Success confirmation with specific improvements highlighted
  • Key feature validation (context management, async handling, enforcement)
  • Clear indication of the decorator's benefits and functionality
🧰 Tools
🪛 Pylint (3.3.7)

[convention] 101-101: Trailing whitespace

(C0303)


[convention] 91-91: Constant name "success" doesn't conform to UPPER_CASE naming style

(C0103)

src/praisonai-agents/praisonaiagents/agent/agent.py (1)

19-20: LGTM: Clean import additions for approval functionality

The new imports for adisplay_instruction and approval_callback are appropriately added to support the human approval system integration.

src/praisonai-agents/praisonaiagents/approval.py (1)

61-127: Well-implemented decorator with proper sync/async support.

The decorator correctly handles both synchronous and asynchronous functions, with appropriate fallback mechanisms and context management.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 71-71: Trailing whitespace

(C0303)


[convention] 77-77: Trailing whitespace

(C0303)


[convention] 95-95: Trailing whitespace

(C0303)


[convention] 98-98: Trailing whitespace

(C0303)


[convention] 103-103: Trailing whitespace

(C0303)


[convention] 109-109: Trailing whitespace

(C0303)


[convention] 114-114: Trailing whitespace

(C0303)


[convention] 119-119: Trailing whitespace

(C0303)


[convention] 125-125: Trailing whitespace

(C0303)


[warning] 90-90: Catching too general exception Exception

(W0718)


[warning] 92-92: Use lazy % formatting in logging functions

(W1203)


[error] 96-96: Using variable 'decision' before assignment

(E0601)


[refactor] 121-124: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

examples/python/general/human_approval_example.py (5)

40-64: LGTM! Well-implemented custom approval callback.

The custom approval callback demonstrates excellent examples of:

  • Auto-approving low-risk operations
  • Blocking dangerous commands with pattern matching
  • Falling back to default console approval for other cases

The logic correctly handles different risk levels and provides meaningful feedback to users.

🧰 Tools
🪛 Ruff (0.11.9)

45-45: f-string without any placeholders

Remove extraneous f prefix

(F541)

🪛 Pylint (3.3.7)

[convention] 40-40: Line too long (103/100)

(C0301)


[convention] 49-49: Trailing whitespace

(C0303)


[convention] 54-54: Trailing whitespace

(C0303)


[convention] 57-57: Trailing whitespace

(C0303)


[convention] 62-62: Trailing whitespace

(C0303)


[warning] 45-45: Using an f-string that does not have any interpolated variables

(W1309)


89-111: Well-designed task examples covering different risk scenarios.

The tasks effectively demonstrate various dangerous operations:

  • Python code execution
  • File system operations (create/delete)
  • Shell commands

This provides a comprehensive showcase of the approval system across different tool categories.


133-150: LGTM! Excellent demonstration of runtime configuration.

This function effectively shows how to:

  • Add approval requirements for normally safe operations
  • Remove requirements for dangerous operations
  • Display current configuration state

The examples clearly illustrate the flexibility of the approval system.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 135-135: Trailing whitespace

(C0303)


[convention] 138-138: Trailing whitespace

(C0303)


[convention] 142-142: Trailing whitespace

(C0303)


[convention] 146-146: Trailing whitespace

(C0303)


[error] 148-148: Unable to import 'praisonaiagents.approval'

(E0401)


[convention] 148-148: Import outside toplevel (praisonaiagents.approval.APPROVAL_REQUIRED_TOOLS, praisonaiagents.approval.TOOL_RISK_LEVELS)

(C0415)


152-184: Good async demonstration with proper error handling.

The async demo effectively shows how the approval system works in asynchronous contexts. The error handling is appropriate for this demonstration context.

🧰 Tools
🪛 Pylint (3.3.7)

[convention] 154-154: Trailing whitespace

(C0303)


[convention] 157-157: Trailing whitespace

(C0303)


[convention] 161-161: Trailing whitespace

(C0303)


[convention] 166-166: Trailing whitespace

(C0303)


[convention] 173-173: Trailing whitespace

(C0303)


[convention] 179-179: Trailing whitespace

(C0303)


[warning] 183-183: Catching too general exception Exception

(W0718)


196-202: Robust user input handling.

The input handling properly catches KeyboardInterrupt and provides a good user experience with clear prompts and graceful error handling.

import os

# Add the praisonai-agents module to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the path construction for module imports.

The current path construction may not work correctly depending on the test execution context. The path should be relative to the repository root structure.

-sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
-sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
🤖 Prompt for AI Agents
In src/praisonai/tests/unit/test_decorator_enforcement.py at line 11, the
sys.path insertion uses a relative path that may fail depending on where the
test is run. Modify the path construction to be relative to the repository root
by using an absolute path based on the repository root directory, ensuring
consistent module import resolution regardless of the current working directory.

import asyncio

# Add the praisonai-agents module to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the path construction for module imports.

The current path construction may not work correctly. The path should be relative to the repository root structure.

-sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'praisonai-agents'))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'praisonai-agents'))
🤖 Prompt for AI Agents
In src/praisonai/tests/unit/test_approval_basic.py at line 13, the sys.path
insertion uses a relative path that may not correctly resolve from the
repository root. Update the path construction to be relative to the repository
root by adjusting the os.path.join arguments accordingly, ensuring it correctly
points to the 'praisonai-agents' directory from the root of the project.

import os

# Add the praisonai-agents module to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the path construction for module imports.

The current path construction may not work correctly. The path should be relative to the repository root structure.

-sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'praisonai-agents'))
🤖 Prompt for AI Agents
In src/praisonai/tests/unit/test_decorator_simple.py at line 10, the sys.path
insertion uses a path relative to the current file which may not correctly
resolve module imports. Modify the path construction to be relative to the
repository root by adjusting the os.path.join call to navigate from the repo
root to 'src/praisonai-agents', ensuring imports resolve correctly regardless of
the test file location.

Comment on lines +574 to +601
# Check if approval is required for this tool
from ..approval import is_approval_required, console_approval_callback, get_risk_level, mark_approved, ApprovalDecision
if is_approval_required(function_name):
risk_level = get_risk_level(function_name)
logging.info(f"Tool {function_name} requires approval (risk level: {risk_level})")

# Use global approval callback or default console callback
callback = approval_callback or console_approval_callback

try:
decision = callback(function_name, arguments, risk_level)
if not decision.approved:
error_msg = f"Tool execution denied: {decision.reason}"
logging.warning(error_msg)
return {"error": error_msg, "approval_denied": True}

# Mark as approved in context to prevent double approval in decorator
mark_approved(function_name)

# Use modified arguments if provided
if decision.modified_args:
arguments = decision.modified_args
logging.info(f"Using modified arguments: {arguments}")

except Exception as e:
error_msg = f"Error during approval process: {str(e)}"
logging.error(error_msg)
return {"error": error_msg, "approval_error": True}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix import and code quality issues in approval integration

The approval integration logic is sound, but there are several code quality issues to address:

Apply this diff to fix the issues:

-        # Check if approval is required for this tool
-        from ..approval import is_approval_required, console_approval_callback, get_risk_level, mark_approved, ApprovalDecision
+        # Check if approval is required for this tool
+        from ..approval import is_approval_required, console_approval_callback, get_risk_level, mark_approved
         if is_approval_required(function_name):
             risk_level = get_risk_level(function_name)
-            logging.info(f"Tool {function_name} requires approval (risk level: {risk_level})")
-            
+            logging.info("Tool %s requires approval (risk level: %s)", function_name, risk_level)
+
             # Use global approval callback or default console callback
             callback = approval_callback or console_approval_callback
-            
+
             try:
                 decision = callback(function_name, arguments, risk_level)
                 if not decision.approved:
                     error_msg = f"Tool execution denied: {decision.reason}"
                     logging.warning(error_msg)
                     return {"error": error_msg, "approval_denied": True}
-                
+
                 # Mark as approved in context to prevent double approval in decorator
                 mark_approved(function_name)
-                
+
                 # Use modified arguments if provided
                 if decision.modified_args:
                     arguments = decision.modified_args
-                    logging.info(f"Using modified arguments: {arguments}")
-                    
+                    logging.info("Using modified arguments: %s", arguments)
+
             except Exception as e:
                 error_msg = f"Error during approval process: {str(e)}"
                 logging.error(error_msg)
                 return {"error": error_msg, "approval_error": True}
-

Issues addressed:

  • Removed unused ApprovalDecision import (Ruff F401)
  • Fixed lazy logging formatting (Pylint W1203)
  • Removed trailing whitespace
  • Line length stays within reasonable bounds with the formatting changes

Note: The general exception catching is appropriate here since this is error handling at the boundary between the approval system and tool execution.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Check if approval is required for this tool
from ..approval import is_approval_required, console_approval_callback, get_risk_level, mark_approved, ApprovalDecision
if is_approval_required(function_name):
risk_level = get_risk_level(function_name)
logging.info(f"Tool {function_name} requires approval (risk level: {risk_level})")
# Use global approval callback or default console callback
callback = approval_callback or console_approval_callback
try:
decision = callback(function_name, arguments, risk_level)
if not decision.approved:
error_msg = f"Tool execution denied: {decision.reason}"
logging.warning(error_msg)
return {"error": error_msg, "approval_denied": True}
# Mark as approved in context to prevent double approval in decorator
mark_approved(function_name)
# Use modified arguments if provided
if decision.modified_args:
arguments = decision.modified_args
logging.info(f"Using modified arguments: {arguments}")
except Exception as e:
error_msg = f"Error during approval process: {str(e)}"
logging.error(error_msg)
return {"error": error_msg, "approval_error": True}
# Check if approval is required for this tool
from ..approval import is_approval_required, console_approval_callback, get_risk_level, mark_approved
if is_approval_required(function_name):
risk_level = get_risk_level(function_name)
logging.info("Tool %s requires approval (risk level: %s)", function_name, risk_level)
# Use global approval callback or default console callback
callback = approval_callback or console_approval_callback
try:
decision = callback(function_name, arguments, risk_level)
if not decision.approved:
error_msg = f"Tool execution denied: {decision.reason}"
logging.warning(error_msg)
return {"error": error_msg, "approval_denied": True}
# Mark as approved in context to prevent double approval in decorator
mark_approved(function_name)
# Use modified arguments if provided
if decision.modified_args:
arguments = decision.modified_args
logging.info("Using modified arguments: %s", arguments)
except Exception as e:
error_msg = f"Error during approval process: {str(e)}"
logging.error(error_msg)
return {"error": error_msg, "approval_error": True}
🧰 Tools
🪛 Ruff (0.11.9)

575-575: ..approval.ApprovalDecision imported but unused

Remove unused import: ..approval.ApprovalDecision

(F401)

🪛 Pylint (3.3.7)

[convention] 575-575: Line too long (127/100)

(C0301)


[convention] 579-579: Trailing whitespace

(C0303)


[convention] 582-582: Trailing whitespace

(C0303)


[convention] 589-589: Trailing whitespace

(C0303)


[convention] 592-592: Trailing whitespace

(C0303)


[convention] 597-597: Trailing whitespace

(C0303)


[convention] 575-575: Import outside toplevel (approval.is_approval_required, approval.console_approval_callback, approval.get_risk_level, approval.mark_approved, approval.ApprovalDecision)

(C0415)


[warning] 578-578: Use lazy % formatting in logging functions

(W1203)


[warning] 598-598: Catching too general exception Exception

(W0718)


[warning] 596-596: Use lazy % formatting in logging functions

(W1203)


[warning] 575-575: Unused ApprovalDecision imported from approval

(W0611)

🤖 Prompt for AI Agents
In src/praisonai-agents/praisonaiagents/agent/agent.py around lines 574 to 601,
remove the unused import ApprovalDecision to fix the unused import warning.
Change all logging calls that use f-strings to use lazy formatting by passing
the message and arguments separately to logging methods to improve performance
and comply with linting rules. Also, remove any trailing whitespace and ensure
line lengths remain reasonable by adjusting formatting as needed.


import sys
import os
import asyncio

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused import.

asyncio is imported but never used in this file.

-import asyncio
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import asyncio
🧰 Tools
🪛 Ruff (0.11.9)

11-11: asyncio imported but unused

Remove unused import: asyncio

(F401)

🪛 Pylint (3.3.7)

[warning] 11-11: Unused import asyncio

(W0611)

🤖 Prompt for AI Agents
In src/praisonai/tests/unit/test_approval_interactive.py at line 11, the import
statement for asyncio is unused. Remove the line importing asyncio to clean up
the code and avoid unnecessary imports.

Comment on lines +128 to +131
except KeyboardInterrupt:
print("\n❌ Process cancelled by user")
except Exception as e:
print(f"\n❌ Process failed: {e}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve exception handling specificity.

The broad Exception catch should be more specific to provide better error handling and debugging information.

     except KeyboardInterrupt:
         print("\n❌ Process cancelled by user")
-    except Exception as e:
-        print(f"\n❌ Process failed: {e}")
+    except Exception as e:
+        print(f"\n❌ Process failed: {e}")
+        logging.exception("Process execution failed")

Consider catching specific exceptions like ImportError, AttributeError, etc. based on expected failure modes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except KeyboardInterrupt:
print("\n❌ Process cancelled by user")
except Exception as e:
print(f"\n❌ Process failed: {e}")
except KeyboardInterrupt:
print("\n❌ Process cancelled by user")
except Exception as e:
print(f"\n❌ Process failed: {e}")
logging.exception("Process execution failed")
🧰 Tools
🪛 Pylint (3.3.7)

[warning] 130-130: Catching too general exception Exception

(W0718)

🤖 Prompt for AI Agents
In examples/python/general/human_approval_example.py around lines 128 to 131,
the current code catches a broad Exception which reduces error handling
specificity. Replace the broad Exception catch with more specific exceptions
such as ImportError, AttributeError, or others relevant to the expected failure
modes in this context. This will improve debugging and make error handling
clearer and more precise.

shaneholloman pushed a commit to shaneholloman/praisonai that referenced this pull request Feb 4, 2026
…12-20250601_032826

feat: Add human-in-the-loop approval system for dangerous tool operations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add human executting code for run some python functions that would be awesome!! to solve most of the features in the agent ecosystem

1 participant