praisonai-code 0.0.1__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_code/__init__.py +17 -0
- praisonai_code/cli/__init__.py +12 -0
- praisonai_code/cli/_forward_shim.py +10 -0
- praisonai_code/cli/_paths.py +88 -0
- praisonai_code/cli/_warnings.py +58 -0
- praisonai_code/cli/app.py +757 -0
- praisonai_code/cli/approval_backend.py +272 -0
- praisonai_code/cli/branding.py +94 -0
- praisonai_code/cli/commands/__init__.py +114 -0
- praisonai_code/cli/commands/acp.py +80 -0
- praisonai_code/cli/commands/agent.py +116 -0
- praisonai_code/cli/commands/agents.py +80 -0
- praisonai_code/cli/commands/app.py +139 -0
- praisonai_code/cli/commands/attach.py +95 -0
- praisonai_code/cli/commands/audit.py +102 -0
- praisonai_code/cli/commands/auth.py +508 -0
- praisonai_code/cli/commands/batch.py +848 -0
- praisonai_code/cli/commands/benchmark.py +286 -0
- praisonai_code/cli/commands/browser.py +299 -0
- praisonai_code/cli/commands/call.py +45 -0
- praisonai_code/cli/commands/chat.py +332 -0
- praisonai_code/cli/commands/checkpoint.py +170 -0
- praisonai_code/cli/commands/code.py +276 -0
- praisonai_code/cli/commands/command.py +114 -0
- praisonai_code/cli/commands/commit.py +47 -0
- praisonai_code/cli/commands/completion.py +333 -0
- praisonai_code/cli/commands/config.py +681 -0
- praisonai_code/cli/commands/context.py +414 -0
- praisonai_code/cli/commands/daemon.py +203 -0
- praisonai_code/cli/commands/debug.py +142 -0
- praisonai_code/cli/commands/deploy.py +71 -0
- praisonai_code/cli/commands/diag.py +55 -0
- praisonai_code/cli/commands/docs.py +1575 -0
- praisonai_code/cli/commands/doctor.py +332 -0
- praisonai_code/cli/commands/endpoints.py +51 -0
- praisonai_code/cli/commands/environment.py +179 -0
- praisonai_code/cli/commands/eval.py +131 -0
- praisonai_code/cli/commands/examples.py +953 -0
- praisonai_code/cli/commands/flow.py +436 -0
- praisonai_code/cli/commands/github.py +752 -0
- praisonai_code/cli/commands/hooks.py +74 -0
- praisonai_code/cli/commands/init.py +174 -0
- praisonai_code/cli/commands/knowledge.py +440 -0
- praisonai_code/cli/commands/langextract.py +120 -0
- praisonai_code/cli/commands/langfuse.py +984 -0
- praisonai_code/cli/commands/loop.py +211 -0
- praisonai_code/cli/commands/lsp.py +112 -0
- praisonai_code/cli/commands/managed.py +659 -0
- praisonai_code/cli/commands/mcp.py +763 -0
- praisonai_code/cli/commands/memory.py +298 -0
- praisonai_code/cli/commands/models.py +264 -0
- praisonai_code/cli/commands/n8n.py +326 -0
- praisonai_code/cli/commands/obs.py +19 -0
- praisonai_code/cli/commands/package.py +76 -0
- praisonai_code/cli/commands/paths.py +106 -0
- praisonai_code/cli/commands/permissions.py +272 -0
- praisonai_code/cli/commands/plugins.py +609 -0
- praisonai_code/cli/commands/port.py +530 -0
- praisonai_code/cli/commands/profile.py +466 -0
- praisonai_code/cli/commands/publish.py +193 -0
- praisonai_code/cli/commands/rag.py +913 -0
- praisonai_code/cli/commands/realtime.py +52 -0
- praisonai_code/cli/commands/recipe.py +684 -0
- praisonai_code/cli/commands/registry.py +59 -0
- praisonai_code/cli/commands/replay.py +830 -0
- praisonai_code/cli/commands/research.py +49 -0
- praisonai_code/cli/commands/retrieval.py +377 -0
- praisonai_code/cli/commands/rules.py +71 -0
- praisonai_code/cli/commands/run.py +1573 -0
- praisonai_code/cli/commands/sandbox.py +371 -0
- praisonai_code/cli/commands/schedule.py +529 -0
- praisonai_code/cli/commands/serve.py +690 -0
- praisonai_code/cli/commands/session.py +450 -0
- praisonai_code/cli/commands/setup.py +174 -0
- praisonai_code/cli/commands/skills.py +545 -0
- praisonai_code/cli/commands/standardise.py +711 -0
- praisonai_code/cli/commands/templates.py +54 -0
- praisonai_code/cli/commands/test.py +558 -0
- praisonai_code/cli/commands/todo.py +74 -0
- praisonai_code/cli/commands/tools.py +205 -0
- praisonai_code/cli/commands/traces.py +145 -0
- praisonai_code/cli/commands/tracker.py +852 -0
- praisonai_code/cli/commands/train.py +613 -0
- praisonai_code/cli/commands/ui.py +172 -0
- praisonai_code/cli/commands/up.py +354 -0
- praisonai_code/cli/commands/validate.py +291 -0
- praisonai_code/cli/commands/version.py +101 -0
- praisonai_code/cli/commands/workflow.py +97 -0
- praisonai_code/cli/config_loader.py +437 -0
- praisonai_code/cli/configuration/__init__.py +27 -0
- praisonai_code/cli/configuration/config.schema.json +57 -0
- praisonai_code/cli/configuration/credentials.py +446 -0
- praisonai_code/cli/configuration/loader.py +364 -0
- praisonai_code/cli/configuration/model_resolver.py +161 -0
- praisonai_code/cli/configuration/oauth.py +389 -0
- praisonai_code/cli/configuration/paths.py +224 -0
- praisonai_code/cli/configuration/resolver.py +687 -0
- praisonai_code/cli/configuration/schema.py +317 -0
- praisonai_code/cli/execution/__init__.py +99 -0
- praisonai_code/cli/execution/core.py +208 -0
- praisonai_code/cli/execution/profiler.py +898 -0
- praisonai_code/cli/execution/request.py +85 -0
- praisonai_code/cli/execution/result.py +74 -0
- praisonai_code/cli/fallback_schema.py +416 -0
- praisonai_code/cli/features/__init__.py +278 -0
- praisonai_code/cli/features/_endpoint_registry.py +64 -0
- praisonai_code/cli/features/_search_registry.py +43 -0
- praisonai_code/cli/features/acp.py +236 -0
- praisonai_code/cli/features/action_orchestrator.py +576 -0
- praisonai_code/cli/features/agent_scheduler.py +773 -0
- praisonai_code/cli/features/agent_tools.py +603 -0
- praisonai_code/cli/features/agents.py +397 -0
- praisonai_code/cli/features/at_mentions.py +471 -0
- praisonai_code/cli/features/audit_cli.py +270 -0
- praisonai_code/cli/features/auto_memory.py +182 -0
- praisonai_code/cli/features/auto_mode.py +552 -0
- praisonai_code/cli/features/autonomy_mode.py +546 -0
- praisonai_code/cli/features/background.py +356 -0
- praisonai_code/cli/features/base.py +168 -0
- praisonai_code/cli/features/benchmark.py +1462 -0
- praisonai_code/cli/features/capabilities.py +1326 -0
- praisonai_code/cli/features/checkpoints.py +345 -0
- praisonai_code/cli/features/cli_profiler.py +335 -0
- praisonai_code/cli/features/code_intelligence.py +666 -0
- praisonai_code/cli/features/compaction.py +294 -0
- praisonai_code/cli/features/compare.py +534 -0
- praisonai_code/cli/features/config_hierarchy.py +366 -0
- praisonai_code/cli/features/context_manager.py +597 -0
- praisonai_code/cli/features/cost_tracker.py +514 -0
- praisonai_code/cli/features/csv_test_runner.py +736 -0
- praisonai_code/cli/features/custom_definitions.py +790 -0
- praisonai_code/cli/features/debug.py +810 -0
- praisonai_code/cli/features/deploy.py +605 -0
- praisonai_code/cli/features/diag.py +289 -0
- praisonai_code/cli/features/display_jsonl.py +173 -0
- praisonai_code/cli/features/doctor/__init__.py +63 -0
- praisonai_code/cli/features/doctor/checks/__init__.py +29 -0
- praisonai_code/cli/features/doctor/checks/acp_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/bot_checks.py +340 -0
- praisonai_code/cli/features/doctor/checks/config_checks.py +373 -0
- praisonai_code/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai_code/cli/features/doctor/checks/env_checks.py +637 -0
- praisonai_code/cli/features/doctor/checks/gateway_checks.py +387 -0
- praisonai_code/cli/features/doctor/checks/lsp_checks.py +231 -0
- praisonai_code/cli/features/doctor/checks/mcp_checks.py +367 -0
- praisonai_code/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai_code/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai_code/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai_code/cli/features/doctor/checks/packaging_checks.py +422 -0
- praisonai_code/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai_code/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai_code/cli/features/doctor/checks/runtime_checks.py +650 -0
- praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai_code/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai_code/cli/features/doctor/checks/skills_checks.py +327 -0
- praisonai_code/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai_code/cli/features/doctor/engine.py +266 -0
- praisonai_code/cli/features/doctor/formatters.py +377 -0
- praisonai_code/cli/features/doctor/handler.py +564 -0
- praisonai_code/cli/features/doctor/models.py +276 -0
- praisonai_code/cli/features/doctor/registry.py +239 -0
- praisonai_code/cli/features/endpoints.py +1016 -0
- praisonai_code/cli/features/eval.py +559 -0
- praisonai_code/cli/features/examples.py +707 -0
- praisonai_code/cli/features/external_agents.py +231 -0
- praisonai_code/cli/features/fast_context.py +410 -0
- praisonai_code/cli/features/file_history.py +320 -0
- praisonai_code/cli/features/flow_display.py +566 -0
- praisonai_code/cli/features/git_attribution.py +159 -0
- praisonai_code/cli/features/git_integration.py +651 -0
- praisonai_code/cli/features/guardrail.py +171 -0
- praisonai_code/cli/features/handoff.py +252 -0
- praisonai_code/cli/features/hooks.py +583 -0
- praisonai_code/cli/features/hybrid_workflow.py +391 -0
- praisonai_code/cli/features/image.py +384 -0
- praisonai_code/cli/features/interactive_core_headless.py +450 -0
- praisonai_code/cli/features/interactive_runtime.py +600 -0
- praisonai_code/cli/features/interactive_test_harness.py +537 -0
- praisonai_code/cli/features/interactive_tools.py +428 -0
- praisonai_code/cli/features/interactive_tui.py +603 -0
- praisonai_code/cli/features/job_workflow.py +906 -0
- praisonai_code/cli/features/jobs.py +632 -0
- praisonai_code/cli/features/knowledge.py +531 -0
- praisonai_code/cli/features/knowledge_cli.py +438 -0
- praisonai_code/cli/features/lite.py +244 -0
- praisonai_code/cli/features/logs.py +200 -0
- praisonai_code/cli/features/lsp_cli.py +225 -0
- praisonai_code/cli/features/lsp_diagnostics.py +185 -0
- praisonai_code/cli/features/mcp.py +344 -0
- praisonai_code/cli/features/message_queue.py +587 -0
- praisonai_code/cli/features/metrics.py +210 -0
- praisonai_code/cli/features/migrate.py +1329 -0
- praisonai_code/cli/features/migration_flow.py +463 -0
- praisonai_code/cli/features/migration_spec.py +276 -0
- praisonai_code/cli/features/n8n.py +703 -0
- praisonai_code/cli/features/observability.py +293 -0
- praisonai_code/cli/features/ollama.py +361 -0
- praisonai_code/cli/features/output_modes.py +155 -0
- praisonai_code/cli/features/output_style.py +273 -0
- praisonai_code/cli/features/package.py +631 -0
- praisonai_code/cli/features/performance.py +308 -0
- praisonai_code/cli/features/persistence.py +636 -0
- praisonai_code/cli/features/profiler/__init__.py +81 -0
- praisonai_code/cli/features/profiler/core.py +558 -0
- praisonai_code/cli/features/profiler/optimizations.py +652 -0
- praisonai_code/cli/features/profiler/suite.py +386 -0
- praisonai_code/cli/features/queue/__init__.py +73 -0
- praisonai_code/cli/features/queue/manager.py +435 -0
- praisonai_code/cli/features/queue/models.py +289 -0
- praisonai_code/cli/features/queue/persistence.py +564 -0
- praisonai_code/cli/features/queue/scheduler.py +529 -0
- praisonai_code/cli/features/queue/worker.py +400 -0
- praisonai_code/cli/features/recipe.py +2187 -0
- praisonai_code/cli/features/recipe_creator.py +996 -0
- praisonai_code/cli/features/recipe_optimizer.py +1364 -0
- praisonai_code/cli/features/recipe_prompts.py +226 -0
- praisonai_code/cli/features/registry.py +229 -0
- praisonai_code/cli/features/repo_map.py +860 -0
- praisonai_code/cli/features/router.py +466 -0
- praisonai_code/cli/features/safe_shell.py +427 -0
- praisonai_code/cli/features/sandbox_cli.py +283 -0
- praisonai_code/cli/features/sandbox_executor.py +536 -0
- praisonai_code/cli/features/sdk_knowledge.py +500 -0
- praisonai_code/cli/features/session.py +222 -0
- praisonai_code/cli/features/session_checkpoints.py +208 -0
- praisonai_code/cli/features/setup/__init__.py +9 -0
- praisonai_code/cli/features/setup/handler.py +355 -0
- praisonai_code/cli/features/setup/templates.py +62 -0
- praisonai_code/cli/features/skills.py +940 -0
- praisonai_code/cli/features/slash_commands.py +692 -0
- praisonai_code/cli/features/telemetry.py +179 -0
- praisonai_code/cli/features/templates.py +1390 -0
- praisonai_code/cli/features/thinking.py +343 -0
- praisonai_code/cli/features/todo.py +334 -0
- praisonai_code/cli/features/tools.py +680 -0
- praisonai_code/cli/features/tui/__init__.py +83 -0
- praisonai_code/cli/features/tui/app.py +871 -0
- praisonai_code/cli/features/tui/cli.py +580 -0
- praisonai_code/cli/features/tui/config.py +150 -0
- praisonai_code/cli/features/tui/debug.py +526 -0
- praisonai_code/cli/features/tui/events.py +99 -0
- praisonai_code/cli/features/tui/mock_provider.py +328 -0
- praisonai_code/cli/features/tui/orchestrator.py +652 -0
- praisonai_code/cli/features/tui/screens/__init__.py +50 -0
- praisonai_code/cli/features/tui/screens/help.py +157 -0
- praisonai_code/cli/features/tui/screens/main.py +568 -0
- praisonai_code/cli/features/tui/screens/queue.py +174 -0
- praisonai_code/cli/features/tui/screens/session.py +124 -0
- praisonai_code/cli/features/tui/screens/settings.py +148 -0
- praisonai_code/cli/features/tui/session_store.py +198 -0
- praisonai_code/cli/features/tui/widgets/__init__.py +56 -0
- praisonai_code/cli/features/tui/widgets/chat.py +263 -0
- praisonai_code/cli/features/tui/widgets/command_popup.py +258 -0
- praisonai_code/cli/features/tui/widgets/composer.py +292 -0
- praisonai_code/cli/features/tui/widgets/file_popup.py +207 -0
- praisonai_code/cli/features/tui/widgets/queue_panel.py +223 -0
- praisonai_code/cli/features/tui/widgets/status.py +181 -0
- praisonai_code/cli/features/tui/widgets/tool_panel.py +307 -0
- praisonai_code/cli/features/wizard.py +289 -0
- praisonai_code/cli/features/workflow.py +802 -0
- praisonai_code/cli/features/yaml_utils.py +321 -0
- praisonai_code/cli/interactive/__init__.py +48 -0
- praisonai_code/cli/interactive/async_tui.py +1218 -0
- praisonai_code/cli/interactive/config.py +139 -0
- praisonai_code/cli/interactive/core.py +618 -0
- praisonai_code/cli/interactive/events.py +131 -0
- praisonai_code/cli/interactive/frontends/__init__.py +31 -0
- praisonai_code/cli/interactive/frontends/rich_frontend.py +462 -0
- praisonai_code/cli/interactive/frontends/textual_frontend.py +157 -0
- praisonai_code/cli/interactive/praison_io.py +502 -0
- praisonai_code/cli/interactive/repl.py +297 -0
- praisonai_code/cli/interactive/split_tui.py +456 -0
- praisonai_code/cli/interactive/tui_app.py +457 -0
- praisonai_code/cli/langfuse_client.py +360 -0
- praisonai_code/cli/main.py +7421 -0
- praisonai_code/cli/output/__init__.py +25 -0
- praisonai_code/cli/output/console.py +456 -0
- praisonai_code/cli/output/event_bridge.py +191 -0
- praisonai_code/cli/schedule_cli.py +54 -0
- praisonai_code/cli/schema_provider.py +23 -0
- praisonai_code/cli/session/__init__.py +16 -0
- praisonai_code/cli/session/resume.py +148 -0
- praisonai_code/cli/session/unified.py +548 -0
- praisonai_code/cli/state/__init__.py +31 -0
- praisonai_code/cli/state/identifiers.py +161 -0
- praisonai_code/cli/state/project_sessions.py +383 -0
- praisonai_code/cli/state/sessions.py +390 -0
- praisonai_code/cli/ui/__init__.py +160 -0
- praisonai_code/cli/ui/config.py +46 -0
- praisonai_code/cli/ui/events.py +61 -0
- praisonai_code/cli/ui/mg_backend.py +342 -0
- praisonai_code/cli/ui/plain.py +133 -0
- praisonai_code/cli/ui/rich_backend.py +162 -0
- praisonai_code/cli/unified_schema.py +655 -0
- praisonai_code/cli/utils/env_utils.py +126 -0
- praisonai_code/cli/utils/project.py +131 -0
- praisonai_code/cli_backends/__init__.py +73 -0
- praisonai_code/cli_backends/claude.py +373 -0
- praisonai_code/cli_backends/registry.py +113 -0
- praisonai_code/runtime/__init__.py +36 -0
- praisonai_code/runtime/__main__.py +81 -0
- praisonai_code/runtime/client.py +131 -0
- praisonai_code/runtime/descriptor.py +209 -0
- praisonai_code/runtime/server.py +356 -0
- praisonai_code-0.0.1.dist-info/METADATA +80 -0
- praisonai_code-0.0.1.dist-info/RECORD +309 -0
- praisonai_code-0.0.1.dist-info/WHEEL +5 -0
- praisonai_code-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Environment checks for the Doctor CLI module.
|
|
3
|
+
|
|
4
|
+
Validates Python version, packages, API keys, and environment variables.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import platform
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
from typing import List, Optional
|
|
12
|
+
|
|
13
|
+
from ..models import (
|
|
14
|
+
CheckCategory,
|
|
15
|
+
CheckResult,
|
|
16
|
+
CheckStatus,
|
|
17
|
+
CheckSeverity,
|
|
18
|
+
DoctorConfig,
|
|
19
|
+
)
|
|
20
|
+
from ..registry import register_check
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@register_check(
|
|
24
|
+
id="python_version",
|
|
25
|
+
title="Python Version",
|
|
26
|
+
description="Check Python version is 3.9+",
|
|
27
|
+
category=CheckCategory.ENVIRONMENT,
|
|
28
|
+
severity=CheckSeverity.CRITICAL,
|
|
29
|
+
)
|
|
30
|
+
def check_python_version(config: DoctorConfig) -> CheckResult:
|
|
31
|
+
"""Check Python version is 3.9+."""
|
|
32
|
+
version = sys.version_info
|
|
33
|
+
version_str = f"{version.major}.{version.minor}.{version.micro}"
|
|
34
|
+
|
|
35
|
+
if version.major >= 3 and version.minor >= 9:
|
|
36
|
+
return CheckResult(
|
|
37
|
+
id="python_version",
|
|
38
|
+
title="Python Version",
|
|
39
|
+
category=CheckCategory.ENVIRONMENT,
|
|
40
|
+
status=CheckStatus.PASS,
|
|
41
|
+
message=f"Python {version_str} (>= 3.9 required)",
|
|
42
|
+
metadata={"version": version_str, "executable": sys.executable},
|
|
43
|
+
)
|
|
44
|
+
else:
|
|
45
|
+
return CheckResult(
|
|
46
|
+
id="python_version",
|
|
47
|
+
title="Python Version",
|
|
48
|
+
category=CheckCategory.ENVIRONMENT,
|
|
49
|
+
status=CheckStatus.FAIL,
|
|
50
|
+
message=f"Python {version_str} found, but 3.9+ required",
|
|
51
|
+
remediation="Upgrade Python to version 3.9 or higher",
|
|
52
|
+
severity=CheckSeverity.CRITICAL,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@register_check(
|
|
57
|
+
id="praisonai_package",
|
|
58
|
+
title="PraisonAI Package",
|
|
59
|
+
description="Check praisonai package is installed",
|
|
60
|
+
category=CheckCategory.ENVIRONMENT,
|
|
61
|
+
severity=CheckSeverity.CRITICAL,
|
|
62
|
+
)
|
|
63
|
+
def check_praisonai_package(config: DoctorConfig) -> CheckResult:
|
|
64
|
+
"""Check praisonai package is installed."""
|
|
65
|
+
try:
|
|
66
|
+
from praisonai.version import __version__
|
|
67
|
+
return CheckResult(
|
|
68
|
+
id="praisonai_package",
|
|
69
|
+
title="PraisonAI Package",
|
|
70
|
+
category=CheckCategory.ENVIRONMENT,
|
|
71
|
+
status=CheckStatus.PASS,
|
|
72
|
+
message=f"praisonai {__version__} installed",
|
|
73
|
+
metadata={"version": __version__},
|
|
74
|
+
)
|
|
75
|
+
except ImportError as e:
|
|
76
|
+
return CheckResult(
|
|
77
|
+
id="praisonai_package",
|
|
78
|
+
title="PraisonAI Package",
|
|
79
|
+
category=CheckCategory.ENVIRONMENT,
|
|
80
|
+
status=CheckStatus.FAIL,
|
|
81
|
+
message="praisonai package not found",
|
|
82
|
+
details=str(e),
|
|
83
|
+
remediation="Install with: pip install praisonai",
|
|
84
|
+
severity=CheckSeverity.CRITICAL,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@register_check(
|
|
89
|
+
id="praisonaiagents_package",
|
|
90
|
+
title="PraisonAI Agents Package",
|
|
91
|
+
description="Check praisonaiagents package is installed",
|
|
92
|
+
category=CheckCategory.ENVIRONMENT,
|
|
93
|
+
severity=CheckSeverity.CRITICAL,
|
|
94
|
+
)
|
|
95
|
+
def check_praisonaiagents_package(config: DoctorConfig) -> CheckResult:
|
|
96
|
+
"""Check praisonaiagents package is installed."""
|
|
97
|
+
try:
|
|
98
|
+
import praisonaiagents
|
|
99
|
+
# praisonaiagents does not expose __version__ at module level yet, so
|
|
100
|
+
# prefer importlib.metadata (which reads the installed dist-info) and
|
|
101
|
+
# fall back to the attribute for forward-compat.
|
|
102
|
+
version = getattr(praisonaiagents, "__version__", None)
|
|
103
|
+
if not version:
|
|
104
|
+
try:
|
|
105
|
+
from importlib.metadata import version as _pkg_version
|
|
106
|
+
version = _pkg_version("praisonaiagents")
|
|
107
|
+
except Exception:
|
|
108
|
+
version = "unknown"
|
|
109
|
+
return CheckResult(
|
|
110
|
+
id="praisonaiagents_package",
|
|
111
|
+
title="PraisonAI Agents Package",
|
|
112
|
+
category=CheckCategory.ENVIRONMENT,
|
|
113
|
+
status=CheckStatus.PASS,
|
|
114
|
+
message=f"praisonaiagents {version} installed",
|
|
115
|
+
metadata={"version": version},
|
|
116
|
+
)
|
|
117
|
+
except ImportError as e:
|
|
118
|
+
return CheckResult(
|
|
119
|
+
id="praisonaiagents_package",
|
|
120
|
+
title="PraisonAI Agents Package",
|
|
121
|
+
category=CheckCategory.ENVIRONMENT,
|
|
122
|
+
status=CheckStatus.FAIL,
|
|
123
|
+
message="praisonaiagents package not found",
|
|
124
|
+
details=str(e),
|
|
125
|
+
remediation="Install with: pip install praisonaiagents",
|
|
126
|
+
severity=CheckSeverity.CRITICAL,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@register_check(
|
|
131
|
+
id="openai_api_key",
|
|
132
|
+
title="OpenAI API Key",
|
|
133
|
+
description="Check OPENAI_API_KEY is configured",
|
|
134
|
+
category=CheckCategory.ENVIRONMENT,
|
|
135
|
+
severity=CheckSeverity.HIGH,
|
|
136
|
+
)
|
|
137
|
+
def check_openai_api_key(config: DoctorConfig) -> CheckResult:
|
|
138
|
+
"""Check OpenAI API key is configured."""
|
|
139
|
+
key = os.environ.get("OPENAI_API_KEY", "")
|
|
140
|
+
|
|
141
|
+
if key:
|
|
142
|
+
# Mask the key for display
|
|
143
|
+
if config.show_keys and len(key) > 12:
|
|
144
|
+
masked = f"{key[:4]}...{key[-4:]}"
|
|
145
|
+
else:
|
|
146
|
+
masked = "***configured***"
|
|
147
|
+
|
|
148
|
+
# Basic validation
|
|
149
|
+
if key.startswith("sk-") or key.startswith("sk-proj-"):
|
|
150
|
+
return CheckResult(
|
|
151
|
+
id="openai_api_key",
|
|
152
|
+
title="OpenAI API Key",
|
|
153
|
+
category=CheckCategory.ENVIRONMENT,
|
|
154
|
+
status=CheckStatus.PASS,
|
|
155
|
+
message=f"OPENAI_API_KEY configured ({masked})",
|
|
156
|
+
metadata={"masked_key": masked},
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
return CheckResult(
|
|
160
|
+
id="openai_api_key",
|
|
161
|
+
title="OpenAI API Key",
|
|
162
|
+
category=CheckCategory.ENVIRONMENT,
|
|
163
|
+
status=CheckStatus.WARN,
|
|
164
|
+
message=f"OPENAI_API_KEY set but format unexpected ({masked})",
|
|
165
|
+
remediation="Verify the API key format is correct",
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
# Check for alternative providers
|
|
169
|
+
alternatives = []
|
|
170
|
+
if os.environ.get("ANTHROPIC_API_KEY"):
|
|
171
|
+
alternatives.append("ANTHROPIC_API_KEY")
|
|
172
|
+
if os.environ.get("GOOGLE_API_KEY") or os.environ.get("GEMINI_API_KEY"):
|
|
173
|
+
alternatives.append("GOOGLE/GEMINI_API_KEY")
|
|
174
|
+
if os.environ.get("OLLAMA_HOST") or shutil.which("ollama"):
|
|
175
|
+
alternatives.append("Ollama")
|
|
176
|
+
|
|
177
|
+
if alternatives:
|
|
178
|
+
return CheckResult(
|
|
179
|
+
id="openai_api_key",
|
|
180
|
+
title="OpenAI API Key",
|
|
181
|
+
category=CheckCategory.ENVIRONMENT,
|
|
182
|
+
status=CheckStatus.WARN,
|
|
183
|
+
message=f"OPENAI_API_KEY not set, but alternatives found: {', '.join(alternatives)}",
|
|
184
|
+
details="OpenAI is the default provider. Other providers require explicit configuration.",
|
|
185
|
+
)
|
|
186
|
+
else:
|
|
187
|
+
return CheckResult(
|
|
188
|
+
id="openai_api_key",
|
|
189
|
+
title="OpenAI API Key",
|
|
190
|
+
category=CheckCategory.ENVIRONMENT,
|
|
191
|
+
status=CheckStatus.FAIL,
|
|
192
|
+
message="OPENAI_API_KEY not configured and no alternative providers found",
|
|
193
|
+
remediation="Run 'praisonai setup' to configure API keys, or set OPENAI_API_KEY environment variable",
|
|
194
|
+
severity=CheckSeverity.HIGH,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@register_check(
|
|
199
|
+
id="anthropic_api_key",
|
|
200
|
+
title="Anthropic API Key",
|
|
201
|
+
description="Check ANTHROPIC_API_KEY is configured",
|
|
202
|
+
category=CheckCategory.ENVIRONMENT,
|
|
203
|
+
severity=CheckSeverity.LOW,
|
|
204
|
+
)
|
|
205
|
+
def check_anthropic_api_key(config: DoctorConfig) -> CheckResult:
|
|
206
|
+
"""Check Anthropic API key is configured."""
|
|
207
|
+
key = os.environ.get("ANTHROPIC_API_KEY", "")
|
|
208
|
+
|
|
209
|
+
if key:
|
|
210
|
+
if config.show_keys and len(key) > 12:
|
|
211
|
+
masked = f"{key[:4]}...{key[-4:]}"
|
|
212
|
+
else:
|
|
213
|
+
masked = "***configured***"
|
|
214
|
+
|
|
215
|
+
return CheckResult(
|
|
216
|
+
id="anthropic_api_key",
|
|
217
|
+
title="Anthropic API Key",
|
|
218
|
+
category=CheckCategory.ENVIRONMENT,
|
|
219
|
+
status=CheckStatus.PASS,
|
|
220
|
+
message=f"ANTHROPIC_API_KEY configured ({masked})",
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
return CheckResult(
|
|
224
|
+
id="anthropic_api_key",
|
|
225
|
+
title="Anthropic API Key",
|
|
226
|
+
category=CheckCategory.ENVIRONMENT,
|
|
227
|
+
status=CheckStatus.SKIP,
|
|
228
|
+
message="ANTHROPIC_API_KEY not set (optional)",
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@register_check(
|
|
233
|
+
id="google_api_key",
|
|
234
|
+
title="Google/Gemini API Key",
|
|
235
|
+
description="Check GOOGLE_API_KEY or GEMINI_API_KEY is configured",
|
|
236
|
+
category=CheckCategory.ENVIRONMENT,
|
|
237
|
+
severity=CheckSeverity.LOW,
|
|
238
|
+
)
|
|
239
|
+
def check_google_api_key(config: DoctorConfig) -> CheckResult:
|
|
240
|
+
"""Check Google/Gemini API key is configured."""
|
|
241
|
+
key = os.environ.get("GOOGLE_API_KEY") or os.environ.get("GEMINI_API_KEY", "")
|
|
242
|
+
|
|
243
|
+
if key:
|
|
244
|
+
if config.show_keys and len(key) > 12:
|
|
245
|
+
masked = f"{key[:4]}...{key[-4:]}"
|
|
246
|
+
else:
|
|
247
|
+
masked = "***configured***"
|
|
248
|
+
|
|
249
|
+
return CheckResult(
|
|
250
|
+
id="google_api_key",
|
|
251
|
+
title="Google/Gemini API Key",
|
|
252
|
+
category=CheckCategory.ENVIRONMENT,
|
|
253
|
+
status=CheckStatus.PASS,
|
|
254
|
+
message=f"Google/Gemini API key configured ({masked})",
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
return CheckResult(
|
|
258
|
+
id="google_api_key",
|
|
259
|
+
title="Google/Gemini API Key",
|
|
260
|
+
category=CheckCategory.ENVIRONMENT,
|
|
261
|
+
status=CheckStatus.SKIP,
|
|
262
|
+
message="GOOGLE_API_KEY/GEMINI_API_KEY not set (optional)",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@register_check(
|
|
267
|
+
id="os_info",
|
|
268
|
+
title="Operating System",
|
|
269
|
+
description="Check operating system information",
|
|
270
|
+
category=CheckCategory.ENVIRONMENT,
|
|
271
|
+
severity=CheckSeverity.INFO,
|
|
272
|
+
)
|
|
273
|
+
def check_os_info(config: DoctorConfig) -> CheckResult:
|
|
274
|
+
"""Check operating system information."""
|
|
275
|
+
os_name = platform.system()
|
|
276
|
+
os_version = platform.release()
|
|
277
|
+
arch = platform.machine()
|
|
278
|
+
|
|
279
|
+
return CheckResult(
|
|
280
|
+
id="os_info",
|
|
281
|
+
title="Operating System",
|
|
282
|
+
category=CheckCategory.ENVIRONMENT,
|
|
283
|
+
status=CheckStatus.PASS,
|
|
284
|
+
message=f"{os_name} {os_version} ({arch})",
|
|
285
|
+
metadata={
|
|
286
|
+
"os_name": os_name,
|
|
287
|
+
"os_version": os_version,
|
|
288
|
+
"architecture": arch,
|
|
289
|
+
},
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
@register_check(
|
|
294
|
+
id="virtual_env",
|
|
295
|
+
title="Virtual Environment",
|
|
296
|
+
description="Check if running in a virtual environment",
|
|
297
|
+
category=CheckCategory.ENVIRONMENT,
|
|
298
|
+
severity=CheckSeverity.INFO,
|
|
299
|
+
)
|
|
300
|
+
def check_virtual_env(config: DoctorConfig) -> CheckResult:
|
|
301
|
+
"""Check if running in a virtual environment."""
|
|
302
|
+
venv = os.environ.get("VIRTUAL_ENV")
|
|
303
|
+
conda_env = os.environ.get("CONDA_DEFAULT_ENV")
|
|
304
|
+
|
|
305
|
+
if venv:
|
|
306
|
+
return CheckResult(
|
|
307
|
+
id="virtual_env",
|
|
308
|
+
title="Virtual Environment",
|
|
309
|
+
category=CheckCategory.ENVIRONMENT,
|
|
310
|
+
status=CheckStatus.PASS,
|
|
311
|
+
message=f"Running in venv: {os.path.basename(venv)}",
|
|
312
|
+
metadata={"venv_path": venv},
|
|
313
|
+
)
|
|
314
|
+
elif conda_env:
|
|
315
|
+
return CheckResult(
|
|
316
|
+
id="virtual_env",
|
|
317
|
+
title="Virtual Environment",
|
|
318
|
+
category=CheckCategory.ENVIRONMENT,
|
|
319
|
+
status=CheckStatus.PASS,
|
|
320
|
+
message=f"Running in conda env: {conda_env}",
|
|
321
|
+
metadata={"conda_env": conda_env},
|
|
322
|
+
)
|
|
323
|
+
else:
|
|
324
|
+
return CheckResult(
|
|
325
|
+
id="virtual_env",
|
|
326
|
+
title="Virtual Environment",
|
|
327
|
+
category=CheckCategory.ENVIRONMENT,
|
|
328
|
+
status=CheckStatus.WARN,
|
|
329
|
+
message="Not running in a virtual environment",
|
|
330
|
+
remediation="Consider using a virtual environment for isolation",
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@register_check(
|
|
335
|
+
id="git_available",
|
|
336
|
+
title="Git",
|
|
337
|
+
description="Check if git is available",
|
|
338
|
+
category=CheckCategory.ENVIRONMENT,
|
|
339
|
+
severity=CheckSeverity.LOW,
|
|
340
|
+
)
|
|
341
|
+
def check_git_available(config: DoctorConfig) -> CheckResult:
|
|
342
|
+
"""Check if git is available."""
|
|
343
|
+
git_path = shutil.which("git")
|
|
344
|
+
|
|
345
|
+
if git_path:
|
|
346
|
+
import subprocess
|
|
347
|
+
try:
|
|
348
|
+
result = subprocess.run(
|
|
349
|
+
["git", "--version"],
|
|
350
|
+
capture_output=True,
|
|
351
|
+
text=True,
|
|
352
|
+
timeout=5,
|
|
353
|
+
)
|
|
354
|
+
version = result.stdout.strip() if result.returncode == 0 else "unknown"
|
|
355
|
+
return CheckResult(
|
|
356
|
+
id="git_available",
|
|
357
|
+
title="Git",
|
|
358
|
+
category=CheckCategory.ENVIRONMENT,
|
|
359
|
+
status=CheckStatus.PASS,
|
|
360
|
+
message=f"Git available: {version}",
|
|
361
|
+
metadata={"path": git_path},
|
|
362
|
+
)
|
|
363
|
+
except Exception:
|
|
364
|
+
return CheckResult(
|
|
365
|
+
id="git_available",
|
|
366
|
+
title="Git",
|
|
367
|
+
category=CheckCategory.ENVIRONMENT,
|
|
368
|
+
status=CheckStatus.PASS,
|
|
369
|
+
message=f"Git available at {git_path}",
|
|
370
|
+
)
|
|
371
|
+
else:
|
|
372
|
+
return CheckResult(
|
|
373
|
+
id="git_available",
|
|
374
|
+
title="Git",
|
|
375
|
+
category=CheckCategory.ENVIRONMENT,
|
|
376
|
+
status=CheckStatus.WARN,
|
|
377
|
+
message="Git not found in PATH",
|
|
378
|
+
remediation="Install git for version control features",
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@register_check(
|
|
383
|
+
id="docker_available",
|
|
384
|
+
title="Docker",
|
|
385
|
+
description="Check if Docker is available",
|
|
386
|
+
category=CheckCategory.ENVIRONMENT,
|
|
387
|
+
severity=CheckSeverity.LOW,
|
|
388
|
+
)
|
|
389
|
+
def check_docker_available(config: DoctorConfig) -> CheckResult:
|
|
390
|
+
"""Check if Docker is available."""
|
|
391
|
+
docker_path = shutil.which("docker")
|
|
392
|
+
|
|
393
|
+
if docker_path:
|
|
394
|
+
import subprocess
|
|
395
|
+
try:
|
|
396
|
+
result = subprocess.run(
|
|
397
|
+
["docker", "--version"],
|
|
398
|
+
capture_output=True,
|
|
399
|
+
text=True,
|
|
400
|
+
timeout=5,
|
|
401
|
+
)
|
|
402
|
+
if result.returncode == 0:
|
|
403
|
+
version = result.stdout.strip()
|
|
404
|
+
return CheckResult(
|
|
405
|
+
id="docker_available",
|
|
406
|
+
title="Docker",
|
|
407
|
+
category=CheckCategory.ENVIRONMENT,
|
|
408
|
+
status=CheckStatus.PASS,
|
|
409
|
+
message=f"Docker available: {version}",
|
|
410
|
+
metadata={"path": docker_path},
|
|
411
|
+
)
|
|
412
|
+
except Exception:
|
|
413
|
+
pass
|
|
414
|
+
|
|
415
|
+
return CheckResult(
|
|
416
|
+
id="docker_available",
|
|
417
|
+
title="Docker",
|
|
418
|
+
category=CheckCategory.ENVIRONMENT,
|
|
419
|
+
status=CheckStatus.WARN,
|
|
420
|
+
message="Docker found but not responding",
|
|
421
|
+
remediation="Ensure Docker daemon is running",
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
return CheckResult(
|
|
425
|
+
id="docker_available",
|
|
426
|
+
title="Docker",
|
|
427
|
+
category=CheckCategory.ENVIRONMENT,
|
|
428
|
+
status=CheckStatus.SKIP,
|
|
429
|
+
message="Docker not found (optional)",
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
@register_check(
|
|
434
|
+
id="npx_available",
|
|
435
|
+
title="npx (Node.js)",
|
|
436
|
+
description="Check if npx is available for MCP servers",
|
|
437
|
+
category=CheckCategory.ENVIRONMENT,
|
|
438
|
+
severity=CheckSeverity.LOW,
|
|
439
|
+
)
|
|
440
|
+
def check_npx_available(config: DoctorConfig) -> CheckResult:
|
|
441
|
+
"""Check if npx is available for MCP servers."""
|
|
442
|
+
npx_path = shutil.which("npx")
|
|
443
|
+
|
|
444
|
+
if npx_path:
|
|
445
|
+
return CheckResult(
|
|
446
|
+
id="npx_available",
|
|
447
|
+
title="npx (Node.js)",
|
|
448
|
+
category=CheckCategory.ENVIRONMENT,
|
|
449
|
+
status=CheckStatus.PASS,
|
|
450
|
+
message=f"npx available at {npx_path}",
|
|
451
|
+
metadata={"path": npx_path},
|
|
452
|
+
)
|
|
453
|
+
else:
|
|
454
|
+
return CheckResult(
|
|
455
|
+
id="npx_available",
|
|
456
|
+
title="npx (Node.js)",
|
|
457
|
+
category=CheckCategory.ENVIRONMENT,
|
|
458
|
+
status=CheckStatus.WARN,
|
|
459
|
+
message="npx not found (required for some MCP servers)",
|
|
460
|
+
remediation="Install Node.js to use MCP servers that require npx",
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
@register_check(
|
|
465
|
+
id="optional_deps",
|
|
466
|
+
title="Optional Dependencies",
|
|
467
|
+
description="Check availability of optional dependencies",
|
|
468
|
+
category=CheckCategory.ENVIRONMENT,
|
|
469
|
+
severity=CheckSeverity.INFO,
|
|
470
|
+
requires_deep=True,
|
|
471
|
+
)
|
|
472
|
+
def check_optional_deps(config: DoctorConfig) -> CheckResult:
|
|
473
|
+
"""Check availability of optional dependencies."""
|
|
474
|
+
optional_packages = [
|
|
475
|
+
("chromadb", "Knowledge/RAG features"),
|
|
476
|
+
("mem0ai", "Memory features"),
|
|
477
|
+
("litellm", "Multi-provider LLM support"),
|
|
478
|
+
("praisonaiui", "aiui (Chat/Dashboard UI)"),
|
|
479
|
+
("gradio", "Gradio UI"),
|
|
480
|
+
("crawl4ai", "Web crawling"),
|
|
481
|
+
("tavily", "Tavily search"),
|
|
482
|
+
("duckduckgo_search", "DuckDuckGo search"),
|
|
483
|
+
]
|
|
484
|
+
|
|
485
|
+
available = []
|
|
486
|
+
missing = []
|
|
487
|
+
|
|
488
|
+
for package, description in optional_packages:
|
|
489
|
+
try:
|
|
490
|
+
__import__(package)
|
|
491
|
+
available.append(package)
|
|
492
|
+
except ImportError:
|
|
493
|
+
missing.append(f"{package} ({description})")
|
|
494
|
+
|
|
495
|
+
if missing:
|
|
496
|
+
return CheckResult(
|
|
497
|
+
id="optional_deps",
|
|
498
|
+
title="Optional Dependencies",
|
|
499
|
+
category=CheckCategory.ENVIRONMENT,
|
|
500
|
+
status=CheckStatus.PASS,
|
|
501
|
+
message=f"{len(available)} optional packages available, {len(missing)} not installed",
|
|
502
|
+
details=f"Missing: {', '.join(missing[:5])}{'...' if len(missing) > 5 else ''}",
|
|
503
|
+
metadata={"available": available, "missing": missing},
|
|
504
|
+
)
|
|
505
|
+
else:
|
|
506
|
+
return CheckResult(
|
|
507
|
+
id="optional_deps",
|
|
508
|
+
title="Optional Dependencies",
|
|
509
|
+
category=CheckCategory.ENVIRONMENT,
|
|
510
|
+
status=CheckStatus.PASS,
|
|
511
|
+
message=f"All {len(available)} optional packages available",
|
|
512
|
+
metadata={"available": available},
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
@register_check(
|
|
517
|
+
id="stale_packages",
|
|
518
|
+
title="Stale Package Artifacts",
|
|
519
|
+
description="Check for stale praisonaiagents artifacts in site-packages",
|
|
520
|
+
category=CheckCategory.ENVIRONMENT,
|
|
521
|
+
severity=CheckSeverity.CRITICAL,
|
|
522
|
+
)
|
|
523
|
+
def check_stale_packages(config: DoctorConfig) -> CheckResult:
|
|
524
|
+
"""
|
|
525
|
+
Check for stale praisonaiagents artifacts in site-packages.
|
|
526
|
+
|
|
527
|
+
This detects namespace package shadowing issues where a stale directory
|
|
528
|
+
in site-packages (without __init__.py) shadows the real package.
|
|
529
|
+
"""
|
|
530
|
+
import site
|
|
531
|
+
|
|
532
|
+
stale_dirs = []
|
|
533
|
+
|
|
534
|
+
# Check all site-packages directories
|
|
535
|
+
try:
|
|
536
|
+
site_packages = site.getsitepackages()
|
|
537
|
+
except AttributeError:
|
|
538
|
+
# Some environments don't have getsitepackages
|
|
539
|
+
site_packages = []
|
|
540
|
+
|
|
541
|
+
# Also check user site-packages
|
|
542
|
+
user_site = site.getusersitepackages() if hasattr(site, 'getusersitepackages') else None
|
|
543
|
+
if user_site:
|
|
544
|
+
site_packages = list(site_packages) + [user_site]
|
|
545
|
+
|
|
546
|
+
for sp in site_packages:
|
|
547
|
+
praisonai_dir = os.path.join(sp, 'praisonaiagents')
|
|
548
|
+
if os.path.isdir(praisonai_dir):
|
|
549
|
+
init_path = os.path.join(praisonai_dir, '__init__.py')
|
|
550
|
+
if not os.path.exists(init_path):
|
|
551
|
+
# This is a stale namespace package directory
|
|
552
|
+
stale_dirs.append(praisonai_dir)
|
|
553
|
+
|
|
554
|
+
if stale_dirs:
|
|
555
|
+
return CheckResult(
|
|
556
|
+
id="stale_packages",
|
|
557
|
+
title="Stale Package Artifacts",
|
|
558
|
+
category=CheckCategory.ENVIRONMENT,
|
|
559
|
+
status=CheckStatus.FAIL,
|
|
560
|
+
message=f"Found {len(stale_dirs)} stale praisonaiagents directory(ies)",
|
|
561
|
+
details=f"Stale directories: {', '.join(stale_dirs)}",
|
|
562
|
+
remediation=(
|
|
563
|
+
"Remove stale directories to fix import errors:\n"
|
|
564
|
+
f" rm -rf {stale_dirs[0]}\n"
|
|
565
|
+
"Then reinstall: pip install praisonaiagents"
|
|
566
|
+
),
|
|
567
|
+
severity=CheckSeverity.CRITICAL,
|
|
568
|
+
metadata={"stale_dirs": stale_dirs},
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Also verify the package loads correctly (not as namespace)
|
|
572
|
+
try:
|
|
573
|
+
import praisonaiagents
|
|
574
|
+
if praisonaiagents.__file__ is None:
|
|
575
|
+
return CheckResult(
|
|
576
|
+
id="stale_packages",
|
|
577
|
+
title="Stale Package Artifacts",
|
|
578
|
+
category=CheckCategory.ENVIRONMENT,
|
|
579
|
+
status=CheckStatus.FAIL,
|
|
580
|
+
message="praisonaiagents loaded as namespace package",
|
|
581
|
+
details="__file__ is None, indicating namespace package shadowing",
|
|
582
|
+
remediation=(
|
|
583
|
+
"Remove stale praisonaiagents directory from site-packages:\n"
|
|
584
|
+
" rm -rf $(python -c \"import site; print(site.getsitepackages()[0])\")/praisonaiagents/\n"
|
|
585
|
+
"Then reinstall: pip install praisonaiagents"
|
|
586
|
+
),
|
|
587
|
+
severity=CheckSeverity.CRITICAL,
|
|
588
|
+
)
|
|
589
|
+
except ImportError:
|
|
590
|
+
pass # Package not installed - handled by praisonaiagents_package check
|
|
591
|
+
|
|
592
|
+
return CheckResult(
|
|
593
|
+
id="stale_packages",
|
|
594
|
+
title="Stale Package Artifacts",
|
|
595
|
+
category=CheckCategory.ENVIRONMENT,
|
|
596
|
+
status=CheckStatus.PASS,
|
|
597
|
+
message="No stale package artifacts found",
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
@register_check(
|
|
602
|
+
id="model_env_vars",
|
|
603
|
+
title="Model Configuration",
|
|
604
|
+
description="Check model-related environment variables",
|
|
605
|
+
category=CheckCategory.ENVIRONMENT,
|
|
606
|
+
severity=CheckSeverity.INFO,
|
|
607
|
+
)
|
|
608
|
+
def check_model_env_vars(config: DoctorConfig) -> CheckResult:
|
|
609
|
+
"""Check model-related environment variables."""
|
|
610
|
+
model_vars = {
|
|
611
|
+
"MODEL_NAME": os.environ.get("MODEL_NAME"),
|
|
612
|
+
"OPENAI_MODEL_NAME": os.environ.get("OPENAI_MODEL_NAME"),
|
|
613
|
+
"OPENAI_BASE_URL": os.environ.get("OPENAI_BASE_URL"),
|
|
614
|
+
"OPENAI_API_BASE": os.environ.get("OPENAI_API_BASE"),
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
configured = {k: v for k, v in model_vars.items() if v}
|
|
618
|
+
|
|
619
|
+
if configured:
|
|
620
|
+
details = ", ".join(f"{k}={v}" for k, v in configured.items())
|
|
621
|
+
return CheckResult(
|
|
622
|
+
id="model_env_vars",
|
|
623
|
+
title="Model Configuration",
|
|
624
|
+
category=CheckCategory.ENVIRONMENT,
|
|
625
|
+
status=CheckStatus.PASS,
|
|
626
|
+
message=f"Model config: {details}",
|
|
627
|
+
metadata=configured,
|
|
628
|
+
)
|
|
629
|
+
else:
|
|
630
|
+
return CheckResult(
|
|
631
|
+
id="model_env_vars",
|
|
632
|
+
title="Model Configuration",
|
|
633
|
+
category=CheckCategory.ENVIRONMENT,
|
|
634
|
+
status=CheckStatus.PASS,
|
|
635
|
+
message="Using default model configuration (gpt-4o-mini)",
|
|
636
|
+
metadata={"default_model": "gpt-4o-mini"},
|
|
637
|
+
)
|