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,426 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Doctor checks for serve and endpoints functionality.
|
|
3
|
+
|
|
4
|
+
Checks for:
|
|
5
|
+
- Serve module availability
|
|
6
|
+
- Endpoints module availability
|
|
7
|
+
- Server connectivity
|
|
8
|
+
- Discovery endpoint
|
|
9
|
+
- Provider types
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from ..models import CheckResult, CheckStatus, CheckCategory, CheckSeverity, DoctorConfig
|
|
15
|
+
from ..registry import register_check
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@register_check(
|
|
19
|
+
id="serve_module",
|
|
20
|
+
title="Serve Module",
|
|
21
|
+
description="Check if serve module is available",
|
|
22
|
+
category=CheckCategory.ENVIRONMENT,
|
|
23
|
+
severity=CheckSeverity.MEDIUM,
|
|
24
|
+
tags=["serve", "deploy"],
|
|
25
|
+
)
|
|
26
|
+
def check_serve_module(config: DoctorConfig) -> CheckResult:
|
|
27
|
+
"""Check if serve module is available."""
|
|
28
|
+
try:
|
|
29
|
+
from praisonai.cli.features.serve import ServeHandler
|
|
30
|
+
ServeHandler() # Test instantiation
|
|
31
|
+
return CheckResult(
|
|
32
|
+
id="serve_module",
|
|
33
|
+
title="Serve Module",
|
|
34
|
+
category=CheckCategory.ENVIRONMENT,
|
|
35
|
+
status=CheckStatus.PASS,
|
|
36
|
+
message="Serve module available",
|
|
37
|
+
metadata={"handler": "ServeHandler"},
|
|
38
|
+
)
|
|
39
|
+
except ImportError as e:
|
|
40
|
+
return CheckResult(
|
|
41
|
+
id="serve_module",
|
|
42
|
+
title="Serve Module",
|
|
43
|
+
category=CheckCategory.ENVIRONMENT,
|
|
44
|
+
status=CheckStatus.WARN,
|
|
45
|
+
message=f"Serve module not available: {e}",
|
|
46
|
+
remediation="pip install praisonai[serve]",
|
|
47
|
+
)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
return CheckResult(
|
|
50
|
+
id="serve_module",
|
|
51
|
+
title="Serve Module",
|
|
52
|
+
category=CheckCategory.ENVIRONMENT,
|
|
53
|
+
status=CheckStatus.ERROR,
|
|
54
|
+
message=f"Error checking serve module: {e}",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@register_check(
|
|
59
|
+
id="endpoints_module",
|
|
60
|
+
title="Endpoints Module",
|
|
61
|
+
description="Check if endpoints module is available",
|
|
62
|
+
category=CheckCategory.ENVIRONMENT,
|
|
63
|
+
severity=CheckSeverity.MEDIUM,
|
|
64
|
+
tags=["endpoints", "deploy"],
|
|
65
|
+
)
|
|
66
|
+
def check_endpoints_module(config: DoctorConfig) -> CheckResult:
|
|
67
|
+
"""Check if endpoints module is available."""
|
|
68
|
+
try:
|
|
69
|
+
from praisonai.endpoints import (
|
|
70
|
+
DiscoveryDocument,
|
|
71
|
+
EndpointInfo,
|
|
72
|
+
ProviderInfo,
|
|
73
|
+
list_provider_types,
|
|
74
|
+
)
|
|
75
|
+
types = list_provider_types()
|
|
76
|
+
return CheckResult(
|
|
77
|
+
id="endpoints_module",
|
|
78
|
+
title="Endpoints Module",
|
|
79
|
+
category=CheckCategory.ENVIRONMENT,
|
|
80
|
+
status=CheckStatus.PASS,
|
|
81
|
+
message=f"Endpoints module available ({len(types)} provider types)",
|
|
82
|
+
metadata={"provider_types": types},
|
|
83
|
+
)
|
|
84
|
+
except ImportError as e:
|
|
85
|
+
return CheckResult(
|
|
86
|
+
id="endpoints_module",
|
|
87
|
+
title="Endpoints Module",
|
|
88
|
+
category=CheckCategory.ENVIRONMENT,
|
|
89
|
+
status=CheckStatus.WARN,
|
|
90
|
+
message=f"Endpoints module not available: {e}",
|
|
91
|
+
remediation="pip install praisonai[serve]",
|
|
92
|
+
)
|
|
93
|
+
except Exception as e:
|
|
94
|
+
return CheckResult(
|
|
95
|
+
id="endpoints_module",
|
|
96
|
+
title="Endpoints Module",
|
|
97
|
+
category=CheckCategory.ENVIRONMENT,
|
|
98
|
+
status=CheckStatus.ERROR,
|
|
99
|
+
message=f"Error checking endpoints module: {e}",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@register_check(
|
|
104
|
+
id="endpoints_cli",
|
|
105
|
+
title="Endpoints CLI",
|
|
106
|
+
description="Check if endpoints CLI handler is available",
|
|
107
|
+
category=CheckCategory.ENVIRONMENT,
|
|
108
|
+
severity=CheckSeverity.LOW,
|
|
109
|
+
tags=["endpoints", "cli"],
|
|
110
|
+
)
|
|
111
|
+
def check_endpoints_cli(config: DoctorConfig) -> CheckResult:
|
|
112
|
+
"""Check if endpoints CLI handler is available."""
|
|
113
|
+
try:
|
|
114
|
+
from praisonai.cli.features.endpoints import EndpointsHandler
|
|
115
|
+
handler = EndpointsHandler()
|
|
116
|
+
return CheckResult(
|
|
117
|
+
id="endpoints_cli",
|
|
118
|
+
title="Endpoints CLI",
|
|
119
|
+
category=CheckCategory.ENVIRONMENT,
|
|
120
|
+
status=CheckStatus.PASS,
|
|
121
|
+
message="Endpoints CLI handler available",
|
|
122
|
+
metadata={"default_url": handler.DEFAULT_URL},
|
|
123
|
+
)
|
|
124
|
+
except ImportError as e:
|
|
125
|
+
return CheckResult(
|
|
126
|
+
id="endpoints_cli",
|
|
127
|
+
title="Endpoints CLI",
|
|
128
|
+
category=CheckCategory.ENVIRONMENT,
|
|
129
|
+
status=CheckStatus.WARN,
|
|
130
|
+
message=f"Endpoints CLI not available: {e}",
|
|
131
|
+
remediation="pip install praisonai",
|
|
132
|
+
)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
return CheckResult(
|
|
135
|
+
id="endpoints_cli",
|
|
136
|
+
title="Endpoints CLI",
|
|
137
|
+
category=CheckCategory.ENVIRONMENT,
|
|
138
|
+
status=CheckStatus.ERROR,
|
|
139
|
+
message=f"Error checking endpoints CLI: {e}",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@register_check(
|
|
144
|
+
id="server_connectivity",
|
|
145
|
+
title="Server Connectivity",
|
|
146
|
+
description="Check if a PraisonAI server is reachable",
|
|
147
|
+
category=CheckCategory.NETWORK,
|
|
148
|
+
severity=CheckSeverity.LOW,
|
|
149
|
+
requires_deep=True,
|
|
150
|
+
tags=["serve", "network"],
|
|
151
|
+
)
|
|
152
|
+
def check_server_connectivity(config: DoctorConfig) -> CheckResult:
|
|
153
|
+
"""Check if a PraisonAI server is reachable."""
|
|
154
|
+
import urllib.request
|
|
155
|
+
import urllib.error
|
|
156
|
+
|
|
157
|
+
url = os.environ.get("PRAISONAI_ENDPOINTS_URL", "http://localhost:8765")
|
|
158
|
+
health_url = f"{url}/health"
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
req = urllib.request.Request(health_url, method="GET")
|
|
162
|
+
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
163
|
+
if resp.status == 200:
|
|
164
|
+
return CheckResult(
|
|
165
|
+
id="server_connectivity",
|
|
166
|
+
title="Server Connectivity",
|
|
167
|
+
category=CheckCategory.NETWORK,
|
|
168
|
+
status=CheckStatus.PASS,
|
|
169
|
+
message=f"Server reachable at {url}",
|
|
170
|
+
metadata={"url": url, "status": resp.status},
|
|
171
|
+
)
|
|
172
|
+
else:
|
|
173
|
+
return CheckResult(
|
|
174
|
+
id="server_connectivity",
|
|
175
|
+
title="Server Connectivity",
|
|
176
|
+
category=CheckCategory.NETWORK,
|
|
177
|
+
status=CheckStatus.WARN,
|
|
178
|
+
message=f"Server returned status {resp.status}",
|
|
179
|
+
metadata={"url": url, "status": resp.status},
|
|
180
|
+
)
|
|
181
|
+
except urllib.error.URLError as e:
|
|
182
|
+
return CheckResult(
|
|
183
|
+
id="server_connectivity",
|
|
184
|
+
title="Server Connectivity",
|
|
185
|
+
category=CheckCategory.NETWORK,
|
|
186
|
+
status=CheckStatus.SKIP,
|
|
187
|
+
message=f"No server running at {url}",
|
|
188
|
+
details=str(e.reason),
|
|
189
|
+
remediation="Start a server: praisonai serve unified --port 8765",
|
|
190
|
+
)
|
|
191
|
+
except Exception as e:
|
|
192
|
+
return CheckResult(
|
|
193
|
+
id="server_connectivity",
|
|
194
|
+
title="Server Connectivity",
|
|
195
|
+
category=CheckCategory.NETWORK,
|
|
196
|
+
status=CheckStatus.ERROR,
|
|
197
|
+
message=f"Error checking server: {e}",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@register_check(
|
|
202
|
+
id="discovery_endpoint",
|
|
203
|
+
title="Discovery Endpoint",
|
|
204
|
+
description="Check if discovery endpoint is available",
|
|
205
|
+
category=CheckCategory.NETWORK,
|
|
206
|
+
severity=CheckSeverity.LOW,
|
|
207
|
+
requires_deep=True,
|
|
208
|
+
dependencies=["server_connectivity"],
|
|
209
|
+
tags=["serve", "discovery"],
|
|
210
|
+
)
|
|
211
|
+
def check_discovery_endpoint(config: DoctorConfig) -> CheckResult:
|
|
212
|
+
"""Check if discovery endpoint is available."""
|
|
213
|
+
import urllib.request
|
|
214
|
+
import urllib.error
|
|
215
|
+
import json
|
|
216
|
+
|
|
217
|
+
url = os.environ.get("PRAISONAI_ENDPOINTS_URL", "http://localhost:8765")
|
|
218
|
+
discovery_url = f"{url}/__praisonai__/discovery"
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
req = urllib.request.Request(discovery_url, method="GET")
|
|
222
|
+
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
223
|
+
if resp.status == 200:
|
|
224
|
+
data = json.loads(resp.read().decode())
|
|
225
|
+
providers = data.get("providers", [])
|
|
226
|
+
endpoints = data.get("endpoints", [])
|
|
227
|
+
return CheckResult(
|
|
228
|
+
id="discovery_endpoint",
|
|
229
|
+
title="Discovery Endpoint",
|
|
230
|
+
category=CheckCategory.NETWORK,
|
|
231
|
+
status=CheckStatus.PASS,
|
|
232
|
+
message=f"Discovery available: {len(providers)} providers, {len(endpoints)} endpoints",
|
|
233
|
+
metadata={
|
|
234
|
+
"url": discovery_url,
|
|
235
|
+
"schema_version": data.get("schema_version"),
|
|
236
|
+
"server_name": data.get("server_name"),
|
|
237
|
+
"providers": [p.get("type") for p in providers],
|
|
238
|
+
},
|
|
239
|
+
)
|
|
240
|
+
else:
|
|
241
|
+
return CheckResult(
|
|
242
|
+
id="discovery_endpoint",
|
|
243
|
+
title="Discovery Endpoint",
|
|
244
|
+
category=CheckCategory.NETWORK,
|
|
245
|
+
status=CheckStatus.WARN,
|
|
246
|
+
message=f"Discovery returned status {resp.status}",
|
|
247
|
+
)
|
|
248
|
+
except urllib.error.URLError:
|
|
249
|
+
return CheckResult(
|
|
250
|
+
id="discovery_endpoint",
|
|
251
|
+
title="Discovery Endpoint",
|
|
252
|
+
category=CheckCategory.NETWORK,
|
|
253
|
+
status=CheckStatus.SKIP,
|
|
254
|
+
message="No server running (skipped)",
|
|
255
|
+
)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
return CheckResult(
|
|
258
|
+
id="discovery_endpoint",
|
|
259
|
+
title="Discovery Endpoint",
|
|
260
|
+
category=CheckCategory.NETWORK,
|
|
261
|
+
status=CheckStatus.ERROR,
|
|
262
|
+
message=f"Error checking discovery: {e}",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@register_check(
|
|
267
|
+
id="a2u_module",
|
|
268
|
+
title="A2U Module",
|
|
269
|
+
description="Check if A2U server module is available",
|
|
270
|
+
category=CheckCategory.ENVIRONMENT,
|
|
271
|
+
severity=CheckSeverity.LOW,
|
|
272
|
+
tags=["serve", "a2u"],
|
|
273
|
+
)
|
|
274
|
+
def check_a2u_module(config: DoctorConfig) -> CheckResult:
|
|
275
|
+
"""Check if A2U server module is available."""
|
|
276
|
+
try:
|
|
277
|
+
from praisonai.endpoints.a2u_server import (
|
|
278
|
+
A2UEvent,
|
|
279
|
+
A2USubscription,
|
|
280
|
+
A2UEventBus,
|
|
281
|
+
create_a2u_routes,
|
|
282
|
+
)
|
|
283
|
+
return CheckResult(
|
|
284
|
+
id="a2u_module",
|
|
285
|
+
title="A2U Module",
|
|
286
|
+
category=CheckCategory.ENVIRONMENT,
|
|
287
|
+
status=CheckStatus.PASS,
|
|
288
|
+
message="A2U server module available",
|
|
289
|
+
)
|
|
290
|
+
except ImportError as e:
|
|
291
|
+
return CheckResult(
|
|
292
|
+
id="a2u_module",
|
|
293
|
+
title="A2U Module",
|
|
294
|
+
category=CheckCategory.ENVIRONMENT,
|
|
295
|
+
status=CheckStatus.WARN,
|
|
296
|
+
message=f"A2U module not available: {e}",
|
|
297
|
+
remediation="pip install praisonai[serve]",
|
|
298
|
+
)
|
|
299
|
+
except Exception as e:
|
|
300
|
+
return CheckResult(
|
|
301
|
+
id="a2u_module",
|
|
302
|
+
title="A2U Module",
|
|
303
|
+
category=CheckCategory.ENVIRONMENT,
|
|
304
|
+
status=CheckStatus.ERROR,
|
|
305
|
+
message=f"Error checking A2U module: {e}",
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
@register_check(
|
|
310
|
+
id="provider_adapters",
|
|
311
|
+
title="Provider Adapters",
|
|
312
|
+
description="Check if all provider adapters are available",
|
|
313
|
+
category=CheckCategory.ENVIRONMENT,
|
|
314
|
+
severity=CheckSeverity.LOW,
|
|
315
|
+
tags=["serve", "providers"],
|
|
316
|
+
)
|
|
317
|
+
def check_provider_adapters(config: DoctorConfig) -> CheckResult:
|
|
318
|
+
"""Check if all provider adapters are available."""
|
|
319
|
+
try:
|
|
320
|
+
from praisonai.endpoints.providers import (
|
|
321
|
+
BaseProvider,
|
|
322
|
+
RecipeProvider,
|
|
323
|
+
AgentsAPIProvider,
|
|
324
|
+
MCPProvider,
|
|
325
|
+
ToolsMCPProvider,
|
|
326
|
+
A2AProvider,
|
|
327
|
+
A2UProvider,
|
|
328
|
+
)
|
|
329
|
+
providers = [
|
|
330
|
+
"BaseProvider",
|
|
331
|
+
"RecipeProvider",
|
|
332
|
+
"AgentsAPIProvider",
|
|
333
|
+
"MCPProvider",
|
|
334
|
+
"ToolsMCPProvider",
|
|
335
|
+
"A2AProvider",
|
|
336
|
+
"A2UProvider",
|
|
337
|
+
]
|
|
338
|
+
return CheckResult(
|
|
339
|
+
id="provider_adapters",
|
|
340
|
+
title="Provider Adapters",
|
|
341
|
+
category=CheckCategory.ENVIRONMENT,
|
|
342
|
+
status=CheckStatus.PASS,
|
|
343
|
+
message=f"All {len(providers)} provider adapters available",
|
|
344
|
+
metadata={"providers": providers},
|
|
345
|
+
)
|
|
346
|
+
except ImportError as e:
|
|
347
|
+
return CheckResult(
|
|
348
|
+
id="provider_adapters",
|
|
349
|
+
title="Provider Adapters",
|
|
350
|
+
category=CheckCategory.ENVIRONMENT,
|
|
351
|
+
status=CheckStatus.WARN,
|
|
352
|
+
message=f"Some provider adapters not available: {e}",
|
|
353
|
+
remediation="pip install praisonai[serve]",
|
|
354
|
+
)
|
|
355
|
+
except Exception as e:
|
|
356
|
+
return CheckResult(
|
|
357
|
+
id="provider_adapters",
|
|
358
|
+
title="Provider Adapters",
|
|
359
|
+
category=CheckCategory.ENVIRONMENT,
|
|
360
|
+
status=CheckStatus.ERROR,
|
|
361
|
+
message=f"Error checking provider adapters: {e}",
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@register_check(
|
|
366
|
+
id="fastapi_available",
|
|
367
|
+
title="FastAPI Available",
|
|
368
|
+
description="Check if FastAPI is available for serving",
|
|
369
|
+
category=CheckCategory.ENVIRONMENT,
|
|
370
|
+
severity=CheckSeverity.MEDIUM,
|
|
371
|
+
tags=["serve", "dependencies"],
|
|
372
|
+
)
|
|
373
|
+
def check_fastapi_available(config: DoctorConfig) -> CheckResult:
|
|
374
|
+
"""Check if FastAPI is available."""
|
|
375
|
+
try:
|
|
376
|
+
import fastapi
|
|
377
|
+
version = getattr(fastapi, "__version__", "unknown")
|
|
378
|
+
return CheckResult(
|
|
379
|
+
id="fastapi_available",
|
|
380
|
+
title="FastAPI Available",
|
|
381
|
+
category=CheckCategory.ENVIRONMENT,
|
|
382
|
+
status=CheckStatus.PASS,
|
|
383
|
+
message=f"FastAPI {version} available",
|
|
384
|
+
metadata={"version": version},
|
|
385
|
+
)
|
|
386
|
+
except ImportError:
|
|
387
|
+
return CheckResult(
|
|
388
|
+
id="fastapi_available",
|
|
389
|
+
title="FastAPI Available",
|
|
390
|
+
category=CheckCategory.ENVIRONMENT,
|
|
391
|
+
status=CheckStatus.WARN,
|
|
392
|
+
message="FastAPI not installed",
|
|
393
|
+
remediation="pip install fastapi uvicorn",
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
@register_check(
|
|
398
|
+
id="uvicorn_available",
|
|
399
|
+
title="Uvicorn Available",
|
|
400
|
+
description="Check if Uvicorn is available for serving",
|
|
401
|
+
category=CheckCategory.ENVIRONMENT,
|
|
402
|
+
severity=CheckSeverity.MEDIUM,
|
|
403
|
+
tags=["serve", "dependencies"],
|
|
404
|
+
)
|
|
405
|
+
def check_uvicorn_available(config: DoctorConfig) -> CheckResult:
|
|
406
|
+
"""Check if Uvicorn is available."""
|
|
407
|
+
try:
|
|
408
|
+
import uvicorn
|
|
409
|
+
version = getattr(uvicorn, "__version__", "unknown")
|
|
410
|
+
return CheckResult(
|
|
411
|
+
id="uvicorn_available",
|
|
412
|
+
title="Uvicorn Available",
|
|
413
|
+
category=CheckCategory.ENVIRONMENT,
|
|
414
|
+
status=CheckStatus.PASS,
|
|
415
|
+
message=f"Uvicorn {version} available",
|
|
416
|
+
metadata={"version": version},
|
|
417
|
+
)
|
|
418
|
+
except ImportError:
|
|
419
|
+
return CheckResult(
|
|
420
|
+
id="uvicorn_available",
|
|
421
|
+
title="Uvicorn Available",
|
|
422
|
+
category=CheckCategory.ENVIRONMENT,
|
|
423
|
+
status=CheckStatus.WARN,
|
|
424
|
+
message="Uvicorn not installed",
|
|
425
|
+
remediation="pip install uvicorn",
|
|
426
|
+
)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skills checks for the Doctor CLI module.
|
|
3
|
+
|
|
4
|
+
Validates Agent Skills configurations and manifests.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from ..models import (
|
|
10
|
+
CheckCategory,
|
|
11
|
+
CheckResult,
|
|
12
|
+
CheckStatus,
|
|
13
|
+
CheckSeverity,
|
|
14
|
+
DoctorConfig,
|
|
15
|
+
)
|
|
16
|
+
from ..registry import register_check
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _find_skills_dirs() -> list:
|
|
20
|
+
"""Find skills directories."""
|
|
21
|
+
locations = [
|
|
22
|
+
Path.cwd() / ".praison" / "skills",
|
|
23
|
+
Path.cwd() / ".claude" / "skills",
|
|
24
|
+
Path.home() / ".praison" / "skills",
|
|
25
|
+
Path.home() / ".config" / "praison" / "skills",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
found = []
|
|
29
|
+
for loc in locations:
|
|
30
|
+
if loc.exists() and loc.is_dir():
|
|
31
|
+
found.append(str(loc))
|
|
32
|
+
|
|
33
|
+
return found
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _validate_skill_dir(skill_path: Path) -> dict:
|
|
37
|
+
"""Validate a single skill directory."""
|
|
38
|
+
result = {"valid": False, "errors": [], "warnings": []}
|
|
39
|
+
|
|
40
|
+
skill_md = skill_path / "SKILL.md"
|
|
41
|
+
if not skill_md.exists():
|
|
42
|
+
result["errors"].append("Missing SKILL.md")
|
|
43
|
+
return result
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
content = skill_md.read_text()
|
|
47
|
+
|
|
48
|
+
# Check for YAML frontmatter
|
|
49
|
+
if not content.startswith("---"):
|
|
50
|
+
result["errors"].append("SKILL.md missing YAML frontmatter")
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
# Parse frontmatter
|
|
54
|
+
parts = content.split("---", 2)
|
|
55
|
+
if len(parts) < 3:
|
|
56
|
+
result["errors"].append("Invalid YAML frontmatter format")
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
import yaml
|
|
61
|
+
frontmatter = yaml.safe_load(parts[1])
|
|
62
|
+
|
|
63
|
+
# Check required fields
|
|
64
|
+
if not frontmatter.get("name"):
|
|
65
|
+
result["errors"].append("Missing 'name' in frontmatter")
|
|
66
|
+
if not frontmatter.get("description"):
|
|
67
|
+
result["errors"].append("Missing 'description' in frontmatter")
|
|
68
|
+
|
|
69
|
+
# Check name format
|
|
70
|
+
name = frontmatter.get("name", "")
|
|
71
|
+
if name and not name.replace("-", "").replace("_", "").isalnum():
|
|
72
|
+
result["warnings"].append(f"Name '{name}' should be alphanumeric with hyphens")
|
|
73
|
+
|
|
74
|
+
if not result["errors"]:
|
|
75
|
+
result["valid"] = True
|
|
76
|
+
result["name"] = name
|
|
77
|
+
result["description"] = frontmatter.get("description", "")[:100]
|
|
78
|
+
|
|
79
|
+
except Exception as e:
|
|
80
|
+
result["errors"].append(f"YAML parse error: {e}")
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
result["errors"].append(f"Cannot read SKILL.md: {e}")
|
|
84
|
+
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@register_check(
|
|
89
|
+
id="skills_dirs",
|
|
90
|
+
title="Skills Directories",
|
|
91
|
+
description="Check for skills directories",
|
|
92
|
+
category=CheckCategory.SKILLS,
|
|
93
|
+
severity=CheckSeverity.INFO,
|
|
94
|
+
)
|
|
95
|
+
def check_skills_dirs(config: DoctorConfig) -> CheckResult:
|
|
96
|
+
"""Check for skills directories."""
|
|
97
|
+
dirs = _find_skills_dirs()
|
|
98
|
+
|
|
99
|
+
if config.path:
|
|
100
|
+
# Check specific path
|
|
101
|
+
path = Path(config.path)
|
|
102
|
+
if path.exists():
|
|
103
|
+
dirs = [str(path)]
|
|
104
|
+
else:
|
|
105
|
+
return CheckResult(
|
|
106
|
+
id="skills_dirs",
|
|
107
|
+
title="Skills Directories",
|
|
108
|
+
category=CheckCategory.SKILLS,
|
|
109
|
+
status=CheckStatus.FAIL,
|
|
110
|
+
message=f"Specified path not found: {config.path}",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if dirs:
|
|
114
|
+
return CheckResult(
|
|
115
|
+
id="skills_dirs",
|
|
116
|
+
title="Skills Directories",
|
|
117
|
+
category=CheckCategory.SKILLS,
|
|
118
|
+
status=CheckStatus.PASS,
|
|
119
|
+
message=f"Found {len(dirs)} skills directory(ies)",
|
|
120
|
+
details=", ".join(dirs),
|
|
121
|
+
metadata={"directories": dirs},
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
return CheckResult(
|
|
125
|
+
id="skills_dirs",
|
|
126
|
+
title="Skills Directories",
|
|
127
|
+
category=CheckCategory.SKILLS,
|
|
128
|
+
status=CheckStatus.SKIP,
|
|
129
|
+
message="No skills directories found (optional)",
|
|
130
|
+
details="Create .praison/skills/ to add agent skills",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@register_check(
|
|
135
|
+
id="skills_valid",
|
|
136
|
+
title="Skills Validation",
|
|
137
|
+
description="Validate installed skills",
|
|
138
|
+
category=CheckCategory.SKILLS,
|
|
139
|
+
severity=CheckSeverity.MEDIUM,
|
|
140
|
+
dependencies=["skills_dirs"],
|
|
141
|
+
)
|
|
142
|
+
def check_skills_valid(config: DoctorConfig) -> CheckResult:
|
|
143
|
+
"""Validate installed skills."""
|
|
144
|
+
dirs = _find_skills_dirs()
|
|
145
|
+
|
|
146
|
+
if config.path:
|
|
147
|
+
path = Path(config.path)
|
|
148
|
+
if path.exists():
|
|
149
|
+
dirs = [str(path)]
|
|
150
|
+
|
|
151
|
+
if not dirs:
|
|
152
|
+
return CheckResult(
|
|
153
|
+
id="skills_valid",
|
|
154
|
+
title="Skills Validation",
|
|
155
|
+
category=CheckCategory.SKILLS,
|
|
156
|
+
status=CheckStatus.SKIP,
|
|
157
|
+
message="No skills to validate",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
valid_skills = []
|
|
161
|
+
invalid_skills = []
|
|
162
|
+
|
|
163
|
+
for dir_path in dirs:
|
|
164
|
+
skills_dir = Path(dir_path)
|
|
165
|
+
for skill_path in skills_dir.iterdir():
|
|
166
|
+
if skill_path.is_dir() and not skill_path.name.startswith("."):
|
|
167
|
+
result = _validate_skill_dir(skill_path)
|
|
168
|
+
if result["valid"]:
|
|
169
|
+
valid_skills.append(result.get("name", skill_path.name))
|
|
170
|
+
else:
|
|
171
|
+
invalid_skills.append(f"{skill_path.name}: {'; '.join(result['errors'])}")
|
|
172
|
+
|
|
173
|
+
total = len(valid_skills) + len(invalid_skills)
|
|
174
|
+
|
|
175
|
+
if total == 0:
|
|
176
|
+
return CheckResult(
|
|
177
|
+
id="skills_valid",
|
|
178
|
+
title="Skills Validation",
|
|
179
|
+
category=CheckCategory.SKILLS,
|
|
180
|
+
status=CheckStatus.SKIP,
|
|
181
|
+
message="No skills found in directories",
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
if invalid_skills:
|
|
185
|
+
return CheckResult(
|
|
186
|
+
id="skills_valid",
|
|
187
|
+
title="Skills Validation",
|
|
188
|
+
category=CheckCategory.SKILLS,
|
|
189
|
+
status=CheckStatus.WARN,
|
|
190
|
+
message=f"{len(valid_skills)}/{total} skills valid",
|
|
191
|
+
details="; ".join(invalid_skills[:3]) + ("..." if len(invalid_skills) > 3 else ""),
|
|
192
|
+
metadata={"valid": valid_skills, "invalid": invalid_skills},
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
return CheckResult(
|
|
196
|
+
id="skills_valid",
|
|
197
|
+
title="Skills Validation",
|
|
198
|
+
category=CheckCategory.SKILLS,
|
|
199
|
+
status=CheckStatus.PASS,
|
|
200
|
+
message=f"All {total} skill(s) valid",
|
|
201
|
+
metadata={"valid": valid_skills},
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@register_check(
|
|
206
|
+
id="skills_praisonai_integration",
|
|
207
|
+
title="PraisonAI Skills Integration",
|
|
208
|
+
description="Check PraisonAI skills module",
|
|
209
|
+
category=CheckCategory.SKILLS,
|
|
210
|
+
severity=CheckSeverity.LOW,
|
|
211
|
+
)
|
|
212
|
+
def check_skills_praisonai_integration(config: DoctorConfig) -> CheckResult:
|
|
213
|
+
"""Check PraisonAI skills module."""
|
|
214
|
+
try:
|
|
215
|
+
from praisonaiagents.skills import SkillManager
|
|
216
|
+
return CheckResult(
|
|
217
|
+
id="skills_praisonai_integration",
|
|
218
|
+
title="PraisonAI Skills Integration",
|
|
219
|
+
category=CheckCategory.SKILLS,
|
|
220
|
+
status=CheckStatus.PASS,
|
|
221
|
+
message="PraisonAI skills module available",
|
|
222
|
+
)
|
|
223
|
+
except ImportError as e:
|
|
224
|
+
return CheckResult(
|
|
225
|
+
id="skills_praisonai_integration",
|
|
226
|
+
title="PraisonAI Skills Integration",
|
|
227
|
+
category=CheckCategory.SKILLS,
|
|
228
|
+
status=CheckStatus.SKIP,
|
|
229
|
+
message="Skills module not available",
|
|
230
|
+
details=str(e),
|
|
231
|
+
)
|