PraisonAI 2.3.59__tar.gz → 2.3.61__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {praisonai-2.3.59 → praisonai-2.3.61}/PKG-INFO +1 -1
  2. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/PKG-INFO +1 -1
  3. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/main.py +110 -2
  4. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/deploy.py +1 -1
  5. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/base.py +6 -3
  6. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/claude_code.py +12 -12
  7. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/codex_cli.py +3 -0
  8. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/cursor_cli.py +3 -0
  9. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/gemini_cli.py +6 -6
  10. praisonai-2.3.61/praisonai/version.py +1 -0
  11. praisonai-2.3.59/praisonai/version.py +0 -1
  12. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/SOURCES.txt +0 -0
  13. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/dependency_links.txt +0 -0
  14. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/entry_points.txt +0 -0
  15. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/requires.txt +0 -0
  16. {praisonai-2.3.59 → praisonai-2.3.61}/PraisonAI.egg-info/top_level.txt +0 -0
  17. {praisonai-2.3.59 → praisonai-2.3.61}/README.md +0 -0
  18. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/__init__.py +0 -0
  19. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/__main__.py +0 -0
  20. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/agents_generator.py +0 -0
  21. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/api/call.py +0 -0
  22. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/auto.py +0 -0
  23. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/chainlit_ui.py +0 -0
  24. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/__init__.py +0 -0
  25. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/__init__.py +0 -0
  26. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/at_mentions.py +0 -0
  27. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/auto_memory.py +0 -0
  28. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/autonomy_mode.py +0 -0
  29. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/base.py +0 -0
  30. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/cost_tracker.py +0 -0
  31. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/external_agents.py +0 -0
  32. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/fast_context.py +0 -0
  33. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/flow_display.py +0 -0
  34. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/git_integration.py +0 -0
  35. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/guardrail.py +0 -0
  36. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/handoff.py +0 -0
  37. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/image.py +0 -0
  38. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/interactive_tui.py +0 -0
  39. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/knowledge.py +0 -0
  40. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/mcp.py +0 -0
  41. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/message_queue.py +0 -0
  42. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/metrics.py +0 -0
  43. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/n8n.py +0 -0
  44. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/repo_map.py +0 -0
  45. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/router.py +0 -0
  46. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/sandbox_executor.py +0 -0
  47. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/session.py +0 -0
  48. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/slash_commands.py +0 -0
  49. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/telemetry.py +0 -0
  50. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/todo.py +0 -0
  51. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/tools.py +0 -0
  52. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/cli/features/workflow.py +0 -0
  53. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/__init__.py +0 -0
  54. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/agent_tools.py +0 -0
  55. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/diff/__init__.py +0 -0
  56. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/diff/diff_strategy.py +0 -0
  57. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/__init__.py +0 -0
  58. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/apply_diff.py +0 -0
  59. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/execute_command.py +0 -0
  60. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/list_files.py +0 -0
  61. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/read_file.py +0 -0
  62. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/search_replace.py +0 -0
  63. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/tools/write_file.py +0 -0
  64. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/utils/__init__.py +0 -0
  65. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/utils/file_utils.py +0 -0
  66. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/utils/ignore_utils.py +0 -0
  67. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/code/utils/text_utils.py +0 -0
  68. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/inbuilt_tools/__init__.py +0 -0
  69. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
  70. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/inc/__init__.py +0 -0
  71. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/inc/config.py +0 -0
  72. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/inc/models.py +0 -0
  73. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/integrations/__init__.py +0 -0
  74. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/profiler.py +0 -0
  75. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/scheduler.py +0 -0
  76. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/setup/__init__.py +0 -0
  77. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/setup/build.py +0 -0
  78. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/setup/post_install.py +0 -0
  79. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/setup/setup_conda_env.py +0 -0
  80. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/setup.py +0 -0
  81. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/test.py +0 -0
  82. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/train.py +0 -0
  83. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/train_vision.py +0 -0
  84. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/agents.py +0 -0
  85. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/callbacks.py +0 -0
  86. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/chat.py +0 -0
  87. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/code.py +0 -0
  88. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/colab.py +0 -0
  89. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/colab_chainlit.py +0 -0
  90. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/components/aicoder.py +0 -0
  91. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/context.py +0 -0
  92. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/database_config.py +0 -0
  93. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/db.py +0 -0
  94. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/realtime.py +0 -0
  95. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/realtimeclient/__init__.py +0 -0
  96. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/realtimeclient/tools.py +0 -0
  97. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/ui/sql_alchemy.py +0 -0
  98. {praisonai-2.3.59 → praisonai-2.3.61}/praisonai/upload_vision.py +0 -0
  99. {praisonai-2.3.59 → praisonai-2.3.61}/pyproject.toml +0 -0
  100. {praisonai-2.3.59 → praisonai-2.3.61}/setup.cfg +0 -0
  101. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test.py +0 -0
  102. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_agents_playbook.py +0 -0
  103. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_approval_system.py +0 -0
  104. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_basic.py +0 -0
  105. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_cli_features.py +0 -0
  106. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_custom_tools_fix.py +0 -0
  107. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_double_api_fix.py +0 -0
  108. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_n8n_integration.py +0 -0
  109. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_phase2_refactor.py +0 -0
  110. {praisonai-2.3.59 → praisonai-2.3.61}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.3.59
