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,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Recipe Provider
|
|
3
|
+
|
|
4
|
+
Provider adapter for recipe runner endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Iterator, List, Optional
|
|
8
|
+
|
|
9
|
+
from .base import BaseProvider, InvokeResult, HealthResult
|
|
10
|
+
from ..discovery import EndpointInfo, ProviderInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RecipeProvider(BaseProvider):
|
|
14
|
+
"""
|
|
15
|
+
Provider adapter for recipe runner endpoints.
|
|
16
|
+
|
|
17
|
+
Connects to recipe runner server (Starlette-based) and provides
|
|
18
|
+
unified discovery and invocation interface.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
provider_type = "recipe"
|
|
22
|
+
|
|
23
|
+
def get_provider_info(self) -> ProviderInfo:
|
|
24
|
+
"""Get provider information."""
|
|
25
|
+
return ProviderInfo(
|
|
26
|
+
type=self.provider_type,
|
|
27
|
+
name="Recipe Runner",
|
|
28
|
+
description="Recipe execution endpoints",
|
|
29
|
+
capabilities=["list", "describe", "invoke", "stream", "validate"],
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def list_endpoints(self, tags: Optional[List[str]] = None) -> List[EndpointInfo]:
|
|
33
|
+
"""List available recipe endpoints."""
|
|
34
|
+
path = "/v1/recipes"
|
|
35
|
+
if tags:
|
|
36
|
+
path += f"?tags={','.join(tags)}"
|
|
37
|
+
|
|
38
|
+
result = self._make_request("GET", path)
|
|
39
|
+
|
|
40
|
+
if result.get("error"):
|
|
41
|
+
return []
|
|
42
|
+
|
|
43
|
+
recipes = result.get("data", {}).get("recipes", [])
|
|
44
|
+
endpoints = []
|
|
45
|
+
|
|
46
|
+
for r in recipes:
|
|
47
|
+
endpoints.append(EndpointInfo(
|
|
48
|
+
name=r.get("name", ""),
|
|
49
|
+
description=r.get("description", ""),
|
|
50
|
+
provider_type=self.provider_type,
|
|
51
|
+
tags=r.get("tags", []),
|
|
52
|
+
version=r.get("version", "1.0.0"),
|
|
53
|
+
streaming=["none", "sse"],
|
|
54
|
+
auth_modes=["none", "api-key"],
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
return endpoints
|
|
58
|
+
|
|
59
|
+
def describe_endpoint(self, name: str) -> Optional[EndpointInfo]:
|
|
60
|
+
"""Get detailed information about a recipe endpoint."""
|
|
61
|
+
result = self._make_request("GET", f"/v1/recipes/{name}")
|
|
62
|
+
|
|
63
|
+
if result.get("status") == 404 or result.get("error"):
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
data = result.get("data", {})
|
|
67
|
+
|
|
68
|
+
# Get schema
|
|
69
|
+
schema_result = self._make_request("GET", f"/v1/recipes/{name}/schema")
|
|
70
|
+
schema_data = schema_result.get("data", {}) if not schema_result.get("error") else {}
|
|
71
|
+
|
|
72
|
+
return EndpointInfo(
|
|
73
|
+
name=data.get("name", name),
|
|
74
|
+
description=data.get("description", ""),
|
|
75
|
+
provider_type=self.provider_type,
|
|
76
|
+
tags=data.get("tags", []),
|
|
77
|
+
version=data.get("version", "1.0.0"),
|
|
78
|
+
input_schema=schema_data.get("input_schema"),
|
|
79
|
+
output_schema=schema_data.get("output_schema"),
|
|
80
|
+
streaming=["none", "sse"],
|
|
81
|
+
auth_modes=["none", "api-key"],
|
|
82
|
+
metadata=data.get("metadata", {}),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def invoke(
|
|
86
|
+
self,
|
|
87
|
+
name: str,
|
|
88
|
+
input_data: Optional[Dict[str, Any]] = None,
|
|
89
|
+
config: Optional[Dict[str, Any]] = None,
|
|
90
|
+
stream: bool = False,
|
|
91
|
+
) -> InvokeResult:
|
|
92
|
+
"""Invoke a recipe endpoint."""
|
|
93
|
+
body = {
|
|
94
|
+
"recipe": name,
|
|
95
|
+
"input": input_data or {},
|
|
96
|
+
"config": config or {},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
result = self._make_request("POST", "/v1/recipes/run", json_data=body)
|
|
100
|
+
|
|
101
|
+
if result.get("status") == 401:
|
|
102
|
+
return InvokeResult(
|
|
103
|
+
ok=False,
|
|
104
|
+
status="auth_error",
|
|
105
|
+
error="Authentication required",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if result.get("status") == 404:
|
|
109
|
+
return InvokeResult(
|
|
110
|
+
ok=False,
|
|
111
|
+
status="not_found",
|
|
112
|
+
error=f"Recipe not found: {name}",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if result.get("error"):
|
|
116
|
+
return InvokeResult(
|
|
117
|
+
ok=False,
|
|
118
|
+
status="error",
|
|
119
|
+
error=result["error"].get("message", str(result["error"])),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
data = result.get("data", {})
|
|
123
|
+
return InvokeResult(
|
|
124
|
+
ok=data.get("ok", True),
|
|
125
|
+
status=data.get("status", "success"),
|
|
126
|
+
data=data.get("output"),
|
|
127
|
+
metadata={"run_id": data.get("run_id")},
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def invoke_stream(
|
|
131
|
+
self,
|
|
132
|
+
name: str,
|
|
133
|
+
input_data: Optional[Dict[str, Any]] = None,
|
|
134
|
+
config: Optional[Dict[str, Any]] = None,
|
|
135
|
+
) -> Iterator[Dict[str, Any]]:
|
|
136
|
+
"""Invoke a recipe endpoint with streaming."""
|
|
137
|
+
import json
|
|
138
|
+
import urllib.request
|
|
139
|
+
|
|
140
|
+
body = {
|
|
141
|
+
"recipe": name,
|
|
142
|
+
"input": input_data or {},
|
|
143
|
+
"config": config or {},
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
full_url = f"{self.base_url}/v1/recipes/stream"
|
|
147
|
+
|
|
148
|
+
headers = {
|
|
149
|
+
"Content-Type": "application/json",
|
|
150
|
+
"Accept": "text/event-stream",
|
|
151
|
+
}
|
|
152
|
+
if self.api_key:
|
|
153
|
+
headers["X-API-Key"] = self.api_key
|
|
154
|
+
|
|
155
|
+
data = json.dumps(body).encode("utf-8")
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
req = urllib.request.Request(full_url, data=data, headers=headers, method="POST")
|
|
159
|
+
|
|
160
|
+
with urllib.request.urlopen(req, timeout=300) as response:
|
|
161
|
+
buffer = ""
|
|
162
|
+
for line in response:
|
|
163
|
+
line = line.decode("utf-8")
|
|
164
|
+
buffer += line
|
|
165
|
+
|
|
166
|
+
if buffer.endswith("\n\n"):
|
|
167
|
+
event_type = "message"
|
|
168
|
+
event_data = ""
|
|
169
|
+
|
|
170
|
+
for part in buffer.strip().split("\n"):
|
|
171
|
+
if part.startswith("event:"):
|
|
172
|
+
event_type = part[6:].strip()
|
|
173
|
+
elif part.startswith("data:"):
|
|
174
|
+
event_data = part[5:].strip()
|
|
175
|
+
|
|
176
|
+
if event_data:
|
|
177
|
+
try:
|
|
178
|
+
yield {"event": event_type, "data": json.loads(event_data)}
|
|
179
|
+
except json.JSONDecodeError:
|
|
180
|
+
yield {"event": event_type, "data": event_data}
|
|
181
|
+
|
|
182
|
+
buffer = ""
|
|
183
|
+
|
|
184
|
+
except Exception as e:
|
|
185
|
+
yield {"event": "error", "data": {"error": str(e)}}
|
|
186
|
+
|
|
187
|
+
def health(self) -> HealthResult:
|
|
188
|
+
"""Check recipe server health."""
|
|
189
|
+
result = self._make_request("GET", "/health")
|
|
190
|
+
|
|
191
|
+
if result.get("error"):
|
|
192
|
+
return HealthResult(
|
|
193
|
+
healthy=False,
|
|
194
|
+
status="unhealthy",
|
|
195
|
+
provider_type=self.provider_type,
|
|
196
|
+
metadata={"error": result["error"].get("message", str(result["error"]))},
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
data = result.get("data", {})
|
|
200
|
+
return HealthResult(
|
|
201
|
+
healthy=data.get("status") == "healthy",
|
|
202
|
+
status=data.get("status", "unknown"),
|
|
203
|
+
server_name=data.get("service"),
|
|
204
|
+
server_version=data.get("version"),
|
|
205
|
+
provider_type=self.provider_type,
|
|
206
|
+
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tools MCP Provider
|
|
3
|
+
|
|
4
|
+
Provider adapter for tools exposed as MCP server.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Iterator, List, Optional
|
|
8
|
+
|
|
9
|
+
from .base import BaseProvider, InvokeResult, HealthResult
|
|
10
|
+
from ..discovery import EndpointInfo, ProviderInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ToolsMCPProvider(BaseProvider):
|
|
14
|
+
"""
|
|
15
|
+
Provider adapter for tools exposed as MCP server.
|
|
16
|
+
|
|
17
|
+
This provider connects to a ToolsMCPServer that exposes Python functions
|
|
18
|
+
as MCP tools.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
provider_type = "tools-mcp"
|
|
22
|
+
|
|
23
|
+
def get_provider_info(self) -> ProviderInfo:
|
|
24
|
+
"""Get provider information."""
|
|
25
|
+
return ProviderInfo(
|
|
26
|
+
type=self.provider_type,
|
|
27
|
+
name="Tools MCP Server",
|
|
28
|
+
description="Python tools exposed as MCP server",
|
|
29
|
+
capabilities=["list-tools", "call-tool"],
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def list_endpoints(self, tags: Optional[List[str]] = None) -> List[EndpointInfo]:
|
|
33
|
+
"""List available tools as endpoints."""
|
|
34
|
+
# Try unified discovery first
|
|
35
|
+
result = self._make_request("GET", "/__praisonai__/discovery")
|
|
36
|
+
|
|
37
|
+
if not result.get("error") and result.get("data"):
|
|
38
|
+
data = result.get("data", {})
|
|
39
|
+
endpoints = []
|
|
40
|
+
for ep in data.get("endpoints", []):
|
|
41
|
+
if ep.get("provider_type") == self.provider_type:
|
|
42
|
+
endpoints.append(EndpointInfo(
|
|
43
|
+
name=ep.get("name", ""),
|
|
44
|
+
description=ep.get("description", ""),
|
|
45
|
+
provider_type=self.provider_type,
|
|
46
|
+
tags=ep.get("tags", []),
|
|
47
|
+
input_schema=ep.get("input_schema"),
|
|
48
|
+
streaming=ep.get("streaming", ["none"]),
|
|
49
|
+
auth_modes=ep.get("auth_modes", ["none"]),
|
|
50
|
+
))
|
|
51
|
+
return endpoints
|
|
52
|
+
|
|
53
|
+
# Fallback: try tools endpoint
|
|
54
|
+
result = self._make_request("GET", "/tools")
|
|
55
|
+
|
|
56
|
+
if result.get("error"):
|
|
57
|
+
return []
|
|
58
|
+
|
|
59
|
+
tools = result.get("data", {}).get("tools", [])
|
|
60
|
+
endpoints = []
|
|
61
|
+
|
|
62
|
+
for tool in tools:
|
|
63
|
+
endpoints.append(EndpointInfo(
|
|
64
|
+
name=tool.get("name", ""),
|
|
65
|
+
description=tool.get("description", ""),
|
|
66
|
+
provider_type=self.provider_type,
|
|
67
|
+
input_schema=tool.get("input_schema"),
|
|
68
|
+
streaming=["none"],
|
|
69
|
+
auth_modes=["none"],
|
|
70
|
+
))
|
|
71
|
+
|
|
72
|
+
return endpoints
|
|
73
|
+
|
|
74
|
+
def describe_endpoint(self, name: str) -> Optional[EndpointInfo]:
|
|
75
|
+
"""Get detailed information about a tool."""
|
|
76
|
+
endpoints = self.list_endpoints()
|
|
77
|
+
for ep in endpoints:
|
|
78
|
+
if ep.name == name:
|
|
79
|
+
return ep
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
def invoke(
|
|
83
|
+
self,
|
|
84
|
+
name: str,
|
|
85
|
+
input_data: Optional[Dict[str, Any]] = None,
|
|
86
|
+
config: Optional[Dict[str, Any]] = None,
|
|
87
|
+
stream: bool = False,
|
|
88
|
+
) -> InvokeResult:
|
|
89
|
+
"""Invoke a tool."""
|
|
90
|
+
body = {
|
|
91
|
+
"tool": name,
|
|
92
|
+
"arguments": input_data or {},
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
result = self._make_request("POST", "/tools/call", json_data=body)
|
|
96
|
+
|
|
97
|
+
if result.get("status") == 404:
|
|
98
|
+
return InvokeResult(
|
|
99
|
+
ok=False,
|
|
100
|
+
status="not_found",
|
|
101
|
+
error=f"Tool not found: {name}",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if result.get("error"):
|
|
105
|
+
return InvokeResult(
|
|
106
|
+
ok=False,
|
|
107
|
+
status="error",
|
|
108
|
+
error=result["error"].get("message", str(result["error"])),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
data = result.get("data", {})
|
|
112
|
+
return InvokeResult(
|
|
113
|
+
ok=True,
|
|
114
|
+
status="success",
|
|
115
|
+
data=data.get("result", data),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def invoke_stream(
|
|
119
|
+
self,
|
|
120
|
+
name: str,
|
|
121
|
+
input_data: Optional[Dict[str, Any]] = None,
|
|
122
|
+
config: Optional[Dict[str, Any]] = None,
|
|
123
|
+
) -> Iterator[Dict[str, Any]]:
|
|
124
|
+
"""Invoke tool with streaming (wraps sync call)."""
|
|
125
|
+
result = self.invoke(name, input_data, config)
|
|
126
|
+
if result.ok:
|
|
127
|
+
yield {"event": "result", "data": result.data}
|
|
128
|
+
else:
|
|
129
|
+
yield {"event": "error", "data": {"error": result.error}}
|
|
130
|
+
|
|
131
|
+
def health(self) -> HealthResult:
|
|
132
|
+
"""Check tools server health."""
|
|
133
|
+
result = self._make_request("GET", "/health")
|
|
134
|
+
|
|
135
|
+
if result.get("error"):
|
|
136
|
+
return HealthResult(
|
|
137
|
+
healthy=False,
|
|
138
|
+
status="unhealthy",
|
|
139
|
+
provider_type=self.provider_type,
|
|
140
|
+
metadata={"error": result["error"].get("message", str(result["error"]))},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
data = result.get("data", {})
|
|
144
|
+
return HealthResult(
|
|
145
|
+
healthy=True,
|
|
146
|
+
status="healthy",
|
|
147
|
+
server_name=data.get("server_name", "Tools MCP Server"),
|
|
148
|
+
server_version=data.get("version"),
|
|
149
|
+
provider_type=self.provider_type,
|
|
150
|
+
)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provider Registry
|
|
3
|
+
|
|
4
|
+
Central registry for provider adapters.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Optional, Type
|
|
8
|
+
|
|
9
|
+
from .providers.base import BaseProvider
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Global provider registry
|
|
13
|
+
_providers: Dict[str, Type[BaseProvider]] = {}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def register_provider(provider_type: str, provider_class: Type[BaseProvider]) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Register a provider class.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
provider_type: Provider type identifier
|
|
22
|
+
provider_class: Provider class to register
|
|
23
|
+
"""
|
|
24
|
+
_providers[provider_type] = provider_class
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_provider(
|
|
28
|
+
provider_type: str,
|
|
29
|
+
base_url: str = "http://localhost:8765",
|
|
30
|
+
api_key: Optional[str] = None,
|
|
31
|
+
**kwargs,
|
|
32
|
+
) -> Optional[BaseProvider]:
|
|
33
|
+
"""
|
|
34
|
+
Get a provider instance by type.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
provider_type: Provider type identifier
|
|
38
|
+
base_url: Base URL for the provider
|
|
39
|
+
api_key: Optional API key
|
|
40
|
+
**kwargs: Additional provider-specific arguments
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Provider instance or None if not found
|
|
44
|
+
"""
|
|
45
|
+
# Lazy register built-in providers
|
|
46
|
+
_ensure_providers_registered()
|
|
47
|
+
|
|
48
|
+
if provider_type not in _providers:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
return _providers[provider_type](base_url=base_url, api_key=api_key, **kwargs)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def list_provider_types() -> List[str]:
|
|
55
|
+
"""
|
|
56
|
+
List all registered provider types.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
List of provider type identifiers
|
|
60
|
+
"""
|
|
61
|
+
_ensure_providers_registered()
|
|
62
|
+
return list(_providers.keys())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_provider_class(provider_type: str) -> Optional[Type[BaseProvider]]:
|
|
66
|
+
"""
|
|
67
|
+
Get a provider class by type.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
provider_type: Provider type identifier
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Provider class or None if not found
|
|
74
|
+
"""
|
|
75
|
+
_ensure_providers_registered()
|
|
76
|
+
return _providers.get(provider_type)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _ensure_providers_registered() -> None:
|
|
80
|
+
"""Ensure built-in providers are registered."""
|
|
81
|
+
if _providers:
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Lazy import and register built-in providers
|
|
85
|
+
from .providers.recipe import RecipeProvider
|
|
86
|
+
from .providers.agents_api import AgentsAPIProvider
|
|
87
|
+
from .providers.mcp import MCPProvider
|
|
88
|
+
from .providers.tools_mcp import ToolsMCPProvider
|
|
89
|
+
from .providers.a2a import A2AProvider
|
|
90
|
+
from .providers.a2u import A2UProvider
|
|
91
|
+
|
|
92
|
+
register_provider("recipe", RecipeProvider)
|
|
93
|
+
register_provider("agents-api", AgentsAPIProvider)
|
|
94
|
+
register_provider("mcp", MCPProvider)
|
|
95
|
+
register_provider("tools-mcp", ToolsMCPProvider)
|
|
96
|
+
register_provider("a2a", A2AProvider)
|
|
97
|
+
register_provider("a2u", A2UProvider)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ProviderRegistry:
|
|
101
|
+
"""
|
|
102
|
+
Provider registry class for managing provider instances.
|
|
103
|
+
|
|
104
|
+
This class provides a more object-oriented interface to the provider registry.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
def __init__(self):
|
|
108
|
+
"""Initialize the registry."""
|
|
109
|
+
_ensure_providers_registered()
|
|
110
|
+
|
|
111
|
+
def get(
|
|
112
|
+
self,
|
|
113
|
+
provider_type: str,
|
|
114
|
+
base_url: str = "http://localhost:8765",
|
|
115
|
+
api_key: Optional[str] = None,
|
|
116
|
+
**kwargs,
|
|
117
|
+
) -> Optional[BaseProvider]:
|
|
118
|
+
"""Get a provider instance."""
|
|
119
|
+
return get_provider(provider_type, base_url, api_key, **kwargs)
|
|
120
|
+
|
|
121
|
+
def register(self, provider_type: str, provider_class: Type[BaseProvider]) -> None:
|
|
122
|
+
"""Register a provider class."""
|
|
123
|
+
register_provider(provider_type, provider_class)
|
|
124
|
+
|
|
125
|
+
def list_types(self) -> List[str]:
|
|
126
|
+
"""List all provider types."""
|
|
127
|
+
return list_provider_types()
|
|
128
|
+
|
|
129
|
+
def get_class(self, provider_type: str) -> Optional[Type[BaseProvider]]:
|
|
130
|
+
"""Get a provider class."""
|
|
131
|
+
return get_provider_class(provider_type)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified Server Utilities
|
|
3
|
+
|
|
4
|
+
Provides utilities for adding discovery endpoints to any server.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, List, Optional
|
|
8
|
+
|
|
9
|
+
from .discovery import (
|
|
10
|
+
DiscoveryDocument,
|
|
11
|
+
EndpointInfo,
|
|
12
|
+
ProviderInfo,
|
|
13
|
+
SCHEMA_VERSION,
|
|
14
|
+
create_discovery_document,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def add_discovery_routes(
|
|
19
|
+
app: Any,
|
|
20
|
+
discovery: DiscoveryDocument,
|
|
21
|
+
path: str = "/__praisonai__/discovery",
|
|
22
|
+
) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Add unified discovery routes to a Starlette/FastAPI application.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
app: Starlette or FastAPI application
|
|
28
|
+
discovery: DiscoveryDocument to serve
|
|
29
|
+
path: Path for discovery endpoint
|
|
30
|
+
"""
|
|
31
|
+
try:
|
|
32
|
+
from starlette.responses import JSONResponse
|
|
33
|
+
from starlette.routing import Route
|
|
34
|
+
except ImportError:
|
|
35
|
+
# Try FastAPI
|
|
36
|
+
try:
|
|
37
|
+
from fastapi.responses import JSONResponse
|
|
38
|
+
except ImportError:
|
|
39
|
+
raise ImportError("Starlette or FastAPI required for discovery routes")
|
|
40
|
+
|
|
41
|
+
async def discovery_handler(request):
|
|
42
|
+
"""Return discovery document."""
|
|
43
|
+
return JSONResponse(discovery.to_dict())
|
|
44
|
+
|
|
45
|
+
async def health_handler(request):
|
|
46
|
+
"""Return health status with discovery info."""
|
|
47
|
+
return JSONResponse({
|
|
48
|
+
"status": "healthy",
|
|
49
|
+
"schema_version": SCHEMA_VERSION,
|
|
50
|
+
"server_name": discovery.server_name,
|
|
51
|
+
"server_version": discovery.server_version,
|
|
52
|
+
"providers": [p.type for p in discovery.providers],
|
|
53
|
+
"endpoint_count": len(discovery.endpoints),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
# Add routes based on app type
|
|
57
|
+
if hasattr(app, 'add_api_route'):
|
|
58
|
+
# FastAPI
|
|
59
|
+
app.add_api_route(path, discovery_handler, methods=["GET"])
|
|
60
|
+
if not _has_route(app, "/health"):
|
|
61
|
+
app.add_api_route("/health", health_handler, methods=["GET"])
|
|
62
|
+
elif hasattr(app, 'routes'):
|
|
63
|
+
# Starlette
|
|
64
|
+
app.routes.append(Route(path, discovery_handler, methods=["GET"]))
|
|
65
|
+
if not _has_route(app, "/health"):
|
|
66
|
+
app.routes.append(Route("/health", health_handler, methods=["GET"]))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _has_route(app: Any, path: str) -> bool:
|
|
70
|
+
"""Check if app already has a route at path."""
|
|
71
|
+
if hasattr(app, 'routes'):
|
|
72
|
+
for route in app.routes:
|
|
73
|
+
if hasattr(route, 'path') and route.path == path:
|
|
74
|
+
return True
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def create_unified_app(
|
|
79
|
+
providers: Optional[List[str]] = None,
|
|
80
|
+
server_name: str = "praisonai",
|
|
81
|
+
host: str = "127.0.0.1",
|
|
82
|
+
port: int = 8765,
|
|
83
|
+
cors_origins: Optional[List[str]] = None,
|
|
84
|
+
api_key: Optional[str] = None,
|
|
85
|
+
) -> Any:
|
|
86
|
+
"""
|
|
87
|
+
Create a unified server application with discovery support.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
providers: List of provider types to enable
|
|
91
|
+
server_name: Server name for discovery
|
|
92
|
+
host: Server host
|
|
93
|
+
port: Server port
|
|
94
|
+
cors_origins: CORS allowed origins
|
|
95
|
+
api_key: Optional API key for authentication
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
FastAPI application
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
from fastapi import FastAPI
|
|
102
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
103
|
+
except ImportError:
|
|
104
|
+
raise ImportError("FastAPI required. Install with: pip install fastapi")
|
|
105
|
+
|
|
106
|
+
# Create discovery document
|
|
107
|
+
discovery = create_discovery_document(server_name=server_name)
|
|
108
|
+
|
|
109
|
+
# Create FastAPI app
|
|
110
|
+
app = FastAPI(
|
|
111
|
+
title=f"{server_name} Unified API",
|
|
112
|
+
description="Unified PraisonAI endpoints server",
|
|
113
|
+
version=discovery.server_version,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Add CORS if configured
|
|
117
|
+
if cors_origins:
|
|
118
|
+
app.add_middleware(
|
|
119
|
+
CORSMiddleware,
|
|
120
|
+
allow_origins=cors_origins,
|
|
121
|
+
allow_methods=["*"],
|
|
122
|
+
allow_headers=["*"],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Add discovery routes
|
|
126
|
+
add_discovery_routes(app, discovery)
|
|
127
|
+
|
|
128
|
+
# Store discovery document for later modification
|
|
129
|
+
app.state.discovery = discovery
|
|
130
|
+
|
|
131
|
+
return app
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def register_endpoint_to_discovery(
|
|
135
|
+
app: Any,
|
|
136
|
+
endpoint: EndpointInfo,
|
|
137
|
+
) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Register an endpoint to the app's discovery document.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
app: FastAPI/Starlette app with discovery
|
|
143
|
+
endpoint: EndpointInfo to register
|
|
144
|
+
"""
|
|
145
|
+
if hasattr(app, 'state') and hasattr(app.state, 'discovery'):
|
|
146
|
+
app.state.discovery.add_endpoint(endpoint)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def register_provider_to_discovery(
|
|
150
|
+
app: Any,
|
|
151
|
+
provider: ProviderInfo,
|
|
152
|
+
) -> None:
|
|
153
|
+
"""
|
|
154
|
+
Register a provider to the app's discovery document.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
app: FastAPI/Starlette app with discovery
|
|
158
|
+
provider: ProviderInfo to register
|
|
159
|
+
"""
|
|
160
|
+
if hasattr(app, 'state') and hasattr(app.state, 'discovery'):
|
|
161
|
+
app.state.discovery.add_provider(provider)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Only try to import autogen_tools if either CrewAI or AG2 is available
|
|
2
|
+
CREWAI_AVAILABLE = False
|
|
3
|
+
AUTOGEN_AVAILABLE = False
|
|
4
|
+
PRAISONAI_TOOLS_AVAILABLE = False
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from crewai import Agent, Task, Crew
|
|
8
|
+
CREWAI_AVAILABLE = True
|
|
9
|
+
except ImportError:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import autogen
|
|
14
|
+
AUTOGEN_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
# Only try to import tools if a framework is available
|
|
19
|
+
if CREWAI_AVAILABLE or AUTOGEN_AVAILABLE:
|
|
20
|
+
try:
|
|
21
|
+
from .autogen_tools import *
|
|
22
|
+
PRAISONAI_TOOLS_AVAILABLE = True
|
|
23
|
+
except ImportError:
|
|
24
|
+
pass
|