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,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Guardrail Handler for CLI.
|
|
3
|
+
|
|
4
|
+
Provides output validation using LLM guardrails.
|
|
5
|
+
Usage: praisonai "prompt" --guardrail "Ensure output is valid JSON"
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, Tuple
|
|
9
|
+
from .base import FlagHandler
|
|
10
|
+
|
|
11
|
+
# Lazy import to avoid performance impact
|
|
12
|
+
PRAISONAI_AVAILABLE = False
|
|
13
|
+
LLMGuardrail = None
|
|
14
|
+
|
|
15
|
+
def _check_praisonai():
|
|
16
|
+
"""Check if praisonaiagents is available."""
|
|
17
|
+
global PRAISONAI_AVAILABLE, LLMGuardrail
|
|
18
|
+
try:
|
|
19
|
+
from praisonaiagents import LLMGuardrail as _LLMGuardrail
|
|
20
|
+
LLMGuardrail = _LLMGuardrail
|
|
21
|
+
PRAISONAI_AVAILABLE = True
|
|
22
|
+
except ImportError:
|
|
23
|
+
PRAISONAI_AVAILABLE = False
|
|
24
|
+
return PRAISONAI_AVAILABLE
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GuardrailHandler(FlagHandler):
|
|
28
|
+
"""
|
|
29
|
+
Handler for --guardrail flag.
|
|
30
|
+
|
|
31
|
+
Validates agent output using LLM-based guardrails.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
praisonai "Write code" --guardrail "Ensure code is secure"
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def feature_name(self) -> str:
|
|
39
|
+
return "guardrail"
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def flag_name(self) -> str:
|
|
43
|
+
return "guardrail"
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def flag_help(self) -> str:
|
|
47
|
+
return "Validate output with LLM guardrail (provide description string)"
|
|
48
|
+
|
|
49
|
+
def check_dependencies(self) -> Tuple[bool, str]:
|
|
50
|
+
"""Check if praisonaiagents is available."""
|
|
51
|
+
if _check_praisonai():
|
|
52
|
+
return True, ""
|
|
53
|
+
return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
|
|
54
|
+
|
|
55
|
+
def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
|
|
56
|
+
"""
|
|
57
|
+
Apply guardrail configuration to agent config.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
config: Agent configuration dictionary
|
|
61
|
+
flag_value: Guardrail description string
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Modified configuration with guardrail settings
|
|
65
|
+
"""
|
|
66
|
+
if flag_value:
|
|
67
|
+
config["guardrail_description"] = flag_value
|
|
68
|
+
# Store for later use in post_process_result
|
|
69
|
+
self._guardrail_description = flag_value
|
|
70
|
+
return config
|
|
71
|
+
|
|
72
|
+
def create_guardrail(self, description: str, llm: Any = None):
|
|
73
|
+
"""
|
|
74
|
+
Create an LLMGuardrail instance.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
description: Natural language description of validation criteria
|
|
78
|
+
llm: Optional LLM instance for validation (defaults to gpt-4o-mini)
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
LLMGuardrail instance or None if unavailable
|
|
82
|
+
"""
|
|
83
|
+
if not _check_praisonai():
|
|
84
|
+
self.print_status(
|
|
85
|
+
"Guardrail requires praisonaiagents. Install with: pip install praisonaiagents",
|
|
86
|
+
"error"
|
|
87
|
+
)
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
# Provide default LLM if none specified
|
|
91
|
+
if llm is None:
|
|
92
|
+
import os
|
|
93
|
+
# Try to get from environment or use default
|
|
94
|
+
llm = os.environ.get('OPENAI_MODEL_NAME', 'gpt-4o-mini')
|
|
95
|
+
|
|
96
|
+
return LLMGuardrail(description=description, llm=llm)
|
|
97
|
+
|
|
98
|
+
def validate_output(self, output: str, description: str, llm: Any = None) -> Tuple[bool, str]:
|
|
99
|
+
"""
|
|
100
|
+
Validate output against guardrail criteria.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
output: The output to validate
|
|
104
|
+
description: Validation criteria description
|
|
105
|
+
llm: Optional LLM for validation
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Tuple of (is_valid, message)
|
|
109
|
+
"""
|
|
110
|
+
guardrail = self.create_guardrail(description, llm)
|
|
111
|
+
if not guardrail:
|
|
112
|
+
return True, "Guardrail unavailable, skipping validation"
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
# Create a mock TaskOutput for the guardrail
|
|
116
|
+
from praisonaiagents import TaskOutput
|
|
117
|
+
task_output = TaskOutput(
|
|
118
|
+
description="CLI output",
|
|
119
|
+
summary="CLI output",
|
|
120
|
+
raw=output,
|
|
121
|
+
agent="CLI",
|
|
122
|
+
output_format="RAW"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
success, result = guardrail(task_output)
|
|
126
|
+
if success:
|
|
127
|
+
return True, "Guardrail validation passed"
|
|
128
|
+
else:
|
|
129
|
+
return False, f"Guardrail validation failed: {result}"
|
|
130
|
+
except Exception as e:
|
|
131
|
+
self.log(f"Guardrail error: {e}", "warning")
|
|
132
|
+
return True, f"Guardrail error (skipped): {e}"
|
|
133
|
+
|
|
134
|
+
def post_process_result(self, result: Any, flag_value: Any) -> Any:
|
|
135
|
+
"""
|
|
136
|
+
Post-process result with guardrail validation.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
result: Agent output
|
|
140
|
+
flag_value: Guardrail description
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Original result (validation is logged)
|
|
144
|
+
"""
|
|
145
|
+
if not flag_value:
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
is_valid, message = self.validate_output(str(result), flag_value)
|
|
149
|
+
|
|
150
|
+
if is_valid:
|
|
151
|
+
self.print_status(f"✅ {message}", "success")
|
|
152
|
+
else:
|
|
153
|
+
self.print_status(f"⚠️ {message}", "warning")
|
|
154
|
+
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
def execute(self, output: str = None, guardrail_description: str = None, **kwargs) -> Tuple[bool, str]:
|
|
158
|
+
"""
|
|
159
|
+
Execute guardrail validation.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
output: Output to validate
|
|
163
|
+
guardrail_description: Validation criteria
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Tuple of (is_valid, message)
|
|
167
|
+
"""
|
|
168
|
+
if not output or not guardrail_description:
|
|
169
|
+
return True, "No output or description provided"
|
|
170
|
+
|
|
171
|
+
return self.validate_output(output, guardrail_description)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Handoff Handler for CLI.
|
|
3
|
+
|
|
4
|
+
Provides agent-to-agent delegation capability.
|
|
5
|
+
Usage: praisonai "Complex task" --handoff "researcher,writer,editor"
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, Tuple, List
|
|
9
|
+
from .base import FlagHandler
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class HandoffHandler(FlagHandler):
|
|
13
|
+
"""
|
|
14
|
+
Handler for --handoff flag.
|
|
15
|
+
|
|
16
|
+
Enables agent-to-agent delegation for complex tasks.
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
praisonai "Research and write article" --handoff "researcher,writer"
|
|
20
|
+
praisonai "Analyze and visualize data" --handoff "analyst,visualizer"
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def feature_name(self) -> str:
|
|
25
|
+
return "handoff"
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def flag_name(self) -> str:
|
|
29
|
+
return "handoff"
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def flag_help(self) -> str:
|
|
33
|
+
return "Comma-separated list of agent roles for task delegation"
|
|
34
|
+
|
|
35
|
+
def check_dependencies(self) -> Tuple[bool, str]:
|
|
36
|
+
"""Check if Handoff is available."""
|
|
37
|
+
try:
|
|
38
|
+
import importlib.util
|
|
39
|
+
if importlib.util.find_spec("praisonaiagents") is not None:
|
|
40
|
+
return True, ""
|
|
41
|
+
return False, "praisonaiagents not installed"
|
|
42
|
+
except ImportError:
|
|
43
|
+
return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
|
|
44
|
+
|
|
45
|
+
def parse_agent_names(self, names_str: str) -> List[str]:
|
|
46
|
+
"""
|
|
47
|
+
Parse comma-separated agent names.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
names_str: Comma-separated string of agent names/roles
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
List of agent names
|
|
54
|
+
"""
|
|
55
|
+
if not names_str:
|
|
56
|
+
return []
|
|
57
|
+
return [name.strip() for name in names_str.split(',') if name.strip()]
|
|
58
|
+
|
|
59
|
+
def create_agents_with_handoff(self, agent_names: List[str], llm: str = None) -> List[Any]:
|
|
60
|
+
"""
|
|
61
|
+
Create agents with handoff capability.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
agent_names: List of agent role names
|
|
65
|
+
llm: Optional LLM model name
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
List of Agent instances with handoff configured
|
|
69
|
+
"""
|
|
70
|
+
available, msg = self.check_dependencies()
|
|
71
|
+
if not available:
|
|
72
|
+
self.print_status(msg, "error")
|
|
73
|
+
return []
|
|
74
|
+
|
|
75
|
+
from praisonaiagents import Agent, handoff
|
|
76
|
+
|
|
77
|
+
agents = []
|
|
78
|
+
|
|
79
|
+
# First pass: Create all agents without handoffs
|
|
80
|
+
for i, name in enumerate(agent_names):
|
|
81
|
+
agent_config = {
|
|
82
|
+
"name": name.title().replace("_", " "),
|
|
83
|
+
"role": name.title().replace("_", " "),
|
|
84
|
+
"goal": f"Complete tasks as {name}",
|
|
85
|
+
"backstory": f"Expert {name} with specialized skills"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if llm:
|
|
89
|
+
agent_config["llm"] = llm
|
|
90
|
+
|
|
91
|
+
agent = Agent(**agent_config)
|
|
92
|
+
agents.append(agent)
|
|
93
|
+
|
|
94
|
+
# Second pass: Set up handoffs by recreating agents with handoff config
|
|
95
|
+
final_agents = []
|
|
96
|
+
for i, name in enumerate(agent_names):
|
|
97
|
+
agent_config = {
|
|
98
|
+
"name": name.title().replace("_", " "),
|
|
99
|
+
"role": name.title().replace("_", " "),
|
|
100
|
+
"goal": f"Complete tasks as {name}",
|
|
101
|
+
"backstory": f"Expert {name} with specialized skills"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if llm:
|
|
105
|
+
agent_config["llm"] = llm
|
|
106
|
+
|
|
107
|
+
# Add handoff to next agent if not the last agent
|
|
108
|
+
if i < len(agent_names) - 1:
|
|
109
|
+
next_agent = agents[i + 1]
|
|
110
|
+
next_agent_name = agent_names[i + 1]
|
|
111
|
+
|
|
112
|
+
# Pass handoffs via constructor - this properly registers them as tools
|
|
113
|
+
agent_config["handoffs"] = [
|
|
114
|
+
handoff(
|
|
115
|
+
agent=next_agent,
|
|
116
|
+
tool_name_override=f"handoff_to_{next_agent_name}",
|
|
117
|
+
tool_description_override=f"Hand off the task to {next_agent_name}. Call this after completing your part."
|
|
118
|
+
)
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
# Add instructions to use handoff
|
|
122
|
+
agent_config["instructions"] = f"After completing your task, you MUST use the handoff_to_{next_agent_name} tool to pass your work to the next agent."
|
|
123
|
+
|
|
124
|
+
final_agent = Agent(**agent_config)
|
|
125
|
+
final_agents.append(final_agent)
|
|
126
|
+
|
|
127
|
+
self.print_status(f"🤝 Created {len(final_agents)} agents with handoff chain", "success")
|
|
128
|
+
for i, name in enumerate(agent_names):
|
|
129
|
+
arrow = " → " if i < len(agent_names) - 1 else ""
|
|
130
|
+
self.print_status(f" {name}{arrow}", "info")
|
|
131
|
+
|
|
132
|
+
return final_agents
|
|
133
|
+
|
|
134
|
+
def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
|
|
135
|
+
"""
|
|
136
|
+
Apply handoff configuration.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
config: Agent configuration dictionary
|
|
140
|
+
flag_value: Comma-separated agent names
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Modified configuration
|
|
144
|
+
"""
|
|
145
|
+
if flag_value:
|
|
146
|
+
agent_names = self.parse_agent_names(flag_value)
|
|
147
|
+
config['handoff_agents'] = agent_names
|
|
148
|
+
config['use_handoff'] = True
|
|
149
|
+
return config
|
|
150
|
+
|
|
151
|
+
def execute(self, prompt: str = None, agent_names: str = None, llm: str = None, **kwargs) -> Any:
|
|
152
|
+
"""
|
|
153
|
+
Execute task with handoff agents.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
prompt: Task prompt
|
|
157
|
+
agent_names: Comma-separated agent names
|
|
158
|
+
llm: Optional LLM model
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
Task result
|
|
162
|
+
"""
|
|
163
|
+
if not agent_names:
|
|
164
|
+
self.print_status("No agent names provided for handoff", "error")
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
names = self.parse_agent_names(agent_names)
|
|
168
|
+
if len(names) < 2:
|
|
169
|
+
self.print_status("Handoff requires at least 2 agents", "error")
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
agents = self.create_agents_with_handoff(names, llm)
|
|
173
|
+
if not agents:
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
if prompt:
|
|
177
|
+
# Execute with first agent
|
|
178
|
+
try:
|
|
179
|
+
result = agents[0].start(prompt)
|
|
180
|
+
return result
|
|
181
|
+
except Exception as e:
|
|
182
|
+
self.print_status(f"Handoff execution failed: {e}", "error")
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
return agents
|