3
+ Version: 2.3.61
4
4
  Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.3.59
3
+ Version: 2.3.61
4
4
  Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  License: MIT
@@ -701,6 +701,10 @@ class PraisonAI:
701
701
  # Sandbox Execution - secure command execution
702
702
  parser.add_argument("--sandbox", type=str, choices=["off", "basic", "strict"], help="Enable sandboxed command execution")
703
703
 
704
+ # External Agent - use external AI CLI tools
705
+ parser.add_argument("--external-agent", type=str, choices=["claude", "gemini", "codex", "cursor"],
706
+ help="Use external AI CLI tool (claude, gemini, codex, cursor)")
707
+
704
708
  # If we're in a test environment, parse with empty args to avoid pytest interference
705
709
  if in_test_env:
706
710
  args, unknown_args = parser.parse_known_args([])
@@ -3021,7 +3025,8 @@ Provide ONLY the commit message, no explanations."""
3021
3025
  if tool_level_value <= max_level_value:
3022
3026
  return ApprovalDecision(approved=True, reason=f"Auto-approved (level {risk_level} <= {max_level})")
3023
3027
  else:
3024
- # Fall back to console approval for higher risk levels
3028
+ # Signal to pause Live display before showing approval prompt
3029
+ # This is handled by the approval_pending flag in status_info
3025
3030
  from praisonaiagents.approval import console_approval_callback
3026
3031
  return console_approval_callback(function_name, arguments, risk_level)
3027
3032
 
@@ -3068,6 +3073,43 @@ Provide ONLY the commit message, no explanations."""
3068
3073
  existing_tools = list(mcp_tools)
3069
3074
  agent_config['tools'] = existing_tools
3070
3075
 
3076
+ # External Agent - Use external AI CLI tools directly
3077
+ if getattr(self.args, 'external_agent', None):
3078
+ from rich.console import Console
3079
+ ext_console = Console()
3080
+ external_agent_name = self.args.external_agent
3081
+ try:
3082
+ from .features.external_agents import ExternalAgentsHandler
3083
+ handler = ExternalAgentsHandler(verbose=getattr(self.args, 'verbose', False))
3084
+
3085
+ # Get workspace from current directory
3086
+ import os
3087
+ workspace = os.getcwd()
3088
+
3089
+ integration = handler.get_integration(external_agent_name, workspace=workspace)
3090
+
3091
+ if integration.is_available:
3092
+ ext_console.print(f"[bold cyan]🔌 Using external agent: {external_agent_name}[/bold cyan]")
3093
+
3094
+ # Run the external agent directly instead of PraisonAI agent
3095
+ import asyncio
3096
+ try:
3097
+ result = asyncio.run(integration.execute(prompt))
3098
+ ext_console.print(f"\n[bold green]Result from {external_agent_name}:[/bold green]")
3099
+ ext_console.print(result)
3100
+ # Return empty string to avoid duplicate printing by caller
3101
+ return ""
3102
+ except Exception as e:
3103
+ ext_console.print(f"[red]Error executing {external_agent_name}: {e}[/red]")
3104
+ return None
3105
+ else:
3106
+ ext_console.print(f"[yellow]⚠️ External agent '{external_agent_name}' is not installed[/yellow]")
3107
+ ext_console.print(f"[dim]Install with: {handler._get_install_instructions(external_agent_name)}[/dim]")
3108
+ return None
3109
+ except Exception as e:
3110
+ ext_console.print(f"[red]Error setting up external agent: {e}[/red]")
3111
+ return None
3112
+
3071
3113
  # Fast Context - Codebase search
3072
3114
  if getattr(self.args, 'fast_context', None):
3073
3115
  from .features.fast_context import FastContextHandler
@@ -3297,7 +3339,9 @@ Now, {final_instruction.lower()}:"""
3297
3339
  'result': None,
3298
3340
  'error': None,
3299
3341
  'start_time': time.time(),
3300
- 'available_tools': tool_names
3342
+ 'available_tools': tool_names,
3343
+ 'approval_pending': False, # Flag to pause Live display during approval
3344
+ 'live_instance': None # Reference to Live instance for stopping
3301
3345
  }
3302
3346
 
3303
3347
  def tool_call_callback(message):
@@ -3360,6 +3404,53 @@ Now, {final_instruction.lower()}:"""
3360
3404
  finally:
