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,829 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Serve CLI Feature Handler
|
|
3
|
+
|
|
4
|
+
Provides CLI commands for launching PraisonAI servers:
|
|
5
|
+
- praisonai serve agents - Launch agents as HTTP API
|
|
6
|
+
- praisonai serve recipe - Launch recipe runner
|
|
7
|
+
- praisonai serve mcp - Launch MCP server
|
|
8
|
+
- praisonai serve tools - Launch tools as MCP server
|
|
9
|
+
- praisonai serve a2a - Launch A2A server
|
|
10
|
+
- praisonai serve a2u - Launch A2U event stream server
|
|
11
|
+
- praisonai serve unified - Launch unified server with all providers
|
|
12
|
+
|
|
13
|
+
All servers include the unified discovery endpoint at /__praisonai__/discovery.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from typing import Any, Dict, List
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ServeHandler:
|
|
22
|
+
"""
|
|
23
|
+
CLI handler for serve operations.
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
- agents: Launch agents as HTTP API
|
|
27
|
+
- recipe: Launch recipe runner
|
|
28
|
+
- mcp: Launch MCP server
|
|
29
|
+
- tools: Launch tools as MCP server
|
|
30
|
+
- a2a: Launch A2A server
|
|
31
|
+
- a2u: Launch A2U event stream server
|
|
32
|
+
- unified: Launch unified server
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
EXIT_SUCCESS = 0
|
|
36
|
+
EXIT_GENERAL_ERROR = 1
|
|
37
|
+
EXIT_VALIDATION_ERROR = 2
|
|
38
|
+
|
|
39
|
+
DEFAULT_HOST = "127.0.0.1"
|
|
40
|
+
DEFAULT_PORT = 8765
|
|
41
|
+
|
|
42
|
+
def __init__(self):
|
|
43
|
+
"""Initialize the handler."""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def handle(self, args: List[str]) -> int:
|
|
47
|
+
"""
|
|
48
|
+
Handle serve subcommand.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
args: Command arguments
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Exit code
|
|
55
|
+
"""
|
|
56
|
+
if not args:
|
|
57
|
+
self._print_help()
|
|
58
|
+
return self.EXIT_SUCCESS
|
|
59
|
+
|
|
60
|
+
command = args[0]
|
|
61
|
+
remaining = args[1:]
|
|
62
|
+
|
|
63
|
+
commands = {
|
|
64
|
+
"agents": self.cmd_agents,
|
|
65
|
+
"recipe": self.cmd_recipe,
|
|
66
|
+
"mcp": self.cmd_mcp,
|
|
67
|
+
"tools": self.cmd_tools,
|
|
68
|
+
"a2a": self.cmd_a2a,
|
|
69
|
+
"a2u": self.cmd_a2u,
|
|
70
|
+
"unified": self.cmd_unified,
|
|
71
|
+
"help": lambda _: self._print_help() or self.EXIT_SUCCESS,
|
|
72
|
+
"--help": lambda _: self._print_help() or self.EXIT_SUCCESS,
|
|
73
|
+
"-h": lambda _: self._print_help() or self.EXIT_SUCCESS,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if command in commands:
|
|
77
|
+
return commands[command](remaining)
|
|
78
|
+
else:
|
|
79
|
+
self._print_error(f"Unknown command: {command}")
|
|
80
|
+
self._print_help()
|
|
81
|
+
return self.EXIT_GENERAL_ERROR
|
|
82
|
+
|
|
83
|
+
def _print_help(self):
|
|
84
|
+
"""Print help message."""
|
|
85
|
+
help_text = """
|
|
86
|
+
[bold cyan]PraisonAI Serve[/bold cyan]
|
|
87
|
+
|
|
88
|
+
Launch PraisonAI servers with unified discovery support.
|
|
89
|
+
|
|
90
|
+
[bold]Usage:[/bold]
|
|
91
|
+
praisonai serve <command> [options]
|
|
92
|
+
|
|
93
|
+
[bold]Commands:[/bold]
|
|
94
|
+
agents Launch agents as HTTP API
|
|
95
|
+
recipe Launch recipe runner server
|
|
96
|
+
mcp Launch MCP server (HTTP mode)
|
|
97
|
+
tools Launch tools as MCP server
|
|
98
|
+
a2a Launch A2A protocol server
|
|
99
|
+
a2u Launch A2U event stream server
|
|
100
|
+
unified Launch unified server with all providers
|
|
101
|
+
|
|
102
|
+
[bold]Common Options:[/bold]
|
|
103
|
+
--host <host> Server host (default: 127.0.0.1)
|
|
104
|
+
--port <port> Server port (default: 8765)
|
|
105
|
+
--reload Enable hot reload
|
|
106
|
+
--api-key <key> API key for authentication
|
|
107
|
+
|
|
108
|
+
[bold]Agents Options:[/bold]
|
|
109
|
+
--file <path> Agents YAML file (default: agents.yaml)
|
|
110
|
+
--path <path> API endpoint path (default: /agents)
|
|
111
|
+
|
|
112
|
+
[bold]Recipe Options:[/bold]
|
|
113
|
+
--config <path> Config file path (serve.yaml)
|
|
114
|
+
--preload Preload all recipes
|
|
115
|
+
|
|
116
|
+
[bold]MCP Options:[/bold]
|
|
117
|
+
--transport Transport type: http, sse (default: http)
|
|
118
|
+
|
|
119
|
+
[bold]Examples:[/bold]
|
|
120
|
+
praisonai serve agents --file agents.yaml --port 8000
|
|
121
|
+
praisonai serve recipe --port 8765
|
|
122
|
+
praisonai serve mcp --transport http --port 8080
|
|
123
|
+
praisonai serve tools --port 8081
|
|
124
|
+
praisonai serve a2a --port 8082
|
|
125
|
+
praisonai serve unified --port 8765
|
|
126
|
+
|
|
127
|
+
[bold]Discovery:[/bold]
|
|
128
|
+
All servers expose /__praisonai__/discovery for unified endpoint discovery.
|
|
129
|
+
Use `praisonai endpoints` to interact with any server.
|
|
130
|
+
"""
|
|
131
|
+
self._print_rich(help_text)
|
|
132
|
+
|
|
133
|
+
def _print_rich(self, text: str):
|
|
134
|
+
"""Print with rich formatting if available."""
|
|
135
|
+
try:
|
|
136
|
+
from rich import print as rprint
|
|
137
|
+
rprint(text)
|
|
138
|
+
except ImportError:
|
|
139
|
+
import re
|
|
140
|
+
plain = re.sub(r'\[/?[^\]]+\]', '', text)
|
|
141
|
+
print(plain)
|
|
142
|
+
|
|
143
|
+
def _print_error(self, message: str):
|
|
144
|
+
"""Print error message."""
|
|
145
|
+
try:
|
|
146
|
+
from rich import print as rprint
|
|
147
|
+
rprint(f"[red]Error: {message}[/red]")
|
|
148
|
+
except ImportError:
|
|
149
|
+
print(f"Error: {message}", file=sys.stderr)
|
|
150
|
+
|
|
151
|
+
def _print_success(self, message: str):
|
|
152
|
+
"""Print success message."""
|
|
153
|
+
try:
|
|
154
|
+
from rich import print as rprint
|
|
155
|
+
rprint(f"[green]✓ {message}[/green]")
|
|
156
|
+
except ImportError:
|
|
157
|
+
print(f"✓ {message}")
|
|
158
|
+
|
|
159
|
+
def _parse_args(self, args: List[str], spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
160
|
+
"""Parse command arguments based on spec."""
|
|
161
|
+
result = {k: v.get("default") for k, v in spec.items()}
|
|
162
|
+
|
|
163
|
+
i = 0
|
|
164
|
+
while i < len(args):
|
|
165
|
+
arg = args[i]
|
|
166
|
+
|
|
167
|
+
if arg.startswith("--"):
|
|
168
|
+
key = arg[2:].replace("-", "_")
|
|
169
|
+
if key in spec:
|
|
170
|
+
if spec[key].get("flag"):
|
|
171
|
+
result[key] = True
|
|
172
|
+
elif i + 1 < len(args):
|
|
173
|
+
value = args[i + 1]
|
|
174
|
+
# Type conversion
|
|
175
|
+
if spec[key].get("type") == "int":
|
|
176
|
+
value = int(value)
|
|
177
|
+
result[key] = value
|
|
178
|
+
i += 1
|
|
179
|
+
i += 1
|
|
180
|
+
else:
|
|
181
|
+
i += 1
|
|
182
|
+
|
|
183
|
+
return result
|
|
184
|
+
|
|
185
|
+
def cmd_agents(self, args: List[str]) -> int:
|
|
186
|
+
"""Launch agents as HTTP API."""
|
|
187
|
+
spec = {
|
|
188
|
+
"file": {"default": "agents.yaml"},
|
|
189
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
190
|
+
"port": {"default": self.DEFAULT_PORT, "type": "int"},
|
|
191
|
+
"path": {"default": "/agents"},
|
|
192
|
+
"reload": {"flag": True, "default": False},
|
|
193
|
+
"api_key": {"default": None},
|
|
194
|
+
}
|
|
195
|
+
parsed = self._parse_args(args, spec)
|
|
196
|
+
|
|
197
|
+
# Check if agents file exists
|
|
198
|
+
if not os.path.exists(parsed["file"]):
|
|
199
|
+
self._print_error(f"Agents file not found: {parsed['file']}")
|
|
200
|
+
return self.EXIT_VALIDATION_ERROR
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
self._print_success(f"Starting agents server on {parsed['host']}:{parsed['port']}")
|
|
204
|
+
print(f" Agents file: {parsed['file']}")
|
|
205
|
+
print(f" Endpoint: {parsed['path']}")
|
|
206
|
+
print(" Discovery: /__praisonai__/discovery")
|
|
207
|
+
|
|
208
|
+
# Create and run server
|
|
209
|
+
app = self._create_agents_app(parsed)
|
|
210
|
+
self._run_server(app, parsed["host"], parsed["port"], parsed["reload"])
|
|
211
|
+
|
|
212
|
+
except ImportError as e:
|
|
213
|
+
self._print_error(f"Missing dependency: {e}")
|
|
214
|
+
print("Install with: pip install praisonai[serve]")
|
|
215
|
+
return self.EXIT_GENERAL_ERROR
|
|
216
|
+
except Exception as e:
|
|
217
|
+
self._print_error(str(e))
|
|
218
|
+
return self.EXIT_GENERAL_ERROR
|
|
219
|
+
|
|
220
|
+
return self.EXIT_SUCCESS
|
|
221
|
+
|
|
222
|
+
def _create_agents_app(self, config: Dict[str, Any]) -> Any:
|
|
223
|
+
"""Create FastAPI app for agents."""
|
|
224
|
+
from fastapi import FastAPI, HTTPException, Request
|
|
225
|
+
from fastapi.responses import JSONResponse
|
|
226
|
+
from pydantic import BaseModel
|
|
227
|
+
|
|
228
|
+
from praisonai.endpoints.discovery import (
|
|
229
|
+
create_discovery_document,
|
|
230
|
+
EndpointInfo,
|
|
231
|
+
ProviderInfo,
|
|
232
|
+
)
|
|
233
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
234
|
+
|
|
235
|
+
# Load agents from YAML
|
|
236
|
+
import yaml
|
|
237
|
+
with open(config["file"]) as f:
|
|
238
|
+
_ = yaml.safe_load(f) # Validate YAML
|
|
239
|
+
|
|
240
|
+
# Create discovery document
|
|
241
|
+
discovery = create_discovery_document(server_name="praisonai-agents")
|
|
242
|
+
discovery.add_provider(ProviderInfo(
|
|
243
|
+
type="agents-api",
|
|
244
|
+
name="Agents API",
|
|
245
|
+
description="Agent HTTP API endpoints",
|
|
246
|
+
capabilities=["invoke", "health"],
|
|
247
|
+
))
|
|
248
|
+
|
|
249
|
+
# Create app
|
|
250
|
+
app = FastAPI(
|
|
251
|
+
title="PraisonAI Agents API",
|
|
252
|
+
description="HTTP API for PraisonAI Agents",
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Add discovery routes
|
|
256
|
+
add_discovery_routes(app, discovery)
|
|
257
|
+
|
|
258
|
+
# Request model
|
|
259
|
+
class AgentQuery(BaseModel):
|
|
260
|
+
query: str
|
|
261
|
+
|
|
262
|
+
# Create endpoint for agents
|
|
263
|
+
path = config["path"]
|
|
264
|
+
|
|
265
|
+
@app.post(path)
|
|
266
|
+
async def invoke_agents(request: Request, query_data: AgentQuery = None):
|
|
267
|
+
"""Invoke agents with a query."""
|
|
268
|
+
if query_data is None:
|
|
269
|
+
try:
|
|
270
|
+
body = await request.json()
|
|
271
|
+
_ = body.get("query", "") # Extract query
|
|
272
|
+
except Exception:
|
|
273
|
+
raise HTTPException(status_code=400, detail="Invalid request")
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
# Lazy load and run agents
|
|
277
|
+
from praisonai.agents_generator import AgentsGenerator
|
|
278
|
+
|
|
279
|
+
generator = AgentsGenerator(
|
|
280
|
+
agent_file=config["file"],
|
|
281
|
+
framework="praisonai",
|
|
282
|
+
)
|
|
283
|
+
result = generator.generate_crew_and_kickoff()
|
|
284
|
+
|
|
285
|
+
return {"response": result}
|
|
286
|
+
except Exception as e:
|
|
287
|
+
return JSONResponse(
|
|
288
|
+
{"error": str(e)},
|
|
289
|
+
status_code=500,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Add endpoint to discovery
|
|
293
|
+
discovery.add_endpoint(EndpointInfo(
|
|
294
|
+
name=path.lstrip("/"),
|
|
295
|
+
description="Invoke agents workflow",
|
|
296
|
+
provider_type="agents-api",
|
|
297
|
+
input_schema={"type": "object", "properties": {"query": {"type": "string"}}},
|
|
298
|
+
streaming=["none"],
|
|
299
|
+
))
|
|
300
|
+
|
|
301
|
+
# Root endpoint
|
|
302
|
+
@app.get("/")
|
|
303
|
+
async def root():
|
|
304
|
+
return {
|
|
305
|
+
"message": "PraisonAI Agents API",
|
|
306
|
+
"endpoints": [path],
|
|
307
|
+
"discovery": "/__praisonai__/discovery",
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return app
|
|
311
|
+
|
|
312
|
+
def cmd_recipe(self, args: List[str]) -> int:
|
|
313
|
+
"""Launch recipe runner server."""
|
|
314
|
+
spec = {
|
|
315
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
316
|
+
"port": {"default": self.DEFAULT_PORT, "type": "int"},
|
|
317
|
+
"config": {"default": None},
|
|
318
|
+
"reload": {"flag": True, "default": False},
|
|
319
|
+
"api_key": {"default": None},
|
|
320
|
+
"preload": {"flag": True, "default": False},
|
|
321
|
+
}
|
|
322
|
+
parsed = self._parse_args(args, spec)
|
|
323
|
+
|
|
324
|
+
try:
|
|
325
|
+
self._print_success(f"Starting recipe server on {parsed['host']}:{parsed['port']}")
|
|
326
|
+
print(" Discovery: /__praisonai__/discovery")
|
|
327
|
+
|
|
328
|
+
from praisonai.recipe.serve import serve, load_config
|
|
329
|
+
|
|
330
|
+
# Load config
|
|
331
|
+
config = load_config(parsed["config"]) if parsed["config"] else {}
|
|
332
|
+
if parsed["api_key"]:
|
|
333
|
+
config["api_key"] = parsed["api_key"]
|
|
334
|
+
|
|
335
|
+
serve(
|
|
336
|
+
host=parsed["host"],
|
|
337
|
+
port=parsed["port"],
|
|
338
|
+
reload=parsed["reload"],
|
|
339
|
+
config=config,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
except ImportError as e:
|
|
343
|
+
self._print_error(f"Missing dependency: {e}")
|
|
344
|
+
print("Install with: pip install praisonai[serve]")
|
|
345
|
+
return self.EXIT_GENERAL_ERROR
|
|
346
|
+
except Exception as e:
|
|
347
|
+
self._print_error(str(e))
|
|
348
|
+
return self.EXIT_GENERAL_ERROR
|
|
349
|
+
|
|
350
|
+
return self.EXIT_SUCCESS
|
|
351
|
+
|
|
352
|
+
def cmd_mcp(self, args: List[str]) -> int:
|
|
353
|
+
"""Launch MCP server (DEPRECATED - use 'praisonai mcp serve' instead)."""
|
|
354
|
+
import sys
|
|
355
|
+
|
|
356
|
+
# Print deprecation warning
|
|
357
|
+
print("\n[yellow]⚠ DEPRECATION WARNING:[/yellow]", file=sys.stderr)
|
|
358
|
+
print("[yellow]'praisonai serve mcp' is deprecated and will be removed in a future version.[/yellow]", file=sys.stderr)
|
|
359
|
+
print("[yellow]Please use 'praisonai mcp serve' instead.[/yellow]\n", file=sys.stderr)
|
|
360
|
+
|
|
361
|
+
# Redirect to new MCP server CLI
|
|
362
|
+
try:
|
|
363
|
+
from praisonai.mcp_server.cli import handle_mcp_command
|
|
364
|
+
|
|
365
|
+
# Convert args to new format
|
|
366
|
+
new_args = ["serve"]
|
|
367
|
+
spec = {
|
|
368
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
369
|
+
"port": {"default": 8080, "type": "int"},
|
|
370
|
+
"transport": {"default": "http-stream"},
|
|
371
|
+
}
|
|
372
|
+
parsed = self._parse_args(args, spec)
|
|
373
|
+
|
|
374
|
+
new_args.extend(["--host", parsed["host"]])
|
|
375
|
+
new_args.extend(["--port", str(parsed["port"])])
|
|
376
|
+
new_args.extend(["--transport", parsed["transport"]])
|
|
377
|
+
|
|
378
|
+
return handle_mcp_command(new_args)
|
|
379
|
+
|
|
380
|
+
except ImportError as e:
|
|
381
|
+
self._print_error(f"Missing dependency: {e}")
|
|
382
|
+
return self.EXIT_GENERAL_ERROR
|
|
383
|
+
except Exception as e:
|
|
384
|
+
self._print_error(str(e))
|
|
385
|
+
return self.EXIT_GENERAL_ERROR
|
|
386
|
+
|
|
387
|
+
def _create_mcp_app(self, config: Dict[str, Any]) -> Any:
|
|
388
|
+
"""Create FastAPI app for MCP server."""
|
|
389
|
+
from fastapi import FastAPI
|
|
390
|
+
|
|
391
|
+
from praisonai.endpoints.discovery import (
|
|
392
|
+
create_discovery_document,
|
|
393
|
+
ProviderInfo,
|
|
394
|
+
)
|
|
395
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
396
|
+
|
|
397
|
+
# Create discovery document
|
|
398
|
+
discovery = create_discovery_document(server_name="praisonai-mcp")
|
|
399
|
+
discovery.add_provider(ProviderInfo(
|
|
400
|
+
type="mcp",
|
|
401
|
+
name="MCP Server",
|
|
402
|
+
description=f"MCP server ({config['transport']} transport)",
|
|
403
|
+
capabilities=["list-tools", "call-tool"],
|
|
404
|
+
))
|
|
405
|
+
|
|
406
|
+
app = FastAPI(
|
|
407
|
+
title="PraisonAI MCP Server",
|
|
408
|
+
description="MCP protocol server",
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
add_discovery_routes(app, discovery)
|
|
412
|
+
|
|
413
|
+
# MCP tools endpoint
|
|
414
|
+
@app.get("/mcp/tools")
|
|
415
|
+
async def list_tools():
|
|
416
|
+
"""List available MCP tools."""
|
|
417
|
+
# TODO: Load tools from config or registry
|
|
418
|
+
return {"tools": []}
|
|
419
|
+
|
|
420
|
+
@app.post("/mcp/tools/call")
|
|
421
|
+
async def call_tool(request_data: dict):
|
|
422
|
+
"""Call an MCP tool."""
|
|
423
|
+
tool_name = request_data.get("tool")
|
|
424
|
+
_ = request_data.get("arguments", {}) # Arguments for tool
|
|
425
|
+
|
|
426
|
+
# TODO: Execute tool
|
|
427
|
+
return {"result": None, "tool": tool_name}
|
|
428
|
+
|
|
429
|
+
@app.get("/")
|
|
430
|
+
async def root():
|
|
431
|
+
return {
|
|
432
|
+
"message": "PraisonAI MCP Server",
|
|
433
|
+
"transport": config["transport"],
|
|
434
|
+
"discovery": "/__praisonai__/discovery",
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return app
|
|
438
|
+
|
|
439
|
+
def cmd_tools(self, args: List[str]) -> int:
|
|
440
|
+
"""Launch tools as MCP server (DEPRECATED - use 'praisonai mcp serve' instead)."""
|
|
441
|
+
import sys
|
|
442
|
+
|
|
443
|
+
# Print deprecation warning
|
|
444
|
+
print("\n[yellow]⚠ DEPRECATION WARNING:[/yellow]", file=sys.stderr)
|
|
445
|
+
print("[yellow]'praisonai serve tools' is deprecated and will be removed in a future version.[/yellow]", file=sys.stderr)
|
|
446
|
+
print("[yellow]Please use 'praisonai mcp serve' instead.[/yellow]\n", file=sys.stderr)
|
|
447
|
+
|
|
448
|
+
# Redirect to new MCP server CLI
|
|
449
|
+
try:
|
|
450
|
+
from praisonai.mcp_server.cli import handle_mcp_command
|
|
451
|
+
|
|
452
|
+
# Convert args to new format
|
|
453
|
+
new_args = ["serve"]
|
|
454
|
+
spec = {
|
|
455
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
456
|
+
"port": {"default": 8080, "type": "int"},
|
|
457
|
+
}
|
|
458
|
+
parsed = self._parse_args(args, spec)
|
|
459
|
+
|
|
460
|
+
new_args.extend(["--host", parsed["host"]])
|
|
461
|
+
new_args.extend(["--port", str(parsed["port"])])
|
|
462
|
+
new_args.extend(["--transport", "http-stream"])
|
|
463
|
+
|
|
464
|
+
return handle_mcp_command(new_args)
|
|
465
|
+
|
|
466
|
+
except ImportError as e:
|
|
467
|
+
self._print_error(f"Missing dependency: {e}")
|
|
468
|
+
return self.EXIT_GENERAL_ERROR
|
|
469
|
+
except Exception as e:
|
|
470
|
+
self._print_error(str(e))
|
|
471
|
+
return self.EXIT_GENERAL_ERROR
|
|
472
|
+
|
|
473
|
+
def _create_tools_app(self, config: Dict[str, Any]) -> Any:
|
|
474
|
+
"""Create FastAPI app for tools MCP server."""
|
|
475
|
+
from fastapi import FastAPI
|
|
476
|
+
|
|
477
|
+
from praisonai.endpoints.discovery import (
|
|
478
|
+
create_discovery_document,
|
|
479
|
+
ProviderInfo,
|
|
480
|
+
)
|
|
481
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
482
|
+
|
|
483
|
+
discovery = create_discovery_document(server_name="praisonai-tools-mcp")
|
|
484
|
+
discovery.add_provider(ProviderInfo(
|
|
485
|
+
type="tools-mcp",
|
|
486
|
+
name="Tools MCP Server",
|
|
487
|
+
description="Python tools exposed as MCP server",
|
|
488
|
+
capabilities=["list-tools", "call-tool"],
|
|
489
|
+
))
|
|
490
|
+
|
|
491
|
+
app = FastAPI(
|
|
492
|
+
title="PraisonAI Tools MCP Server",
|
|
493
|
+
description="Tools exposed as MCP server",
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
add_discovery_routes(app, discovery)
|
|
497
|
+
|
|
498
|
+
@app.get("/tools")
|
|
499
|
+
async def list_tools():
|
|
500
|
+
"""List available tools."""
|
|
501
|
+
return {"tools": []}
|
|
502
|
+
|
|
503
|
+
@app.post("/tools/call")
|
|
504
|
+
async def call_tool(request_data: dict):
|
|
505
|
+
"""Call a tool."""
|
|
506
|
+
return {"result": None}
|
|
507
|
+
|
|
508
|
+
@app.get("/")
|
|
509
|
+
async def root():
|
|
510
|
+
return {
|
|
511
|
+
"message": "PraisonAI Tools MCP Server",
|
|
512
|
+
"discovery": "/__praisonai__/discovery",
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return app
|
|
516
|
+
|
|
517
|
+
def cmd_a2a(self, args: List[str]) -> int:
|
|
518
|
+
"""Launch A2A protocol server."""
|
|
519
|
+
spec = {
|
|
520
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
521
|
+
"port": {"default": 8082, "type": "int"},
|
|
522
|
+
"file": {"default": "agents.yaml"},
|
|
523
|
+
}
|
|
524
|
+
parsed = self._parse_args(args, spec)
|
|
525
|
+
|
|
526
|
+
try:
|
|
527
|
+
self._print_success(f"Starting A2A server on {parsed['host']}:{parsed['port']}")
|
|
528
|
+
print(" Agent Card: /.well-known/agent.json")
|
|
529
|
+
print(" Discovery: /__praisonai__/discovery")
|
|
530
|
+
|
|
531
|
+
app = self._create_a2a_app(parsed)
|
|
532
|
+
self._run_server(app, parsed["host"], parsed["port"], False)
|
|
533
|
+
|
|
534
|
+
except ImportError as e:
|
|
535
|
+
self._print_error(f"Missing dependency: {e}")
|
|
536
|
+
return self.EXIT_GENERAL_ERROR
|
|
537
|
+
except Exception as e:
|
|
538
|
+
self._print_error(str(e))
|
|
539
|
+
return self.EXIT_GENERAL_ERROR
|
|
540
|
+
|
|
541
|
+
return self.EXIT_SUCCESS
|
|
542
|
+
|
|
543
|
+
def _create_a2a_app(self, config: Dict[str, Any]) -> Any:
|
|
544
|
+
"""Create FastAPI app for A2A server."""
|
|
545
|
+
from fastapi import FastAPI
|
|
546
|
+
|
|
547
|
+
from praisonai.endpoints.discovery import (
|
|
548
|
+
create_discovery_document,
|
|
549
|
+
EndpointInfo,
|
|
550
|
+
ProviderInfo,
|
|
551
|
+
)
|
|
552
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
553
|
+
|
|
554
|
+
discovery = create_discovery_document(server_name="praisonai-a2a")
|
|
555
|
+
discovery.add_provider(ProviderInfo(
|
|
556
|
+
type="a2a",
|
|
557
|
+
name="A2A Protocol",
|
|
558
|
+
description="Agent-to-Agent communication",
|
|
559
|
+
capabilities=["agent-card", "message-send"],
|
|
560
|
+
))
|
|
561
|
+
|
|
562
|
+
app = FastAPI(
|
|
563
|
+
title="PraisonAI A2A Server",
|
|
564
|
+
description="A2A protocol server",
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
add_discovery_routes(app, discovery)
|
|
568
|
+
|
|
569
|
+
# Agent card
|
|
570
|
+
@app.get("/.well-known/agent.json")
|
|
571
|
+
async def agent_card():
|
|
572
|
+
"""Return agent card for A2A discovery."""
|
|
573
|
+
return {
|
|
574
|
+
"name": "PraisonAI Agent",
|
|
575
|
+
"description": "PraisonAI Agent via A2A protocol",
|
|
576
|
+
"version": "1.0.0",
|
|
577
|
+
"url": f"http://{config.get('host', 'localhost')}:{config.get('port', 8082)}/a2a",
|
|
578
|
+
"capabilities": {
|
|
579
|
+
"streaming": True,
|
|
580
|
+
"pushNotifications": False,
|
|
581
|
+
},
|
|
582
|
+
"skills": [],
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
@app.get("/status")
|
|
586
|
+
async def status():
|
|
587
|
+
"""Return server status."""
|
|
588
|
+
return {"status": "ok", "name": "PraisonAI A2A", "version": "1.0.0"}
|
|
589
|
+
|
|
590
|
+
@app.post("/a2a")
|
|
591
|
+
async def a2a_endpoint(request_data: dict):
|
|
592
|
+
"""Handle A2A JSON-RPC requests."""
|
|
593
|
+
method = request_data.get("method")
|
|
594
|
+
params = request_data.get("params", {})
|
|
595
|
+
request_id = request_data.get("id")
|
|
596
|
+
|
|
597
|
+
if method == "message/send":
|
|
598
|
+
# Handle message
|
|
599
|
+
message = params.get("message", {})
|
|
600
|
+
parts = message.get("parts", [])
|
|
601
|
+
text = ""
|
|
602
|
+
for part in parts:
|
|
603
|
+
if part.get("type") == "text":
|
|
604
|
+
text += part.get("text", "")
|
|
605
|
+
|
|
606
|
+
# TODO: Process with agent
|
|
607
|
+
return {
|
|
608
|
+
"jsonrpc": "2.0",
|
|
609
|
+
"id": request_id,
|
|
610
|
+
"result": {
|
|
611
|
+
"message": {
|
|
612
|
+
"role": "assistant",
|
|
613
|
+
"parts": [{"type": "text", "text": f"Received: {text}"}],
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return {
|
|
619
|
+
"jsonrpc": "2.0",
|
|
620
|
+
"id": request_id,
|
|
621
|
+
"error": {"code": -32601, "message": f"Method not found: {method}"},
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
discovery.add_endpoint(EndpointInfo(
|
|
625
|
+
name="a2a",
|
|
626
|
+
description="A2A protocol endpoint",
|
|
627
|
+
provider_type="a2a",
|
|
628
|
+
streaming=["sse"],
|
|
629
|
+
))
|
|
630
|
+
|
|
631
|
+
@app.get("/")
|
|
632
|
+
async def root():
|
|
633
|
+
return {
|
|
634
|
+
"message": "PraisonAI A2A Server",
|
|
635
|
+
"agent_card": "/.well-known/agent.json",
|
|
636
|
+
"discovery": "/__praisonai__/discovery",
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return app
|
|
640
|
+
|
|
641
|
+
def cmd_a2u(self, args: List[str]) -> int:
|
|
642
|
+
"""Launch A2U event stream server."""
|
|
643
|
+
spec = {
|
|
644
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
645
|
+
"port": {"default": 8083, "type": "int"},
|
|
646
|
+
}
|
|
647
|
+
parsed = self._parse_args(args, spec)
|
|
648
|
+
|
|
649
|
+
try:
|
|
650
|
+
self._print_success(f"Starting A2U server on {parsed['host']}:{parsed['port']}")
|
|
651
|
+
print(" Events: /a2u/events/<stream>")
|
|
652
|
+
print(" Discovery: /__praisonai__/discovery")
|
|
653
|
+
|
|
654
|
+
app = self._create_a2u_app(parsed)
|
|
655
|
+
self._run_server(app, parsed["host"], parsed["port"], False)
|
|
656
|
+
|
|
657
|
+
except ImportError as e:
|
|
658
|
+
self._print_error(f"Missing dependency: {e}")
|
|
659
|
+
return self.EXIT_GENERAL_ERROR
|
|
660
|
+
except Exception as e:
|
|
661
|
+
self._print_error(str(e))
|
|
662
|
+
return self.EXIT_GENERAL_ERROR
|
|
663
|
+
|
|
664
|
+
return self.EXIT_SUCCESS
|
|
665
|
+
|
|
666
|
+
def _create_a2u_app(self, config: Dict[str, Any]) -> Any:
|
|
667
|
+
"""Create FastAPI app for A2U server."""
|
|
668
|
+
from fastapi import FastAPI
|
|
669
|
+
|
|
670
|
+
from praisonai.endpoints.discovery import (
|
|
671
|
+
create_discovery_document,
|
|
672
|
+
EndpointInfo,
|
|
673
|
+
ProviderInfo,
|
|
674
|
+
)
|
|
675
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
676
|
+
from praisonai.endpoints.a2u_server import create_a2u_routes
|
|
677
|
+
|
|
678
|
+
discovery = create_discovery_document(server_name="praisonai-a2u")
|
|
679
|
+
discovery.add_provider(ProviderInfo(
|
|
680
|
+
type="a2u",
|
|
681
|
+
name="A2U Event Stream",
|
|
682
|
+
description="Agent-to-User event streaming",
|
|
683
|
+
capabilities=["subscribe", "stream"],
|
|
684
|
+
))
|
|
685
|
+
|
|
686
|
+
app = FastAPI(
|
|
687
|
+
title="PraisonAI A2U Server",
|
|
688
|
+
description="A2U event stream server",
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
add_discovery_routes(app, discovery)
|
|
692
|
+
create_a2u_routes(app)
|
|
693
|
+
|
|
694
|
+
discovery.add_endpoint(EndpointInfo(
|
|
695
|
+
name="events",
|
|
696
|
+
description="Agent event stream",
|
|
697
|
+
provider_type="a2u",
|
|
698
|
+
streaming=["sse"],
|
|
699
|
+
))
|
|
700
|
+
|
|
701
|
+
@app.get("/")
|
|
702
|
+
async def root():
|
|
703
|
+
return {
|
|
704
|
+
"message": "PraisonAI A2U Server",
|
|
705
|
+
"events": "/a2u/events/<stream>",
|
|
706
|
+
"discovery": "/__praisonai__/discovery",
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return app
|
|
710
|
+
|
|
711
|
+
def cmd_unified(self, args: List[str]) -> int:
|
|
712
|
+
"""Launch unified server with all providers."""
|
|
713
|
+
spec = {
|
|
714
|
+
"host": {"default": self.DEFAULT_HOST},
|
|
715
|
+
"port": {"default": self.DEFAULT_PORT, "type": "int"},
|
|
716
|
+
"file": {"default": "agents.yaml"},
|
|
717
|
+
"reload": {"flag": True, "default": False},
|
|
718
|
+
"api_key": {"default": None},
|
|
719
|
+
}
|
|
720
|
+
parsed = self._parse_args(args, spec)
|
|
721
|
+
|
|
722
|
+
try:
|
|
723
|
+
self._print_success(f"Starting unified server on {parsed['host']}:{parsed['port']}")
|
|
724
|
+
print(" Providers: agents-api, recipe, mcp, a2a, a2u")
|
|
725
|
+
print(" Discovery: /__praisonai__/discovery")
|
|
726
|
+
|
|
727
|
+
app = self._create_unified_app(parsed)
|
|
728
|
+
self._run_server(app, parsed["host"], parsed["port"], parsed["reload"])
|
|
729
|
+
|
|
730
|
+
except ImportError as e:
|
|
731
|
+
self._print_error(f"Missing dependency: {e}")
|
|
732
|
+
print("Install with: pip install praisonai[serve]")
|
|
733
|
+
return self.EXIT_GENERAL_ERROR
|
|
734
|
+
except Exception as e:
|
|
735
|
+
self._print_error(str(e))
|
|
736
|
+
return self.EXIT_GENERAL_ERROR
|
|
737
|
+
|
|
738
|
+
return self.EXIT_SUCCESS
|
|
739
|
+
|
|
740
|
+
def _create_unified_app(self, config: Dict[str, Any]) -> Any:
|
|
741
|
+
"""Create unified FastAPI app with all providers."""
|
|
742
|
+
from fastapi import FastAPI
|
|
743
|
+
|
|
744
|
+
from praisonai.endpoints.discovery import (
|
|
745
|
+
create_discovery_document,
|
|
746
|
+
EndpointInfo,
|
|
747
|
+
ProviderInfo,
|
|
748
|
+
)
|
|
749
|
+
from praisonai.endpoints.server import add_discovery_routes
|
|
750
|
+
from praisonai.endpoints.a2u_server import create_a2u_routes
|
|
751
|
+
|
|
752
|
+
discovery = create_discovery_document(server_name="praisonai-unified")
|
|
753
|
+
|
|
754
|
+
# Add all providers
|
|
755
|
+
discovery.add_provider(ProviderInfo(
|
|
756
|
+
type="agents-api",
|
|
757
|
+
name="Agents API",
|
|
758
|
+
capabilities=["invoke", "health"],
|
|
759
|
+
))
|
|
760
|
+
discovery.add_provider(ProviderInfo(
|
|
761
|
+
type="recipe",
|
|
762
|
+
name="Recipe Runner",
|
|
763
|
+
capabilities=["list", "describe", "invoke", "stream"],
|
|
764
|
+
))
|
|
765
|
+
discovery.add_provider(ProviderInfo(
|
|
766
|
+
type="mcp",
|
|
767
|
+
name="MCP Server",
|
|
768
|
+
capabilities=["list-tools", "call-tool"],
|
|
769
|
+
))
|
|
770
|
+
discovery.add_provider(ProviderInfo(
|
|
771
|
+
type="a2a",
|
|
772
|
+
name="A2A Protocol",
|
|
773
|
+
capabilities=["agent-card", "message-send"],
|
|
774
|
+
))
|
|
775
|
+
discovery.add_provider(ProviderInfo(
|
|
776
|
+
type="a2u",
|
|
777
|
+
name="A2U Event Stream",
|
|
778
|
+
capabilities=["subscribe", "stream"],
|
|
779
|
+
))
|
|
780
|
+
|
|
781
|
+
app = FastAPI(
|
|
782
|
+
title="PraisonAI Unified Server",
|
|
783
|
+
description="Unified server with all PraisonAI providers",
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
add_discovery_routes(app, discovery)
|
|
787
|
+
create_a2u_routes(app)
|
|
788
|
+
|
|
789
|
+
# Add sample endpoints
|
|
790
|
+
discovery.add_endpoint(EndpointInfo(
|
|
791
|
+
name="agents",
|
|
792
|
+
description="Agents workflow endpoint",
|
|
793
|
+
provider_type="agents-api",
|
|
794
|
+
))
|
|
795
|
+
discovery.add_endpoint(EndpointInfo(
|
|
796
|
+
name="events",
|
|
797
|
+
description="Agent event stream",
|
|
798
|
+
provider_type="a2u",
|
|
799
|
+
streaming=["sse"],
|
|
800
|
+
))
|
|
801
|
+
|
|
802
|
+
@app.get("/")
|
|
803
|
+
async def root():
|
|
804
|
+
return {
|
|
805
|
+
"message": "PraisonAI Unified Server",
|
|
806
|
+
"providers": ["agents-api", "recipe", "mcp", "a2a", "a2u"],
|
|
807
|
+
"discovery": "/__praisonai__/discovery",
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
@app.get("/.well-known/agent.json")
|
|
811
|
+
async def agent_card():
|
|
812
|
+
return {
|
|
813
|
+
"name": "PraisonAI Unified",
|
|
814
|
+
"description": "PraisonAI Unified Server",
|
|
815
|
+
"version": "1.0.0",
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return app
|
|
819
|
+
|
|
820
|
+
def _run_server(self, app: Any, host: str, port: int, reload: bool) -> None:
|
|
821
|
+
"""Run the server with uvicorn."""
|
|
822
|
+
import uvicorn
|
|
823
|
+
uvicorn.run(app, host=host, port=port, reload=reload)
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
def handle_serve_command(args: List[str]) -> int:
|
|
827
|
+
"""Entry point for serve command."""
|
|
828
|
+
handler = ServeHandler()
|
|
829
|
+
return handler.handle(args)
|