PraisonAI 3.0.0__py3-none-any.whl
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/__init__.py +54 -0
- praisonai/__main__.py +15 -0
- praisonai/acp/__init__.py +54 -0
- praisonai/acp/config.py +159 -0
- praisonai/acp/server.py +587 -0
- praisonai/acp/session.py +219 -0
- praisonai/adapters/__init__.py +50 -0
- praisonai/adapters/readers.py +395 -0
- praisonai/adapters/rerankers.py +315 -0
- praisonai/adapters/retrievers.py +394 -0
- praisonai/adapters/vector_stores.py +409 -0
- praisonai/agent_scheduler.py +337 -0
- praisonai/agents_generator.py +903 -0
- praisonai/api/call.py +292 -0
- praisonai/auto.py +1197 -0
- praisonai/capabilities/__init__.py +275 -0
- praisonai/capabilities/a2a.py +140 -0
- praisonai/capabilities/assistants.py +283 -0
- praisonai/capabilities/audio.py +320 -0
- praisonai/capabilities/batches.py +469 -0
- praisonai/capabilities/completions.py +336 -0
- praisonai/capabilities/container_files.py +155 -0
- praisonai/capabilities/containers.py +93 -0
- praisonai/capabilities/embeddings.py +158 -0
- praisonai/capabilities/files.py +467 -0
- praisonai/capabilities/fine_tuning.py +293 -0
- praisonai/capabilities/guardrails.py +182 -0
- praisonai/capabilities/images.py +330 -0
- praisonai/capabilities/mcp.py +190 -0
- praisonai/capabilities/messages.py +270 -0
- praisonai/capabilities/moderations.py +154 -0
- praisonai/capabilities/ocr.py +217 -0
- praisonai/capabilities/passthrough.py +204 -0
- praisonai/capabilities/rag.py +207 -0
- praisonai/capabilities/realtime.py +160 -0
- praisonai/capabilities/rerank.py +165 -0
- praisonai/capabilities/responses.py +266 -0
- praisonai/capabilities/search.py +109 -0
- praisonai/capabilities/skills.py +133 -0
- praisonai/capabilities/vector_store_files.py +334 -0
- praisonai/capabilities/vector_stores.py +304 -0
- praisonai/capabilities/videos.py +141 -0
- praisonai/chainlit_ui.py +304 -0
- praisonai/chat/__init__.py +106 -0
- praisonai/chat/app.py +125 -0
- praisonai/cli/__init__.py +26 -0
- praisonai/cli/app.py +213 -0
- praisonai/cli/commands/__init__.py +75 -0
- praisonai/cli/commands/acp.py +70 -0
- praisonai/cli/commands/completion.py +333 -0
- praisonai/cli/commands/config.py +166 -0
- praisonai/cli/commands/debug.py +142 -0
- praisonai/cli/commands/diag.py +55 -0
- praisonai/cli/commands/doctor.py +166 -0
- praisonai/cli/commands/environment.py +179 -0
- praisonai/cli/commands/lsp.py +112 -0
- praisonai/cli/commands/mcp.py +210 -0
- praisonai/cli/commands/profile.py +457 -0
- praisonai/cli/commands/run.py +228 -0
- praisonai/cli/commands/schedule.py +150 -0
- praisonai/cli/commands/serve.py +97 -0
- praisonai/cli/commands/session.py +212 -0
- praisonai/cli/commands/traces.py +145 -0
- praisonai/cli/commands/version.py +101 -0
- praisonai/cli/configuration/__init__.py +18 -0
- praisonai/cli/configuration/loader.py +353 -0
- praisonai/cli/configuration/paths.py +114 -0
- praisonai/cli/configuration/schema.py +164 -0
- praisonai/cli/features/__init__.py +268 -0
- praisonai/cli/features/acp.py +236 -0
- praisonai/cli/features/action_orchestrator.py +546 -0
- praisonai/cli/features/agent_scheduler.py +773 -0
- praisonai/cli/features/agent_tools.py +474 -0
- praisonai/cli/features/agents.py +375 -0
- praisonai/cli/features/at_mentions.py +471 -0
- praisonai/cli/features/auto_memory.py +182 -0
- praisonai/cli/features/autonomy_mode.py +490 -0
- praisonai/cli/features/background.py +356 -0
- praisonai/cli/features/base.py +168 -0
- praisonai/cli/features/capabilities.py +1326 -0
- praisonai/cli/features/checkpoints.py +338 -0
- praisonai/cli/features/code_intelligence.py +652 -0
- praisonai/cli/features/compaction.py +294 -0
- praisonai/cli/features/compare.py +534 -0
- praisonai/cli/features/cost_tracker.py +514 -0
- praisonai/cli/features/debug.py +810 -0
- praisonai/cli/features/deploy.py +517 -0
- praisonai/cli/features/diag.py +289 -0
- praisonai/cli/features/doctor/__init__.py +63 -0
- praisonai/cli/features/doctor/checks/__init__.py +24 -0
- praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
- praisonai/cli/features/doctor/checks/config_checks.py +366 -0
- praisonai/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai/cli/features/doctor/checks/env_checks.py +543 -0
- praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
- praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
- praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
- praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai/cli/features/doctor/engine.py +266 -0
- praisonai/cli/features/doctor/formatters.py +310 -0
- praisonai/cli/features/doctor/handler.py +397 -0
- praisonai/cli/features/doctor/models.py +264 -0
- praisonai/cli/features/doctor/registry.py +239 -0
- praisonai/cli/features/endpoints.py +1019 -0
- praisonai/cli/features/eval.py +560 -0
- praisonai/cli/features/external_agents.py +231 -0
- praisonai/cli/features/fast_context.py +410 -0
- praisonai/cli/features/flow_display.py +566 -0
- praisonai/cli/features/git_integration.py +651 -0
- praisonai/cli/features/guardrail.py +171 -0
- praisonai/cli/features/handoff.py +185 -0
- praisonai/cli/features/hooks.py +583 -0
- praisonai/cli/features/image.py +384 -0
- praisonai/cli/features/interactive_runtime.py +585 -0
- praisonai/cli/features/interactive_tools.py +380 -0
- praisonai/cli/features/interactive_tui.py +603 -0
- praisonai/cli/features/jobs.py +632 -0
- praisonai/cli/features/knowledge.py +531 -0
- praisonai/cli/features/lite.py +244 -0
- praisonai/cli/features/lsp_cli.py +225 -0
- praisonai/cli/features/mcp.py +169 -0
- praisonai/cli/features/message_queue.py +587 -0
- praisonai/cli/features/metrics.py +211 -0
- praisonai/cli/features/n8n.py +673 -0
- praisonai/cli/features/observability.py +293 -0
- praisonai/cli/features/ollama.py +361 -0
- praisonai/cli/features/output_style.py +273 -0
- praisonai/cli/features/package.py +631 -0
- praisonai/cli/features/performance.py +308 -0
- praisonai/cli/features/persistence.py +636 -0
- praisonai/cli/features/profile.py +226 -0
- praisonai/cli/features/profiler/__init__.py +81 -0
- praisonai/cli/features/profiler/core.py +558 -0
- praisonai/cli/features/profiler/optimizations.py +652 -0
- praisonai/cli/features/profiler/suite.py +386 -0
- praisonai/cli/features/profiling.py +350 -0
- praisonai/cli/features/queue/__init__.py +73 -0
- praisonai/cli/features/queue/manager.py +395 -0
- praisonai/cli/features/queue/models.py +286 -0
- praisonai/cli/features/queue/persistence.py +564 -0
- praisonai/cli/features/queue/scheduler.py +484 -0
- praisonai/cli/features/queue/worker.py +372 -0
- praisonai/cli/features/recipe.py +1723 -0
- praisonai/cli/features/recipes.py +449 -0
- praisonai/cli/features/registry.py +229 -0
- praisonai/cli/features/repo_map.py +860 -0
- praisonai/cli/features/router.py +466 -0
- praisonai/cli/features/sandbox_executor.py +515 -0
- praisonai/cli/features/serve.py +829 -0
- praisonai/cli/features/session.py +222 -0
- praisonai/cli/features/skills.py +856 -0
- praisonai/cli/features/slash_commands.py +650 -0
- praisonai/cli/features/telemetry.py +179 -0
- praisonai/cli/features/templates.py +1384 -0
- praisonai/cli/features/thinking.py +305 -0
- praisonai/cli/features/todo.py +334 -0
- praisonai/cli/features/tools.py +680 -0
- praisonai/cli/features/tui/__init__.py +83 -0
- praisonai/cli/features/tui/app.py +580 -0
- praisonai/cli/features/tui/cli.py +566 -0
- praisonai/cli/features/tui/debug.py +511 -0
- praisonai/cli/features/tui/events.py +99 -0
- praisonai/cli/features/tui/mock_provider.py +328 -0
- praisonai/cli/features/tui/orchestrator.py +652 -0
- praisonai/cli/features/tui/screens/__init__.py +50 -0
- praisonai/cli/features/tui/screens/main.py +245 -0
- praisonai/cli/features/tui/screens/queue.py +174 -0
- praisonai/cli/features/tui/screens/session.py +124 -0
- praisonai/cli/features/tui/screens/settings.py +148 -0
- praisonai/cli/features/tui/widgets/__init__.py +56 -0
- praisonai/cli/features/tui/widgets/chat.py +261 -0
- praisonai/cli/features/tui/widgets/composer.py +224 -0
- praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
- praisonai/cli/features/tui/widgets/status.py +167 -0
- praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
- praisonai/cli/features/workflow.py +720 -0
- praisonai/cli/legacy.py +236 -0
- praisonai/cli/main.py +5559 -0
- praisonai/cli/schedule_cli.py +54 -0
- praisonai/cli/state/__init__.py +31 -0
- praisonai/cli/state/identifiers.py +161 -0
- praisonai/cli/state/sessions.py +313 -0
- praisonai/code/__init__.py +93 -0
- praisonai/code/agent_tools.py +344 -0
- praisonai/code/diff/__init__.py +21 -0
- praisonai/code/diff/diff_strategy.py +432 -0
- praisonai/code/tools/__init__.py +27 -0
- praisonai/code/tools/apply_diff.py +221 -0
- praisonai/code/tools/execute_command.py +275 -0
- praisonai/code/tools/list_files.py +274 -0
- praisonai/code/tools/read_file.py +206 -0
- praisonai/code/tools/search_replace.py +248 -0
- praisonai/code/tools/write_file.py +217 -0
- praisonai/code/utils/__init__.py +46 -0
- praisonai/code/utils/file_utils.py +307 -0
- praisonai/code/utils/ignore_utils.py +308 -0
- praisonai/code/utils/text_utils.py +276 -0
- praisonai/db/__init__.py +64 -0
- praisonai/db/adapter.py +531 -0
- praisonai/deploy/__init__.py +62 -0
- praisonai/deploy/api.py +231 -0
- praisonai/deploy/docker.py +454 -0
- praisonai/deploy/doctor.py +367 -0
- praisonai/deploy/main.py +327 -0
- praisonai/deploy/models.py +179 -0
- praisonai/deploy/providers/__init__.py +33 -0
- praisonai/deploy/providers/aws.py +331 -0
- praisonai/deploy/providers/azure.py +358 -0
- praisonai/deploy/providers/base.py +101 -0
- praisonai/deploy/providers/gcp.py +314 -0
- praisonai/deploy/schema.py +208 -0
- praisonai/deploy.py +185 -0
- praisonai/endpoints/__init__.py +53 -0
- praisonai/endpoints/a2u_server.py +410 -0
- praisonai/endpoints/discovery.py +165 -0
- praisonai/endpoints/providers/__init__.py +28 -0
- praisonai/endpoints/providers/a2a.py +253 -0
- praisonai/endpoints/providers/a2u.py +208 -0
- praisonai/endpoints/providers/agents_api.py +171 -0
- praisonai/endpoints/providers/base.py +231 -0
- praisonai/endpoints/providers/mcp.py +263 -0
- praisonai/endpoints/providers/recipe.py +206 -0
- praisonai/endpoints/providers/tools_mcp.py +150 -0
- praisonai/endpoints/registry.py +131 -0
- praisonai/endpoints/server.py +161 -0
- praisonai/inbuilt_tools/__init__.py +24 -0
- praisonai/inbuilt_tools/autogen_tools.py +117 -0
- praisonai/inc/__init__.py +2 -0
- praisonai/inc/config.py +96 -0
- praisonai/inc/models.py +155 -0
- praisonai/integrations/__init__.py +56 -0
- praisonai/integrations/base.py +303 -0
- praisonai/integrations/claude_code.py +270 -0
- praisonai/integrations/codex_cli.py +255 -0
- praisonai/integrations/cursor_cli.py +195 -0
- praisonai/integrations/gemini_cli.py +222 -0
- praisonai/jobs/__init__.py +67 -0
- praisonai/jobs/executor.py +425 -0
- praisonai/jobs/models.py +230 -0
- praisonai/jobs/router.py +314 -0
- praisonai/jobs/server.py +186 -0
- praisonai/jobs/store.py +203 -0
- praisonai/llm/__init__.py +66 -0
- praisonai/llm/registry.py +382 -0
- praisonai/mcp_server/__init__.py +152 -0
- praisonai/mcp_server/adapters/__init__.py +74 -0
- praisonai/mcp_server/adapters/agents.py +128 -0
- praisonai/mcp_server/adapters/capabilities.py +168 -0
- praisonai/mcp_server/adapters/cli_tools.py +568 -0
- praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
- praisonai/mcp_server/adapters/knowledge.py +93 -0
- praisonai/mcp_server/adapters/memory.py +104 -0
- praisonai/mcp_server/adapters/prompts.py +306 -0
- praisonai/mcp_server/adapters/resources.py +124 -0
- praisonai/mcp_server/adapters/tools_bridge.py +280 -0
- praisonai/mcp_server/auth/__init__.py +48 -0
- praisonai/mcp_server/auth/api_key.py +291 -0
- praisonai/mcp_server/auth/oauth.py +460 -0
- praisonai/mcp_server/auth/oidc.py +289 -0
- praisonai/mcp_server/auth/scopes.py +260 -0
- praisonai/mcp_server/cli.py +852 -0
- praisonai/mcp_server/elicitation.py +445 -0
- praisonai/mcp_server/icons.py +302 -0
- praisonai/mcp_server/recipe_adapter.py +573 -0
- praisonai/mcp_server/recipe_cli.py +824 -0
- praisonai/mcp_server/registry.py +703 -0
- praisonai/mcp_server/sampling.py +422 -0
- praisonai/mcp_server/server.py +490 -0
- praisonai/mcp_server/tasks.py +443 -0
- praisonai/mcp_server/transports/__init__.py +18 -0
- praisonai/mcp_server/transports/http_stream.py +376 -0
- praisonai/mcp_server/transports/stdio.py +132 -0
- praisonai/persistence/__init__.py +84 -0
- praisonai/persistence/config.py +238 -0
- praisonai/persistence/conversation/__init__.py +25 -0
- praisonai/persistence/conversation/async_mysql.py +427 -0
- praisonai/persistence/conversation/async_postgres.py +410 -0
- praisonai/persistence/conversation/async_sqlite.py +371 -0
- praisonai/persistence/conversation/base.py +151 -0
- praisonai/persistence/conversation/json_store.py +250 -0
- praisonai/persistence/conversation/mysql.py +387 -0
- praisonai/persistence/conversation/postgres.py +401 -0
- praisonai/persistence/conversation/singlestore.py +240 -0
- praisonai/persistence/conversation/sqlite.py +341 -0
- praisonai/persistence/conversation/supabase.py +203 -0
- praisonai/persistence/conversation/surrealdb.py +287 -0
- praisonai/persistence/factory.py +301 -0
- praisonai/persistence/hooks/__init__.py +18 -0
- praisonai/persistence/hooks/agent_hooks.py +297 -0
- praisonai/persistence/knowledge/__init__.py +26 -0
- praisonai/persistence/knowledge/base.py +144 -0
- praisonai/persistence/knowledge/cassandra.py +232 -0
- praisonai/persistence/knowledge/chroma.py +295 -0
- praisonai/persistence/knowledge/clickhouse.py +242 -0
- praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
- praisonai/persistence/knowledge/couchbase.py +286 -0
- praisonai/persistence/knowledge/lancedb.py +216 -0
- praisonai/persistence/knowledge/langchain_adapter.py +291 -0
- praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
- praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
- praisonai/persistence/knowledge/milvus.py +277 -0
- praisonai/persistence/knowledge/mongodb_vector.py +306 -0
- praisonai/persistence/knowledge/pgvector.py +335 -0
- praisonai/persistence/knowledge/pinecone.py +253 -0
- praisonai/persistence/knowledge/qdrant.py +301 -0
- praisonai/persistence/knowledge/redis_vector.py +291 -0
- praisonai/persistence/knowledge/singlestore_vector.py +299 -0
- praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
- praisonai/persistence/knowledge/upstash_vector.py +266 -0
- praisonai/persistence/knowledge/weaviate.py +223 -0
- praisonai/persistence/migrations/__init__.py +10 -0
- praisonai/persistence/migrations/manager.py +251 -0
- praisonai/persistence/orchestrator.py +406 -0
- praisonai/persistence/state/__init__.py +21 -0
- praisonai/persistence/state/async_mongodb.py +200 -0
- praisonai/persistence/state/base.py +107 -0
- praisonai/persistence/state/dynamodb.py +226 -0
- praisonai/persistence/state/firestore.py +175 -0
- praisonai/persistence/state/gcs.py +155 -0
- praisonai/persistence/state/memory.py +245 -0
- praisonai/persistence/state/mongodb.py +158 -0
- praisonai/persistence/state/redis.py +190 -0
- praisonai/persistence/state/upstash.py +144 -0
- praisonai/persistence/tests/__init__.py +3 -0
- praisonai/persistence/tests/test_all_backends.py +633 -0
- praisonai/profiler.py +1214 -0
- praisonai/recipe/__init__.py +134 -0
- praisonai/recipe/bridge.py +278 -0
- praisonai/recipe/core.py +893 -0
- praisonai/recipe/exceptions.py +54 -0
- praisonai/recipe/history.py +402 -0
- praisonai/recipe/models.py +266 -0
- praisonai/recipe/operations.py +440 -0
- praisonai/recipe/policy.py +422 -0
- praisonai/recipe/registry.py +849 -0
- praisonai/recipe/runtime.py +214 -0
- praisonai/recipe/security.py +711 -0
- praisonai/recipe/serve.py +859 -0
- praisonai/recipe/server.py +613 -0
- praisonai/scheduler/__init__.py +45 -0
- praisonai/scheduler/agent_scheduler.py +552 -0
- praisonai/scheduler/base.py +124 -0
- praisonai/scheduler/daemon_manager.py +225 -0
- praisonai/scheduler/state_manager.py +155 -0
- praisonai/scheduler/yaml_loader.py +193 -0
- praisonai/scheduler.py +194 -0
- praisonai/setup/__init__.py +1 -0
- praisonai/setup/build.py +21 -0
- praisonai/setup/post_install.py +23 -0
- praisonai/setup/setup_conda_env.py +25 -0
- praisonai/setup.py +16 -0
- praisonai/templates/__init__.py +116 -0
- praisonai/templates/cache.py +364 -0
- praisonai/templates/dependency_checker.py +358 -0
- praisonai/templates/discovery.py +391 -0
- praisonai/templates/loader.py +564 -0
- praisonai/templates/registry.py +511 -0
- praisonai/templates/resolver.py +206 -0
- praisonai/templates/security.py +327 -0
- praisonai/templates/tool_override.py +498 -0
- praisonai/templates/tools_doctor.py +256 -0
- praisonai/test.py +105 -0
- praisonai/train.py +562 -0
- praisonai/train_vision.py +306 -0
- praisonai/ui/agents.py +824 -0
- praisonai/ui/callbacks.py +57 -0
- praisonai/ui/chainlit_compat.py +246 -0
- praisonai/ui/chat.py +532 -0
- praisonai/ui/code.py +717 -0
- praisonai/ui/colab.py +474 -0
- praisonai/ui/colab_chainlit.py +81 -0
- praisonai/ui/components/aicoder.py +284 -0
- praisonai/ui/context.py +283 -0
- praisonai/ui/database_config.py +56 -0
- praisonai/ui/db.py +294 -0
- praisonai/ui/realtime.py +488 -0
- praisonai/ui/realtimeclient/__init__.py +756 -0
- praisonai/ui/realtimeclient/tools.py +242 -0
- praisonai/ui/sql_alchemy.py +710 -0
- praisonai/upload_vision.py +140 -0
- praisonai/version.py +1 -0
- praisonai-3.0.0.dist-info/METADATA +3493 -0
- praisonai-3.0.0.dist-info/RECORD +393 -0
- praisonai-3.0.0.dist-info/WHEEL +5 -0
- praisonai-3.0.0.dist-info/entry_points.txt +4 -0
- praisonai-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent Scheduler for PraisonAI - Run agents periodically 24/7.
|
|
3
|
+
|
|
4
|
+
This module provides scheduling capabilities for running PraisonAI agents
|
|
5
|
+
at regular intervals, enabling 24/7 autonomous agent operations.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
# Run news checker every hour
|
|
9
|
+
from praisonai.agent_scheduler import AgentScheduler
|
|
10
|
+
from praisonai_agents import Agent
|
|
11
|
+
|
|
12
|
+
agent = Agent(
|
|
13
|
+
name="NewsChecker",
|
|
14
|
+
instructions="Check latest AI news and summarize",
|
|
15
|
+
tools=[search_tool]
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
scheduler = AgentScheduler(agent, task="Check latest AI news")
|
|
19
|
+
scheduler.start(schedule_expr="hourly")
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import threading
|
|
23
|
+
import time
|
|
24
|
+
import logging
|
|
25
|
+
from datetime import datetime
|
|
26
|
+
from typing import Optional, Dict, Any, Callable
|
|
27
|
+
from abc import ABC, abstractmethod
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ScheduleParser:
|
|
33
|
+
"""Parse schedule expressions into intervals."""
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def parse(schedule_expr: str) -> int:
|
|
37
|
+
"""
|
|
38
|
+
Parse schedule expression and return interval in seconds.
|
|
39
|
+
|
|
40
|
+
Supported formats:
|
|
41
|
+
- "daily" -> 86400 seconds
|
|
42
|
+
- "hourly" -> 3600 seconds
|
|
43
|
+
- "*/30m" -> 1800 seconds (every 30 minutes)
|
|
44
|
+
- "*/1h" -> 3600 seconds (every 1 hour)
|
|
45
|
+
- "60" -> 60 seconds (plain number)
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
schedule_expr: Schedule expression string
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Interval in seconds
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
ValueError: If schedule format is not supported
|
|
55
|
+
"""
|
|
56
|
+
schedule_expr = schedule_expr.strip().lower()
|
|
57
|
+
|
|
58
|
+
if schedule_expr == "daily":
|
|
59
|
+
return 86400
|
|
60
|
+
elif schedule_expr == "hourly":
|
|
61
|
+
return 3600
|
|
62
|
+
elif schedule_expr.isdigit():
|
|
63
|
+
return int(schedule_expr)
|
|
64
|
+
elif schedule_expr.startswith("*/"):
|
|
65
|
+
interval_part = schedule_expr[2:]
|
|
66
|
+
if interval_part.endswith("m"):
|
|
67
|
+
minutes = int(interval_part[:-1])
|
|
68
|
+
return minutes * 60
|
|
69
|
+
elif interval_part.endswith("h"):
|
|
70
|
+
hours = int(interval_part[:-1])
|
|
71
|
+
return hours * 3600
|
|
72
|
+
elif interval_part.endswith("s"):
|
|
73
|
+
return int(interval_part[:-1])
|
|
74
|
+
else:
|
|
75
|
+
return int(interval_part)
|
|
76
|
+
else:
|
|
77
|
+
raise ValueError(f"Unsupported schedule format: {schedule_expr}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class AgentExecutorInterface(ABC):
|
|
81
|
+
"""Abstract interface for agent execution."""
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def execute(self, task: str) -> Any:
|
|
85
|
+
"""Execute the agent with given task."""
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class PraisonAgentExecutor(AgentExecutorInterface):
|
|
90
|
+
"""Executor for PraisonAI agents."""
|
|
91
|
+
|
|
92
|
+
def __init__(self, agent):
|
|
93
|
+
"""
|
|
94
|
+
Initialize executor with a PraisonAI agent.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
agent: PraisonAI Agent instance
|
|
98
|
+
"""
|
|
99
|
+
self.agent = agent
|
|
100
|
+
|
|
101
|
+
def execute(self, task: str) -> Any:
|
|
102
|
+
"""
|
|
103
|
+
Execute the agent with given task.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
task: Task description for the agent
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Agent execution result
|
|
110
|
+
"""
|
|
111
|
+
try:
|
|
112
|
+
result = self.agent.start(task)
|
|
113
|
+
return result
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.error(f"Agent execution failed: {e}")
|
|
116
|
+
raise
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class AgentScheduler:
|
|
120
|
+
"""
|
|
121
|
+
Scheduler for running PraisonAI agents periodically.
|
|
122
|
+
|
|
123
|
+
Features:
|
|
124
|
+
- Interval-based scheduling (hourly, daily, custom)
|
|
125
|
+
- Thread-safe operation
|
|
126
|
+
- Automatic retry on failure
|
|
127
|
+
- Execution logging and monitoring
|
|
128
|
+
- Graceful shutdown
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
scheduler = AgentScheduler(agent, task="Check news")
|
|
132
|
+
scheduler.start(schedule_expr="hourly", max_retries=3)
|
|
133
|
+
# Agent runs every hour automatically
|
|
134
|
+
scheduler.stop() # Stop when needed
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
def __init__(
|
|
138
|
+
self,
|
|
139
|
+
agent,
|
|
140
|
+
task: str,
|
|
141
|
+
config: Optional[Dict[str, Any]] = None,
|
|
142
|
+
on_success: Optional[Callable] = None,
|
|
143
|
+
on_failure: Optional[Callable] = None
|
|
144
|
+
):
|
|
145
|
+
"""
|
|
146
|
+
Initialize agent scheduler.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
agent: PraisonAI Agent instance
|
|
150
|
+
task: Task description to execute
|
|
151
|
+
config: Optional configuration dict
|
|
152
|
+
on_success: Callback function on successful execution
|
|
153
|
+
on_failure: Callback function on failed execution
|
|
154
|
+
"""
|
|
155
|
+
self.agent = agent
|
|
156
|
+
self.task = task
|
|
157
|
+
self.config = config or {}
|
|
158
|
+
self.on_success = on_success
|
|
159
|
+
self.on_failure = on_failure
|
|
160
|
+
|
|
161
|
+
self.is_running = False
|
|
162
|
+
self._stop_event = threading.Event()
|
|
163
|
+
self._thread = None
|
|
164
|
+
self._executor = PraisonAgentExecutor(agent)
|
|
165
|
+
self._execution_count = 0
|
|
166
|
+
self._success_count = 0
|
|
167
|
+
self._failure_count = 0
|
|
168
|
+
|
|
169
|
+
def start(
|
|
170
|
+
self,
|
|
171
|
+
schedule_expr: str,
|
|
172
|
+
max_retries: int = 3,
|
|
173
|
+
run_immediately: bool = False
|
|
174
|
+
) -> bool:
|
|
175
|
+
"""
|
|
176
|
+
Start scheduled agent execution.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
schedule_expr: Schedule expression (e.g., "hourly", "*/1h", "3600")
|
|
180
|
+
max_retries: Maximum retry attempts on failure
|
|
181
|
+
run_immediately: If True, run agent immediately before starting schedule
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
True if scheduler started successfully
|
|
185
|
+
"""
|
|
186
|
+
if self.is_running:
|
|
187
|
+
logger.warning("Scheduler is already running")
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
interval = ScheduleParser.parse(schedule_expr)
|
|
192
|
+
self.is_running = True
|
|
193
|
+
self._stop_event.clear()
|
|
194
|
+
|
|
195
|
+
logger.info(f"Starting agent scheduler: {self.agent.name if hasattr(self.agent, 'name') else 'Agent'}")
|
|
196
|
+
logger.info(f"Task: {self.task}")
|
|
197
|
+
logger.info(f"Schedule: {schedule_expr} ({interval}s interval)")
|
|
198
|
+
logger.info(f"Max retries: {max_retries}")
|
|
199
|
+
|
|
200
|
+
# Run immediately if requested
|
|
201
|
+
if run_immediately:
|
|
202
|
+
logger.info("Running agent immediately before starting schedule...")
|
|
203
|
+
self._execute_with_retry(max_retries)
|
|
204
|
+
|
|
205
|
+
self._thread = threading.Thread(
|
|
206
|
+
target=self._run_schedule,
|
|
207
|
+
args=(interval, max_retries),
|
|
208
|
+
daemon=True
|
|
209
|
+
)
|
|
210
|
+
self._thread.start()
|
|
211
|
+
|
|
212
|
+
logger.info("Agent scheduler started successfully")
|
|
213
|
+
return True
|
|
214
|
+
|
|
215
|
+
except Exception as e:
|
|
216
|
+
logger.error(f"Failed to start scheduler: {e}")
|
|
217
|
+
self.is_running = False
|
|
218
|
+
return False
|
|
219
|
+
|
|
220
|
+
def stop(self) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
Stop the scheduler gracefully.
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
True if stopped successfully
|
|
226
|
+
"""
|
|
227
|
+
if not self.is_running:
|
|
228
|
+
logger.info("Scheduler is not running")
|
|
229
|
+
return True
|
|
230
|
+
|
|
231
|
+
logger.info("Stopping agent scheduler...")
|
|
232
|
+
self._stop_event.set()
|
|
233
|
+
|
|
234
|
+
if self._thread and self._thread.is_alive():
|
|
235
|
+
self._thread.join(timeout=10)
|
|
236
|
+
|
|
237
|
+
self.is_running = False
|
|
238
|
+
logger.info("Agent scheduler stopped")
|
|
239
|
+
logger.info(f"Execution stats - Total: {self._execution_count}, Success: {self._success_count}, Failed: {self._failure_count}")
|
|
240
|
+
return True
|
|
241
|
+
|
|
242
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
243
|
+
"""
|
|
244
|
+
Get execution statistics.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Dictionary with execution stats
|
|
248
|
+
"""
|
|
249
|
+
return {
|
|
250
|
+
"is_running": self.is_running,
|
|
251
|
+
"total_executions": self._execution_count,
|
|
252
|
+
"successful_executions": self._success_count,
|
|
253
|
+
"failed_executions": self._failure_count,
|
|
254
|
+
"success_rate": (self._success_count / self._execution_count * 100) if self._execution_count > 0 else 0
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
def _run_schedule(self, interval: int, max_retries: int):
|
|
258
|
+
"""Internal method to run scheduled agent executions."""
|
|
259
|
+
while not self._stop_event.is_set():
|
|
260
|
+
logger.info(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Starting scheduled agent execution")
|
|
261
|
+
|
|
262
|
+
self._execute_with_retry(max_retries)
|
|
263
|
+
|
|
264
|
+
# Wait for next scheduled time
|
|
265
|
+
logger.info(f"Next execution in {interval} seconds ({interval/3600:.1f} hours)")
|
|
266
|
+
self._stop_event.wait(interval)
|
|
267
|
+
|
|
268
|
+
def _execute_with_retry(self, max_retries: int):
|
|
269
|
+
"""Execute agent with retry logic."""
|
|
270
|
+
self._execution_count += 1
|
|
271
|
+
success = False
|
|
272
|
+
|
|
273
|
+
for attempt in range(max_retries):
|
|
274
|
+
try:
|
|
275
|
+
logger.info(f"Attempt {attempt + 1}/{max_retries}")
|
|
276
|
+
result = self._executor.execute(self.task)
|
|
277
|
+
|
|
278
|
+
logger.info(f"Agent execution successful on attempt {attempt + 1}")
|
|
279
|
+
logger.info(f"Result: {result}")
|
|
280
|
+
|
|
281
|
+
self._success_count += 1
|
|
282
|
+
success = True
|
|
283
|
+
|
|
284
|
+
if self.on_success:
|
|
285
|
+
self.on_success(result)
|
|
286
|
+
|
|
287
|
+
break
|
|
288
|
+
|
|
289
|
+
except Exception as e:
|
|
290
|
+
logger.error(f"Agent execution failed on attempt {attempt + 1}: {e}")
|
|
291
|
+
|
|
292
|
+
if attempt < max_retries - 1:
|
|
293
|
+
wait_time = 30 * (attempt + 1) # Exponential backoff
|
|
294
|
+
logger.info(f"Waiting {wait_time}s before retry...")
|
|
295
|
+
time.sleep(wait_time)
|
|
296
|
+
|
|
297
|
+
if not success:
|
|
298
|
+
self._failure_count += 1
|
|
299
|
+
logger.error(f"Agent execution failed after {max_retries} attempts")
|
|
300
|
+
|
|
301
|
+
if self.on_failure:
|
|
302
|
+
self.on_failure(f"Failed after {max_retries} attempts")
|
|
303
|
+
|
|
304
|
+
def execute_once(self) -> Any:
|
|
305
|
+
"""
|
|
306
|
+
Execute agent immediately (one-time execution).
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
Agent execution result
|
|
310
|
+
"""
|
|
311
|
+
logger.info("Executing agent once")
|
|
312
|
+
try:
|
|
313
|
+
result = self._executor.execute(self.task)
|
|
314
|
+
logger.info(f"One-time execution successful: {result}")
|
|
315
|
+
return result
|
|
316
|
+
except Exception as e:
|
|
317
|
+
logger.error(f"One-time execution failed: {e}")
|
|
318
|
+
raise
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def create_agent_scheduler(
|
|
322
|
+
agent,
|
|
323
|
+
task: str,
|
|
324
|
+
config: Optional[Dict[str, Any]] = None
|
|
325
|
+
) -> AgentScheduler:
|
|
326
|
+
"""
|
|
327
|
+
Factory function to create agent scheduler.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
agent: PraisonAI Agent instance
|
|
331
|
+
task: Task description
|
|
332
|
+
config: Optional configuration
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Configured AgentScheduler instance
|
|
336
|
+
"""
|
|
337
|
+
return AgentScheduler(agent, task, config)
|