3361
3405
  status_info['done'] = True
3362
3406
 
3407
+ # Set up approval callback that stops Live display before prompting
3408
+ # Only if not using --trust (which auto-approves everything)
3409
+ if not getattr(self.args, 'trust', False):
3410
+ from praisonaiagents.approval import set_approval_callback, ApprovalDecision
3411
+ from rich.prompt import Confirm
3412
+ from rich.panel import Panel
3413
+
3414
+ def cli_approval_with_live_pause(function_name, arguments, risk_level):
3415
+ """Approval callback that stops Live display before prompting."""
3416
+ # Signal to stop Live display
3417
+ status_info['approval_pending'] = True
3418
+
3419
+ # Wait a moment for Live to stop
3420
+ time.sleep(0.2)
3421
+
3422
+ # Now show the approval prompt
3423
+ risk_colors = {"critical": "bold red", "high": "red", "medium": "yellow", "low": "blue"}
3424
+ risk_color = risk_colors.get(risk_level, "white")
3425
+
3426
+ tool_info = f"[bold]Function:[/] {function_name}\n"
3427
+ tool_info += f"[bold]Risk Level:[/] [{risk_color}]{risk_level.upper()}[/{risk_color}]\n"
3428
+ tool_info += "[bold]Arguments:[/]\n"
3429
+ for key, value in arguments.items():
3430
+ str_value = str(value)[:100] + "..." if len(str(value)) > 100 else str(value)
3431
+ tool_info += f" {key}: {str_value}\n"
3432
+
3433
+ console.print(Panel(tool_info.strip(), title="🔒 Tool Approval Required", border_style=risk_color))
3434
+
3435
+ try:
3436
+ approved = Confirm.ask(f"[{risk_color}]Execute this {risk_level} risk tool?[/{risk_color}]", default=False)
3437
+ status_info['approval_pending'] = False
3438
+
3439
+ if approved:
3440
+ console.print("[green]✅ Approved[/green]")
3441
+ return ApprovalDecision(approved=True, reason="User approved")
3442
+ else:
3443
+ console.print("[red]❌ Denied[/red]")
3444
+ return ApprovalDecision(approved=False, reason="User denied")
3445
+ except (KeyboardInterrupt, EOFError):
3446
+ status_info['approval_pending'] = False
3447
+ console.print("\n[red]❌ Cancelled[/red]")
3448
+ return ApprovalDecision(approved=False, reason="User cancelled")
3449
+
3450
+ # Only set if not already set by --approve-level
3451
+ if not getattr(self.args, 'approve_level', None):
3452
+ set_approval_callback(cli_approval_with_live_pause)
3453
+
3363
3454
  # Start agent in background thread
3364
3455
  thread = threading.Thread(target=run_agent, daemon=True)
3365
3456
  thread.start()
@@ -3367,9 +3458,26 @@ Now, {final_instruction.lower()}:"""
3367
3458
  # Show live status while processing
3368
3459
  try:
3369
3460
  with Live(build_status_display(), console=console, refresh_per_second=4, transient=True) as live:
3461
+ status_info['live_instance'] = live
3370
3462
  while not status_info['done']:
3463
+ # Check if approval is pending - stop Live to show prompt
3464
+ if status_info['approval_pending']:
3465
+ break
3371
3466
  live.update(build_status_display())
3372
3467
  time.sleep(0.1)
3468
+
3469
+ # If approval was pending, wait for it to complete then restart Live
3470
+ while status_info['approval_pending']:
3471
+ time.sleep(0.1)
3472
+
3473
+ # Continue with Live display if not done
3474
+ if not status_info['done']:
3475
+ with Live(build_status_display(), console=console, refresh_per_second=4, transient=True) as live:
3476
+ while not status_info['done']:
3477
+ if status_info['approval_pending']:
3478
+ break
3479
+ live.update(build_status_display())
3480
+ time.sleep(0.1)
3373
3481
  except KeyboardInterrupt:
3374
3482
  console.print("\n[dim]Interrupted[/dim]")
3375
3483
  # Unregister callback
@@ -57,7 +57,7 @@ class CloudDeployer:
57
57
  file.write("FROM python:3.11-slim\n")
58
58
  file.write("WORKDIR /app\n")
59
59
  file.write("COPY . .\n")
60
- file.write("RUN pip install flask praisonai==2.3.59 gunicorn markdown\n")
60
+ file.write("RUN pip install flask praisonai==2.3.61 gunicorn markdown\n")
61
61
  file.write("EXPOSE 8080\n")
62
62
  file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
63
63
 
@@ -135,7 +135,8 @@ class BaseCLIIntegration(ABC):
135
135
  *cmd,
136
136
  stdout=asyncio.subprocess.PIPE,
137
137
  stderr=asyncio.subprocess.PIPE,
138
- cwd=self.workspace
138
+ cwd=self.workspace,
139
+ env=self.get_env()
139
140
  )
140
141
 
141
142
  try:
@@ -173,7 +174,8 @@ class BaseCLIIntegration(ABC):
173
174
  *cmd,
174
175
  stdout=asyncio.subprocess.PIPE,
175
176
  stderr=asyncio.subprocess.PIPE,
176
- cwd=self.workspace
177
+ cwd=self.workspace,
178
+ env=self.get_env()
177
179
  )
178
180
 
179
181
  try:
@@ -208,7 +210,8 @@ class BaseCLIIntegration(ABC):
208
210
  *cmd,
209
211
  stdout=asyncio.subprocess.PIPE,
210
212
  stderr=asyncio.subprocess.PIPE,
211
- cwd=self.workspace
213
+ cwd=self.workspace,
214
+ env=self.get_env()
212
215
  )
213
216
 
214
217
  try:
@@ -127,23 +127,16 @@ class ClaudeCodeIntegration(BaseCLIIntegration):
127
127
  """
