praisonAI 2.3.64__tar.gz → 2.3.65__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.
- {praisonai-2.3.64 → praisonai-2.3.65}/PKG-INFO +23 -24
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/PKG-INFO +23 -24
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/SOURCES.txt +3 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/README.md +22 -23
- praisonai-2.3.65/praisonai/cli/features/agent_scheduler.py +182 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/main.py +10 -1
- praisonai-2.3.65/praisonai/cli/schedule_cli.py +54 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/deploy.py +1 -1
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/scheduler/agent_scheduler.py +97 -0
- praisonai-2.3.65/praisonai/scheduler/yaml_loader.py +197 -0
- praisonai-2.3.65/praisonai/version.py +1 -0
- praisonai-2.3.64/praisonai/version.py +0 -1
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/dependency_links.txt +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/entry_points.txt +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/requires.txt +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/PraisonAI.egg-info/top_level.txt +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/__main__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/agent_scheduler.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/agents_generator.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/api/call.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/auto.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/chainlit_ui.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/at_mentions.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/auto_memory.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/autonomy_mode.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/base.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/cost_tracker.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/external_agents.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/fast_context.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/flow_display.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/git_integration.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/guardrail.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/handoff.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/image.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/interactive_tui.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/knowledge.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/mcp.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/message_queue.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/metrics.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/n8n.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/repo_map.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/router.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/sandbox_executor.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/session.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/slash_commands.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/telemetry.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/todo.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/tools.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/cli/features/workflow.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/agent_tools.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/diff/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/diff/diff_strategy.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/apply_diff.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/execute_command.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/list_files.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/read_file.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/search_replace.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/tools/write_file.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/utils/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/utils/file_utils.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/utils/ignore_utils.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/code/utils/text_utils.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/inbuilt_tools/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/inc/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/inc/config.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/inc/models.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/base.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/claude_code.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/codex_cli.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/cursor_cli.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/integrations/gemini_cli.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/profiler.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/scheduler/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/scheduler/base.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/scheduler.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/setup/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/setup/build.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/setup/post_install.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/setup/setup_conda_env.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/setup.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/test.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/train.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/train_vision.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/agents.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/callbacks.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/chat.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/code.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/colab.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/colab_chainlit.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/components/aicoder.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/context.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/database_config.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/db.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/realtime.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/realtimeclient/__init__.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/realtimeclient/tools.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/ui/sql_alchemy.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/praisonai/upload_vision.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/pyproject.toml +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/setup.cfg +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_agents_playbook.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_approval_system.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_basic.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_cli_features.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_custom_tools_fix.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_double_api_fix.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_n8n_integration.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_phase2_refactor.py +0 -0
- {praisonai-2.3.64 → praisonai-2.3.65}/tests/test_runner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.65
|
|
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
|
|
@@ -364,9 +364,7 @@ npm install praisonai
|
|
|
364
364
|
| ↳ Git Integration | [Example](examples/python/cli/git_integration_example.py) | [📖](https://docs.praison.ai/docs/cli/git-integration) |
|
|
365
365
|
| ↳ Sandbox Execution | [Example](examples/python/cli/sandbox_execution_example.py) | [📖](https://docs.praison.ai/docs/cli/sandbox-execution) |
|
|
366
366
|
| **⏰ 24/7 Scheduling** | | |
|
|
367
|
-
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/scheduler
|
|
368
|
-
| ↳ Scheduled News Checker | [Example](examples/python/scheduled_agents/news_checker_agent.py) | [📖](https://docs.praison.ai/scheduler/examples) |
|
|
369
|
-
| ↳ Simple Scheduler Test | [Example](examples/python/scheduled_agents/simple_test.py) | [📖](https://docs.praison.ai/scheduler/quickstart) |
|
|
367
|
+
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/docs/cli/scheduler) |
|
|
370
368
|
|
|
371
369
|
---
|
|
372
370
|
|
|
@@ -1345,32 +1343,33 @@ praisonai "Complex task" --metrics --planning
|
|
|
1345
1343
|
|
|
1346
1344
|
### Scheduler CLI:
|
|
1347
1345
|
```bash
|
|
1348
|
-
# Schedule an agent
|
|
1349
|
-
praisonai schedule
|
|
1346
|
+
# Schedule an agent using agents.yaml
|
|
1347
|
+
praisonai schedule agents.yaml
|
|
1350
1348
|
|
|
1351
|
-
#
|
|
1352
|
-
praisonai schedule --interval "*/30m"
|
|
1349
|
+
# Override interval from CLI
|
|
1350
|
+
praisonai schedule agents.yaml --interval "*/30m"
|
|
1353
1351
|
|
|
1354
|
-
#
|
|
1355
|
-
praisonai schedule
|
|
1352
|
+
# With verbose logging
|
|
1353
|
+
praisonai schedule agents.yaml --verbose
|
|
1354
|
+
```
|
|
1356
1355
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1356
|
+
**agents.yaml with schedule:**
|
|
1357
|
+
```yaml
|
|
1358
|
+
framework: praisonai
|
|
1359
1359
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1360
|
+
agents:
|
|
1361
|
+
- name: "AI News Monitor"
|
|
1362
|
+
instructions: "Search and summarize AI news"
|
|
1363
|
+
tools:
|
|
1364
|
+
- search_tool
|
|
1362
1365
|
|
|
1363
|
-
|
|
1364
|
-
praisonai schedule --help
|
|
1365
|
-
```
|
|
1366
|
+
task: "Search for latest AI news"
|
|
1366
1367
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
- `*/5s` - Every 5 seconds (for testing)
|
|
1373
|
-
- `3600` - Custom seconds
|
|
1368
|
+
schedule:
|
|
1369
|
+
interval: "hourly" # hourly, daily, */30m, */6h
|
|
1370
|
+
max_retries: 3
|
|
1371
|
+
run_immediately: true
|
|
1372
|
+
```
|
|
1374
1373
|
|
|
1375
1374
|
### Image Processing CLI:
|
|
1376
1375
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PraisonAI
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.65
|
|
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
|
|
@@ -364,9 +364,7 @@ npm install praisonai
|
|
|
364
364
|
| ↳ Git Integration | [Example](examples/python/cli/git_integration_example.py) | [📖](https://docs.praison.ai/docs/cli/git-integration) |
|
|
365
365
|
| ↳ Sandbox Execution | [Example](examples/python/cli/sandbox_execution_example.py) | [📖](https://docs.praison.ai/docs/cli/sandbox-execution) |
|
|
366
366
|
| **⏰ 24/7 Scheduling** | | |
|
|
367
|
-
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/scheduler
|
|
368
|
-
| ↳ Scheduled News Checker | [Example](examples/python/scheduled_agents/news_checker_agent.py) | [📖](https://docs.praison.ai/scheduler/examples) |
|
|
369
|
-
| ↳ Simple Scheduler Test | [Example](examples/python/scheduled_agents/simple_test.py) | [📖](https://docs.praison.ai/scheduler/quickstart) |
|
|
367
|
+
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/docs/cli/scheduler) |
|
|
370
368
|
|
|
371
369
|
---
|
|
372
370
|
|
|
@@ -1345,32 +1343,33 @@ praisonai "Complex task" --metrics --planning
|
|
|
1345
1343
|
|
|
1346
1344
|
### Scheduler CLI:
|
|
1347
1345
|
```bash
|
|
1348
|
-
# Schedule an agent
|
|
1349
|
-
praisonai schedule
|
|
1346
|
+
# Schedule an agent using agents.yaml
|
|
1347
|
+
praisonai schedule agents.yaml
|
|
1350
1348
|
|
|
1351
|
-
#
|
|
1352
|
-
praisonai schedule --interval "*/30m"
|
|
1349
|
+
# Override interval from CLI
|
|
1350
|
+
praisonai schedule agents.yaml --interval "*/30m"
|
|
1353
1351
|
|
|
1354
|
-
#
|
|
1355
|
-
praisonai schedule
|
|
1352
|
+
# With verbose logging
|
|
1353
|
+
praisonai schedule agents.yaml --verbose
|
|
1354
|
+
```
|
|
1356
1355
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1356
|
+
**agents.yaml with schedule:**
|
|
1357
|
+
```yaml
|
|
1358
|
+
framework: praisonai
|
|
1359
1359
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1360
|
+
agents:
|
|
1361
|
+
- name: "AI News Monitor"
|
|
1362
|
+
instructions: "Search and summarize AI news"
|
|
1363
|
+
tools:
|
|
1364
|
+
- search_tool
|
|
1362
1365
|
|
|
1363
|
-
|
|
1364
|
-
praisonai schedule --help
|
|
1365
|
-
```
|
|
1366
|
+
task: "Search for latest AI news"
|
|
1366
1367
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
- `*/5s` - Every 5 seconds (for testing)
|
|
1373
|
-
- `3600` - Custom seconds
|
|
1368
|
+
schedule:
|
|
1369
|
+
interval: "hourly" # hourly, daily, */30m, */6h
|
|
1370
|
+
max_retries: 3
|
|
1371
|
+
run_immediately: true
|
|
1372
|
+
```
|
|
1374
1373
|
|
|
1375
1374
|
### Image Processing CLI:
|
|
1376
1375
|
```bash
|
|
@@ -24,7 +24,9 @@ praisonai/version.py
|
|
|
24
24
|
praisonai/api/call.py
|
|
25
25
|
praisonai/cli/__init__.py
|
|
26
26
|
praisonai/cli/main.py
|
|
27
|
+
praisonai/cli/schedule_cli.py
|
|
27
28
|
praisonai/cli/features/__init__.py
|
|
29
|
+
praisonai/cli/features/agent_scheduler.py
|
|
28
30
|
praisonai/cli/features/at_mentions.py
|
|
29
31
|
praisonai/cli/features/auto_memory.py
|
|
30
32
|
praisonai/cli/features/autonomy_mode.py
|
|
@@ -81,6 +83,7 @@ praisonai/integrations/gemini_cli.py
|
|
|
81
83
|
praisonai/scheduler/__init__.py
|
|
82
84
|
praisonai/scheduler/agent_scheduler.py
|
|
83
85
|
praisonai/scheduler/base.py
|
|
86
|
+
praisonai/scheduler/yaml_loader.py
|
|
84
87
|
praisonai/setup/__init__.py
|
|
85
88
|
praisonai/setup/build.py
|
|
86
89
|
praisonai/setup/post_install.py
|
|
@@ -267,9 +267,7 @@ npm install praisonai
|
|
|
267
267
|
| ↳ Git Integration | [Example](examples/python/cli/git_integration_example.py) | [📖](https://docs.praison.ai/docs/cli/git-integration) |
|
|
268
268
|
| ↳ Sandbox Execution | [Example](examples/python/cli/sandbox_execution_example.py) | [📖](https://docs.praison.ai/docs/cli/sandbox-execution) |
|
|
269
269
|
| **⏰ 24/7 Scheduling** | | |
|
|
270
|
-
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/scheduler
|
|
271
|
-
| ↳ Scheduled News Checker | [Example](examples/python/scheduled_agents/news_checker_agent.py) | [📖](https://docs.praison.ai/scheduler/examples) |
|
|
272
|
-
| ↳ Simple Scheduler Test | [Example](examples/python/scheduled_agents/simple_test.py) | [📖](https://docs.praison.ai/scheduler/quickstart) |
|
|
270
|
+
| ↳ Agent Scheduler | [Example](examples/python/scheduled_agents/news_checker_live.py) | [📖](https://docs.praison.ai/docs/cli/scheduler) |
|
|
273
271
|
|
|
274
272
|
---
|
|
275
273
|
|
|
@@ -1248,32 +1246,33 @@ praisonai "Complex task" --metrics --planning
|
|
|
1248
1246
|
|
|
1249
1247
|
### Scheduler CLI:
|
|
1250
1248
|
```bash
|
|
1251
|
-
# Schedule an agent
|
|
1252
|
-
praisonai schedule
|
|
1249
|
+
# Schedule an agent using agents.yaml
|
|
1250
|
+
praisonai schedule agents.yaml
|
|
1253
1251
|
|
|
1254
|
-
#
|
|
1255
|
-
praisonai schedule --interval "*/30m"
|
|
1252
|
+
# Override interval from CLI
|
|
1253
|
+
praisonai schedule agents.yaml --interval "*/30m"
|
|
1256
1254
|
|
|
1257
|
-
#
|
|
1258
|
-
praisonai schedule
|
|
1255
|
+
# With verbose logging
|
|
1256
|
+
praisonai schedule agents.yaml --verbose
|
|
1257
|
+
```
|
|
1259
1258
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1259
|
+
**agents.yaml with schedule:**
|
|
1260
|
+
```yaml
|
|
1261
|
+
framework: praisonai
|
|
1262
1262
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1263
|
+
agents:
|
|
1264
|
+
- name: "AI News Monitor"
|
|
1265
|
+
instructions: "Search and summarize AI news"
|
|
1266
|
+
tools:
|
|
1267
|
+
- search_tool
|
|
1265
1268
|
|
|
1266
|
-
|
|
1267
|
-
praisonai schedule --help
|
|
1268
|
-
```
|
|
1269
|
+
task: "Search for latest AI news"
|
|
1269
1270
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
- `*/5s` - Every 5 seconds (for testing)
|
|
1276
|
-
- `3600` - Custom seconds
|
|
1271
|
+
schedule:
|
|
1272
|
+
interval: "hourly" # hourly, daily, */30m, */6h
|
|
1273
|
+
max_retries: 3
|
|
1274
|
+
run_immediately: true
|
|
1275
|
+
```
|
|
1277
1276
|
|
|
1278
1277
|
### Image Processing CLI:
|
|
1279
1278
|
```bash
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent Scheduler CLI Feature.
|
|
3
|
+
|
|
4
|
+
Provides CLI commands for scheduling agents to run 24/7 at regular intervals.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AgentSchedulerHandler:
|
|
13
|
+
"""Handler for agent scheduler CLI commands."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def handle_schedule_command(args) -> int:
|
|
17
|
+
"""
|
|
18
|
+
Handle the schedule command for running agents periodically.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
args: Parsed command-line arguments
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Exit code (0 for success, 1 for error)
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
from praisonai.scheduler import AgentScheduler
|
|
28
|
+
except ImportError:
|
|
29
|
+
print("Error: praisonai.scheduler module not found")
|
|
30
|
+
print("Please ensure PraisonAI is properly installed")
|
|
31
|
+
return 1
|
|
32
|
+
|
|
33
|
+
# Get YAML file path (default to agents.yaml)
|
|
34
|
+
yaml_path = getattr(args, 'schedule_yaml', None) or 'agents.yaml'
|
|
35
|
+
|
|
36
|
+
# Get overrides from CLI
|
|
37
|
+
interval_override = getattr(args, 'schedule_interval', None)
|
|
38
|
+
max_retries_override = getattr(args, 'schedule_max_retries', None)
|
|
39
|
+
verbose = getattr(args, 'verbose', False)
|
|
40
|
+
|
|
41
|
+
# Set up logging
|
|
42
|
+
if verbose:
|
|
43
|
+
logging.basicConfig(
|
|
44
|
+
level=logging.INFO,
|
|
45
|
+
format='[%(asctime)s] %(levelname)s - %(message)s',
|
|
46
|
+
datefmt='%Y-%m-%d %H:%M:%S'
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
# Create scheduler from YAML
|
|
51
|
+
print(f"🤖 Loading agent configuration from: {yaml_path}")
|
|
52
|
+
scheduler = AgentScheduler.from_yaml(
|
|
53
|
+
yaml_path=yaml_path,
|
|
54
|
+
interval_override=interval_override,
|
|
55
|
+
max_retries_override=max_retries_override
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Display configuration
|
|
59
|
+
agent_name = getattr(scheduler.agent, 'name', 'Agent')
|
|
60
|
+
print(f"\n{'='*60}")
|
|
61
|
+
print(f"🤖 Starting 24/7 {agent_name}")
|
|
62
|
+
print(f"{'='*60}")
|
|
63
|
+
print(f"Task: {scheduler.task[:80]}{'...' if len(scheduler.task) > 80 else ''}")
|
|
64
|
+
|
|
65
|
+
# Get schedule info
|
|
66
|
+
schedule_config = scheduler._yaml_schedule_config
|
|
67
|
+
interval = interval_override or schedule_config.get('interval', 'hourly')
|
|
68
|
+
max_retries = max_retries_override or schedule_config.get('max_retries', 3)
|
|
69
|
+
|
|
70
|
+
print(f"Schedule: {interval}")
|
|
71
|
+
print(f"Max Retries: {max_retries}")
|
|
72
|
+
print(f"{'='*60}\n")
|
|
73
|
+
|
|
74
|
+
# Start scheduler
|
|
75
|
+
print("⏰ Starting scheduler... (Press Ctrl+C to stop)\n")
|
|
76
|
+
scheduler.start_from_yaml_config()
|
|
77
|
+
|
|
78
|
+
# Keep running until interrupted
|
|
79
|
+
try:
|
|
80
|
+
while scheduler.is_running:
|
|
81
|
+
import time
|
|
82
|
+
time.sleep(1)
|
|
83
|
+
except KeyboardInterrupt:
|
|
84
|
+
print("\n\n🛑 Stopping scheduler...")
|
|
85
|
+
scheduler.stop()
|
|
86
|
+
|
|
87
|
+
# Display final stats
|
|
88
|
+
stats = scheduler.get_stats()
|
|
89
|
+
print("\n📊 Final Statistics:")
|
|
90
|
+
print(f" Total Executions: {stats['total_executions']}")
|
|
91
|
+
print(f" Successful: {stats['successful_executions']}")
|
|
92
|
+
print(f" Failed: {stats['failed_executions']}")
|
|
93
|
+
print(f" Success Rate: {stats['success_rate']:.1f}%")
|
|
94
|
+
print("\n✅ Agent stopped successfully\n")
|
|
95
|
+
|
|
96
|
+
return 0
|
|
97
|
+
|
|
98
|
+
except FileNotFoundError as e:
|
|
99
|
+
print(f"❌ Error: {e}")
|
|
100
|
+
print(f"\nMake sure {yaml_path} exists in the current directory.")
|
|
101
|
+
print("\nExample agents.yaml structure:")
|
|
102
|
+
print("""
|
|
103
|
+
framework: praisonai
|
|
104
|
+
|
|
105
|
+
agents:
|
|
106
|
+
- name: "AI News Monitor"
|
|
107
|
+
role: "News Analyst"
|
|
108
|
+
instructions: "Search and summarize AI news"
|
|
109
|
+
tools:
|
|
110
|
+
- search_tool
|
|
111
|
+
|
|
112
|
+
task: "Search for latest AI news"
|
|
113
|
+
|
|
114
|
+
schedule:
|
|
115
|
+
interval: "hourly"
|
|
116
|
+
max_retries: 3
|
|
117
|
+
run_immediately: true
|
|
118
|
+
""")
|
|
119
|
+
return 1
|
|
120
|
+
|
|
121
|
+
except ValueError as e:
|
|
122
|
+
print(f"❌ Configuration Error: {e}")
|
|
123
|
+
return 1
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
print(f"❌ Error: {e}")
|
|
127
|
+
if verbose:
|
|
128
|
+
import traceback
|
|
129
|
+
traceback.print_exc()
|
|
130
|
+
return 1
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def add_schedule_arguments(subparsers):
|
|
134
|
+
"""
|
|
135
|
+
Add schedule subcommand and arguments to parser.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
subparsers: Subparsers object from argparse
|
|
139
|
+
"""
|
|
140
|
+
schedule_parser = subparsers.add_parser(
|
|
141
|
+
'schedule',
|
|
142
|
+
help='Schedule an agent to run continuously at regular intervals'
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
schedule_parser.add_argument(
|
|
146
|
+
'schedule_yaml',
|
|
147
|
+
nargs='?',
|
|
148
|
+
default='agents.yaml',
|
|
149
|
+
help='Path to agents.yaml file (default: agents.yaml)'
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
schedule_parser.add_argument(
|
|
153
|
+
'--interval',
|
|
154
|
+
dest='schedule_interval',
|
|
155
|
+
type=str,
|
|
156
|
+
help='Override schedule interval (e.g., "hourly", "*/30m", "daily")'
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
schedule_parser.add_argument(
|
|
160
|
+
'--max-retries',
|
|
161
|
+
dest='schedule_max_retries',
|
|
162
|
+
type=int,
|
|
163
|
+
help='Override maximum retry attempts (default: from YAML or 3)'
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
schedule_parser.add_argument(
|
|
167
|
+
'--verbose', '-v',
|
|
168
|
+
action='store_true',
|
|
169
|
+
help='Enable verbose logging'
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
schedule_parser.set_defaults(func=AgentSchedulerHandler.handle_schedule_command)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def setup_scheduler_cli(subparsers):
|
|
176
|
+
"""
|
|
177
|
+
Setup scheduler CLI commands.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
subparsers: Subparsers object from argparse
|
|
181
|
+
"""
|
|
182
|
+
AgentSchedulerHandler.add_schedule_arguments(subparsers)
|
|
@@ -223,7 +223,12 @@ class PraisonAI:
|
|
|
223
223
|
file_input = self.read_file_if_provided(getattr(args, 'file', None))
|
|
224
224
|
|
|
225
225
|
if args.command:
|
|
226
|
-
|
|
226
|
+
# Handle schedule command
|
|
227
|
+
if args.command == "schedule":
|
|
228
|
+
from praisonai.cli.features.agent_scheduler import AgentSchedulerHandler
|
|
229
|
+
exit_code = AgentSchedulerHandler.handle_schedule_command(args)
|
|
230
|
+
sys.exit(exit_code)
|
|
231
|
+
elif args.command.startswith("tests.test") or args.command.startswith("tests/test"): # Argument used for testing purposes
|
|
227
232
|
print("test")
|
|
228
233
|
return "test"
|
|
229
234
|
else:
|
|
@@ -710,6 +715,10 @@ class PraisonAI:
|
|
|
710
715
|
parser.add_argument("--external-agent", type=str, choices=["claude", "gemini", "codex", "cursor"],
|
|
711
716
|
help="Use external AI CLI tool (claude, gemini, codex, cursor)")
|
|
712
717
|
|
|
718
|
+
# Agent Scheduler - for schedule command
|
|
719
|
+
parser.add_argument("--interval", dest="schedule_interval", type=str, help="Schedule interval (e.g., 'hourly', '*/30m', 'daily')")
|
|
720
|
+
parser.add_argument("--max-retries", dest="schedule_max_retries", type=int, help="Maximum retry attempts for scheduled execution")
|
|
721
|
+
|
|
713
722
|
# If we're in a test environment, parse with empty args to avoid pytest interference
|
|
714
723
|
if in_test_env:
|
|
715
724
|
args, unknown_args = parser.parse_known_args([])
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple CLI entry point for praisonai schedule command.
|
|
3
|
+
|
|
4
|
+
This provides a standalone entry point that can be called from main.py
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from praisonai.cli.features.agent_scheduler import AgentSchedulerHandler
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
"""Main entry point for schedule CLI command."""
|
|
13
|
+
import argparse
|
|
14
|
+
|
|
15
|
+
parser = argparse.ArgumentParser(
|
|
16
|
+
description='Schedule an agent to run continuously at regular intervals'
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
'schedule_yaml',
|
|
21
|
+
nargs='?',
|
|
22
|
+
default='agents.yaml',
|
|
23
|
+
help='Path to agents.yaml file (default: agents.yaml)'
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
'--interval',
|
|
28
|
+
dest='schedule_interval',
|
|
29
|
+
type=str,
|
|
30
|
+
help='Override schedule interval (e.g., "hourly", "*/30m", "daily")'
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
'--max-retries',
|
|
35
|
+
dest='schedule_max_retries',
|
|
36
|
+
type=int,
|
|
37
|
+
help='Override maximum retry attempts (default: from YAML or 3)'
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
'--verbose', '-v',
|
|
42
|
+
action='store_true',
|
|
43
|
+
help='Enable verbose logging'
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
args = parser.parse_args()
|
|
47
|
+
|
|
48
|
+
# Call the handler
|
|
49
|
+
exit_code = AgentSchedulerHandler.handle_schedule_command(args)
|
|
50
|
+
sys.exit(exit_code)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == '__main__':
|
|
54
|
+
main()
|
|
@@ -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.
|
|
60
|
+
file.write("RUN pip install flask praisonai==2.3.65 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
|
|
|
@@ -230,6 +230,103 @@ class AgentScheduler:
|
|
|
230
230
|
except Exception as e:
|
|
231
231
|
logger.error(f"One-time execution failed: {e}")
|
|
232
232
|
raise
|
|
233
|
+
|
|
234
|
+
@classmethod
|
|
235
|
+
def from_yaml(
|
|
236
|
+
cls,
|
|
237
|
+
yaml_path: str,
|
|
238
|
+
interval_override: Optional[str] = None,
|
|
239
|
+
max_retries_override: Optional[int] = None,
|
|
240
|
+
on_success: Optional[Callable] = None,
|
|
241
|
+
on_failure: Optional[Callable] = None
|
|
242
|
+
) -> 'AgentScheduler':
|
|
243
|
+
"""
|
|
244
|
+
Create AgentScheduler from agents.yaml file.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
yaml_path: Path to agents.yaml file
|
|
248
|
+
interval_override: Override schedule interval from YAML
|
|
249
|
+
max_retries_override: Override max_retries from YAML
|
|
250
|
+
on_success: Callback function on successful execution
|
|
251
|
+
on_failure: Callback function on failed execution
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Configured AgentScheduler instance
|
|
255
|
+
|
|
256
|
+
Example:
|
|
257
|
+
scheduler = AgentScheduler.from_yaml("agents.yaml")
|
|
258
|
+
scheduler.start()
|
|
259
|
+
|
|
260
|
+
Example agents.yaml:
|
|
261
|
+
framework: praisonai
|
|
262
|
+
|
|
263
|
+
agents:
|
|
264
|
+
- name: "AI News Monitor"
|
|
265
|
+
role: "News Analyst"
|
|
266
|
+
instructions: "Search and summarize AI news"
|
|
267
|
+
tools:
|
|
268
|
+
- search_tool
|
|
269
|
+
|
|
270
|
+
task: "Search for latest AI news"
|
|
271
|
+
|
|
272
|
+
schedule:
|
|
273
|
+
interval: "hourly"
|
|
274
|
+
max_retries: 3
|
|
275
|
+
run_immediately: true
|
|
276
|
+
"""
|
|
277
|
+
from .yaml_loader import load_agent_yaml_with_schedule, create_agent_from_config
|
|
278
|
+
|
|
279
|
+
# Load configuration from YAML
|
|
280
|
+
agent_config, schedule_config = load_agent_yaml_with_schedule(yaml_path)
|
|
281
|
+
|
|
282
|
+
# Create agent from config
|
|
283
|
+
agent = create_agent_from_config(agent_config)
|
|
284
|
+
|
|
285
|
+
# Get task
|
|
286
|
+
task = agent_config.get('task', '')
|
|
287
|
+
if not task:
|
|
288
|
+
raise ValueError("No task specified in YAML file")
|
|
289
|
+
|
|
290
|
+
# Create scheduler
|
|
291
|
+
scheduler = cls(
|
|
292
|
+
agent=agent,
|
|
293
|
+
task=task,
|
|
294
|
+
config=agent_config,
|
|
295
|
+
on_success=on_success,
|
|
296
|
+
on_failure=on_failure
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Store schedule config for auto-start
|
|
300
|
+
scheduler._yaml_schedule_config = schedule_config
|
|
301
|
+
scheduler._interval_override = interval_override
|
|
302
|
+
scheduler._max_retries_override = max_retries_override
|
|
303
|
+
|
|
304
|
+
return scheduler
|
|
305
|
+
|
|
306
|
+
def start_from_yaml_config(self) -> bool:
|
|
307
|
+
"""
|
|
308
|
+
Start scheduler using configuration from YAML file.
|
|
309
|
+
|
|
310
|
+
Must be called after from_yaml() class method.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
True if scheduler started successfully
|
|
314
|
+
"""
|
|
315
|
+
if not hasattr(self, '_yaml_schedule_config'):
|
|
316
|
+
raise RuntimeError("start_from_yaml_config() can only be called after from_yaml()")
|
|
317
|
+
|
|
318
|
+
schedule_config = self._yaml_schedule_config
|
|
319
|
+
|
|
320
|
+
# Use overrides if provided, otherwise use YAML config
|
|
321
|
+
interval = self._interval_override or schedule_config.get('interval', 'hourly')
|
|
322
|
+
max_retries = self._max_retries_override or schedule_config.get('max_retries', 3)
|
|
323
|
+
run_immediately = schedule_config.get('run_immediately', False)
|
|
324
|
+
|
|
325
|
+
return self.start(
|
|
326
|
+
schedule_expr=interval,
|
|
327
|
+
max_retries=max_retries,
|
|
328
|
+
run_immediately=run_immediately
|
|
329
|
+
)
|
|
233
330
|
|
|
234
331
|
|
|
235
332
|
def create_agent_scheduler(
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""
|
|
2
|
+
YAML loader for agent scheduler configuration.
|
|
3
|
+
|
|
4
|
+
Loads agent and schedule configuration from agents.yaml files.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Dict, Any, Tuple
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_agent_yaml_with_schedule(yaml_path: str) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
16
|
+
"""
|
|
17
|
+
Load agents.yaml file and extract agent and schedule configuration.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
yaml_path: Path to agents.yaml file
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Tuple of (agent_config, schedule_config)
|
|
24
|
+
|
|
25
|
+
Raises:
|
|
26
|
+
FileNotFoundError: If YAML file doesn't exist
|
|
27
|
+
ValueError: If YAML is invalid or missing required fields
|
|
28
|
+
|
|
29
|
+
Example YAML structure:
|
|
30
|
+
framework: praisonai
|
|
31
|
+
|
|
32
|
+
agents:
|
|
33
|
+
- name: "AI News Monitor"
|
|
34
|
+
role: "News Analyst"
|
|
35
|
+
goal: "Monitor AI news"
|
|
36
|
+
instructions: "Search and summarize"
|
|
37
|
+
tools:
|
|
38
|
+
- search_tool
|
|
39
|
+
verbose: true
|
|
40
|
+
|
|
41
|
+
task: "Search for latest AI news"
|
|
42
|
+
|
|
43
|
+
schedule:
|
|
44
|
+
interval: "hourly"
|
|
45
|
+
max_retries: 3
|
|
46
|
+
run_immediately: true
|
|
47
|
+
"""
|
|
48
|
+
yaml_path = Path(yaml_path)
|
|
49
|
+
|
|
50
|
+
if not yaml_path.exists():
|
|
51
|
+
raise FileNotFoundError(f"YAML file not found: {yaml_path}")
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
with open(yaml_path, 'r') as f:
|
|
55
|
+
config = yaml.safe_load(f)
|
|
56
|
+
except yaml.YAMLError as e:
|
|
57
|
+
raise ValueError(f"Invalid YAML file: {e}")
|
|
58
|
+
|
|
59
|
+
if not config:
|
|
60
|
+
raise ValueError("Empty YAML file")
|
|
61
|
+
|
|
62
|
+
# Extract agent configuration
|
|
63
|
+
agent_config = {}
|
|
64
|
+
|
|
65
|
+
# Get agents list (can be single agent or multiple)
|
|
66
|
+
agents = config.get('agents', [])
|
|
67
|
+
if not agents:
|
|
68
|
+
raise ValueError("No agents defined in YAML file")
|
|
69
|
+
|
|
70
|
+
# Use first agent for scheduling (can be extended for multi-agent later)
|
|
71
|
+
if isinstance(agents, list):
|
|
72
|
+
agent_config = agents[0]
|
|
73
|
+
else:
|
|
74
|
+
agent_config = agents
|
|
75
|
+
|
|
76
|
+
# Get task
|
|
77
|
+
task = config.get('task', '')
|
|
78
|
+
if not task:
|
|
79
|
+
# Try to get from agent's tasks
|
|
80
|
+
if 'tasks' in agent_config and agent_config['tasks']:
|
|
81
|
+
first_task = list(agent_config['tasks'].values())[0]
|
|
82
|
+
task = first_task.get('description', '')
|
|
83
|
+
|
|
84
|
+
agent_config['task'] = task
|
|
85
|
+
|
|
86
|
+
# Get framework (default to praisonai)
|
|
87
|
+
agent_config['framework'] = config.get('framework', 'praisonai')
|
|
88
|
+
|
|
89
|
+
# Extract schedule configuration (optional)
|
|
90
|
+
schedule_config = config.get('schedule', {})
|
|
91
|
+
|
|
92
|
+
# Set defaults for schedule if not provided
|
|
93
|
+
if not schedule_config:
|
|
94
|
+
schedule_config = {
|
|
95
|
+
'interval': 'hourly',
|
|
96
|
+
'max_retries': 3,
|
|
97
|
+
'run_immediately': False
|
|
98
|
+
}
|
|
99
|
+
else:
|
|
100
|
+
# Ensure required fields have defaults
|
|
101
|
+
schedule_config.setdefault('interval', 'hourly')
|
|
102
|
+
schedule_config.setdefault('max_retries', 3)
|
|
103
|
+
schedule_config.setdefault('run_immediately', False)
|
|
104
|
+
|
|
105
|
+
logger.info(f"Loaded agent '{agent_config.get('name', 'Unknown')}' with schedule interval '{schedule_config['interval']}'")
|
|
106
|
+
|
|
107
|
+
return agent_config, schedule_config
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def create_agent_from_config(agent_config: Dict[str, Any]) -> Any:
|
|
111
|
+
"""
|
|
112
|
+
Create a PraisonAI Agent instance from configuration.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
agent_config: Agent configuration dictionary
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Agent instance
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
ImportError: If praisonaiagents is not installed
|
|
122
|
+
"""
|
|
123
|
+
try:
|
|
124
|
+
from praisonaiagents import Agent
|
|
125
|
+
except ImportError:
|
|
126
|
+
raise ImportError("praisonaiagents package is required. Install with: pip install praisonaiagents")
|
|
127
|
+
|
|
128
|
+
# Extract agent parameters
|
|
129
|
+
name = agent_config.get('name', 'Scheduled Agent')
|
|
130
|
+
role = agent_config.get('role', '')
|
|
131
|
+
goal = agent_config.get('goal', '')
|
|
132
|
+
instructions = agent_config.get('instructions', agent_config.get('backstory', ''))
|
|
133
|
+
verbose = agent_config.get('verbose', False)
|
|
134
|
+
|
|
135
|
+
# Handle tools
|
|
136
|
+
tools = []
|
|
137
|
+
tool_names = agent_config.get('tools', [])
|
|
138
|
+
|
|
139
|
+
if tool_names:
|
|
140
|
+
# Try to import tools
|
|
141
|
+
for tool_name in tool_names:
|
|
142
|
+
try:
|
|
143
|
+
# Try common tool imports
|
|
144
|
+
if tool_name == 'search_tool' or tool_name == 'InternetSearchTool':
|
|
145
|
+
try:
|
|
146
|
+
from tools import search_tool
|
|
147
|
+
tools.append(search_tool)
|
|
148
|
+
except ImportError:
|
|
149
|
+
logger.warning(f"Could not import {tool_name}, skipping")
|
|
150
|
+
# Add more tool imports as needed
|
|
151
|
+
except Exception as e:
|
|
152
|
+
logger.warning(f"Error loading tool {tool_name}: {e}")
|
|
153
|
+
|
|
154
|
+
# Create agent
|
|
155
|
+
agent = Agent(
|
|
156
|
+
name=name,
|
|
157
|
+
role=role,
|
|
158
|
+
goal=goal,
|
|
159
|
+
instructions=instructions,
|
|
160
|
+
tools=tools,
|
|
161
|
+
verbose=verbose
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return agent
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def validate_schedule_config(schedule_config: Dict[str, Any]) -> None:
|
|
168
|
+
"""
|
|
169
|
+
Validate schedule configuration.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
schedule_config: Schedule configuration dictionary
|
|
173
|
+
|
|
174
|
+
Raises:
|
|
175
|
+
ValueError: If configuration is invalid
|
|
176
|
+
"""
|
|
177
|
+
required_fields = ['interval']
|
|
178
|
+
for field in required_fields:
|
|
179
|
+
if field not in schedule_config:
|
|
180
|
+
raise ValueError(f"Missing required schedule field: {field}")
|
|
181
|
+
|
|
182
|
+
# Validate interval format
|
|
183
|
+
interval = schedule_config['interval']
|
|
184
|
+
valid_intervals = ['hourly', 'daily']
|
|
185
|
+
|
|
186
|
+
if interval not in valid_intervals:
|
|
187
|
+
# Check if it's a custom format (*/Nm, */Nh, */Ns, or plain number)
|
|
188
|
+
if not (interval.startswith('*/') or interval.isdigit()):
|
|
189
|
+
raise ValueError(
|
|
190
|
+
f"Invalid interval format: {interval}. "
|
|
191
|
+
f"Use 'hourly', 'daily', '*/30m', '*/6h', or seconds as number"
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Validate max_retries
|
|
195
|
+
max_retries = schedule_config.get('max_retries', 3)
|
|
196
|
+
if not isinstance(max_retries, int) or max_retries < 0:
|
|
197
|
+
raise ValueError(f"max_retries must be a non-negative integer, got: {max_retries}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.3.65"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.3.64"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|