128
128
  cmd = ["claude"]
129
129
 
130
- # Add continue flag if needed
131
- if continue_session or self._session_active:
132
- cmd.append("--continue")
133
-
134
- # Add skip permissions flag
135
- if self.skip_permissions:
136
- cmd.append("--dangerously-skip-permissions")
137
-
138
- # Add print mode flag
130
+ # Add print mode flag for non-interactive output
139
131
  cmd.append("-p")
140
132
 
141
- # Add prompt
142
- cmd.append(prompt)
143
-
144
133
  # Add output format
145
134
  cmd.extend(["--output-format", self.output_format])
146
135
 
136
+ # Add continue flag if needed
137
+ if continue_session or self._session_active:
138
+ cmd.append("--continue")
139
+
147
140
  # Add model if specified
148
141
  if self.model:
149
142
  cmd.extend(["--model", self.model])
@@ -160,6 +153,13 @@ class ClaudeCodeIntegration(BaseCLIIntegration):
160
153
  if self.disallowed_tools:
161
154
  cmd.extend(["--disallowedTools", ",".join(self.disallowed_tools)])
162
155
 
156
+ # Add verbose if needed
157
+ if options.get('verbose'):
158
+ cmd.append("--verbose")
159
+
160
+ # Add prompt last
161
+ cmd.append(prompt)
162
+
163
163
  return cmd
164
164
 
165
165
  async def execute(self, prompt: str, **options) -> str:
@@ -93,6 +93,9 @@ class CodexCLIIntegration(BaseCLIIntegration):
93
93
  """
94
94
  cmd = ["codex", "exec"]
95
95
 
96
+ # Add working directory
97
+ cmd.extend(["-C", self.workspace])
98
+
96
99
  # Add task
97
100
  cmd.append(task)
98
101
 
@@ -97,6 +97,9 @@ class CursorCLIIntegration(BaseCLIIntegration):
97
97
  # Add print mode flag
98
98
  cmd.append("-p")
99
99
 
100
+ # Add workspace
101
+ cmd.extend(["--workspace", self.workspace])
102
+
100
103
  # Add force flag if enabled
101
104
  if self.force:
102
105
  cmd.append("--force")
@@ -92,12 +92,6 @@ class GeminiCLIIntegration(BaseCLIIntegration):
92
92
  """
93
93
  cmd = ["gemini"]
94
94
 
95
- # Add print mode flag
96
- cmd.append("-p")
97
-
98
- # Add prompt
99
- cmd.append(prompt)
100
-
101
95
  # Add model
102
96
  cmd.extend(["-m", self.model])
103
97
 
@@ -112,6 +106,12 @@ class GeminiCLIIntegration(BaseCLIIntegration):
112
106
  if self.sandbox:
113
107
  cmd.append("--sandbox")
114
108
 
109
+ # Add YOLO mode for non-interactive execution
110
+ cmd.append("--yolo")
111
+
112
+ # Add prompt as positional argument (must be last)
113
+ cmd.append(prompt)
114
+
115
115
  return cmd
116
116
 
117
117
  async def execute(self, prompt: str, **options) -> str:
@@ -0,0 +1 @@
1
+ __version__ = "2.3.61"
@@ -1 +0,0 @@
1
- __version__ = "2.3.59"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes