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,220 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime configuration migration checks.
|
|
3
|
+
|
|
4
|
+
Checks for legacy cli_backend configuration and provides migration to
|
|
5
|
+
the new model-scoped runtime configuration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import yaml
|
|
10
|
+
import json
|
|
11
|
+
import shutil
|
|
12
|
+
import copy
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Dict, List, Optional, Union
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
|
|
17
|
+
from ..models import CheckCategory, CheckResult, CheckStatus, CheckSeverity, DoctorConfig
|
|
18
|
+
from ..registry import register_check
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _find_config_file(config_file: Optional[str] = None) -> Optional[Path]:
|
|
22
|
+
"""Find the configuration file to check."""
|
|
23
|
+
if config_file:
|
|
24
|
+
path = Path(config_file)
|
|
25
|
+
return path if path.exists() else None
|
|
26
|
+
|
|
27
|
+
# Search for common config files
|
|
28
|
+
current_dir = Path.cwd()
|
|
29
|
+
for filename in ["agents.yaml", "agents.yml", "config.yaml", "config.yml"]:
|
|
30
|
+
path = current_dir / filename
|
|
31
|
+
if path.exists():
|
|
32
|
+
return path
|
|
33
|
+
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _load_config(config_path: Path) -> Dict:
|
|
38
|
+
"""Load configuration from YAML file."""
|
|
39
|
+
try:
|
|
40
|
+
with open(config_path, 'r', encoding='utf-8') as f:
|
|
41
|
+
return yaml.safe_load(f) or {}
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise ValueError(f"Failed to load config file: {e}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _save_config(config_path: Path, config: Dict, create_backup: bool = True) -> str:
|
|
47
|
+
"""Save configuration to YAML file with optional backup."""
|
|
48
|
+
backup_info = ""
|
|
49
|
+
|
|
50
|
+
# Serialize first to ensure it's valid YAML
|
|
51
|
+
try:
|
|
52
|
+
yaml_content = yaml.dump(config, default_flow_style=False, sort_keys=False, indent=2)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
raise ValueError(f"Failed to serialize configuration to YAML: {e}")
|
|
55
|
+
|
|
56
|
+
if create_backup:
|
|
57
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
58
|
+
backup_path = config_path.with_name(f"{config_path.stem}.backup.{timestamp}.yaml")
|
|
59
|
+
shutil.copy2(config_path, backup_path)
|
|
60
|
+
backup_info = f" (backup: {backup_path.name})"
|
|
61
|
+
|
|
62
|
+
with open(config_path, 'w', encoding='utf-8') as f:
|
|
63
|
+
f.write(yaml_content)
|
|
64
|
+
|
|
65
|
+
return backup_info
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@register_check(
|
|
69
|
+
id="runtime.config_migration",
|
|
70
|
+
title="Runtime Configuration Migration",
|
|
71
|
+
description="Check for legacy cli_backend configuration and migrate to model-scoped runtime",
|
|
72
|
+
category=CheckCategory.RUNTIME
|
|
73
|
+
)
|
|
74
|
+
def check_runtime_config_migration(config: DoctorConfig) -> CheckResult:
|
|
75
|
+
"""
|
|
76
|
+
Check for legacy cli_backend configuration and provide migration path.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
config: DoctorConfig instance with fix and execute flags
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
config_path = _find_config_file(config.config_file)
|
|
83
|
+
|
|
84
|
+
# If user specified a file and it doesn't exist, return ERROR
|
|
85
|
+
if config.config_file and not config_path:
|
|
86
|
+
return CheckResult(
|
|
87
|
+
id="runtime.config_file_found",
|
|
88
|
+
title="Configuration File Check",
|
|
89
|
+
category=CheckCategory.RUNTIME,
|
|
90
|
+
status=CheckStatus.ERROR,
|
|
91
|
+
message=f"Specified configuration file not found: {config.config_file}",
|
|
92
|
+
severity=CheckSeverity.HIGH
|
|
93
|
+
)
|
|
94
|
+
elif not config_path:
|
|
95
|
+
return CheckResult(
|
|
96
|
+
id="runtime.config_file_found",
|
|
97
|
+
title="Configuration File Check",
|
|
98
|
+
category=CheckCategory.RUNTIME,
|
|
99
|
+
status=CheckStatus.SKIP,
|
|
100
|
+
message="No configuration file found to check",
|
|
101
|
+
details="Searched for: agents.yaml, agents.yml, config.yaml, config.yml in current directory",
|
|
102
|
+
severity=CheckSeverity.INFO
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Load configuration
|
|
106
|
+
try:
|
|
107
|
+
yaml_config = _load_config(config_path)
|
|
108
|
+
except ValueError as e:
|
|
109
|
+
return CheckResult(
|
|
110
|
+
id="runtime.config_load",
|
|
111
|
+
title="Configuration Load",
|
|
112
|
+
category=CheckCategory.RUNTIME,
|
|
113
|
+
status=CheckStatus.ERROR,
|
|
114
|
+
message=f"Failed to load configuration file: {e}",
|
|
115
|
+
severity=CheckSeverity.HIGH
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Import the migration functionality from praisonaiagents
|
|
119
|
+
try:
|
|
120
|
+
from praisonaiagents.runtime import collect_findings, apply_fixes
|
|
121
|
+
except ImportError as e:
|
|
122
|
+
return CheckResult(
|
|
123
|
+
id="runtime.config_migration",
|
|
124
|
+
title="Runtime Configuration Migration",
|
|
125
|
+
category=CheckCategory.RUNTIME,
|
|
126
|
+
status=CheckStatus.ERROR,
|
|
127
|
+
message=f"Could not import migration tools: {e}",
|
|
128
|
+
details="Ensure praisonaiagents is installed: pip install praisonaiagents",
|
|
129
|
+
severity=CheckSeverity.HIGH
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Collect findings from all registered rules
|
|
133
|
+
findings = collect_findings(yaml_config)
|
|
134
|
+
|
|
135
|
+
if not findings:
|
|
136
|
+
return CheckResult(
|
|
137
|
+
id="runtime.config_migration",
|
|
138
|
+
title="Runtime Configuration Migration",
|
|
139
|
+
category=CheckCategory.RUNTIME,
|
|
140
|
+
status=CheckStatus.PASS,
|
|
141
|
+
message=f"Configuration is up to date: {config_path.name}",
|
|
142
|
+
details="No legacy cli_backend fields found",
|
|
143
|
+
severity=CheckSeverity.INFO
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Prepare details about findings
|
|
147
|
+
details = []
|
|
148
|
+
for finding in findings:
|
|
149
|
+
details.append(f"• {finding.description}")
|
|
150
|
+
if finding.details:
|
|
151
|
+
details.append(f" {finding.details}")
|
|
152
|
+
|
|
153
|
+
# If not fixing, just report findings
|
|
154
|
+
if not config.fix:
|
|
155
|
+
return CheckResult(
|
|
156
|
+
id="runtime.config_migration",
|
|
157
|
+
title="Runtime Configuration Migration",
|
|
158
|
+
category=CheckCategory.RUNTIME,
|
|
159
|
+
status=CheckStatus.WARN,
|
|
160
|
+
message=f"Found {len(findings)} legacy configuration(s) in {config_path.name}",
|
|
161
|
+
details="\n".join(details),
|
|
162
|
+
severity=CheckSeverity.MEDIUM,
|
|
163
|
+
fix_suggestion="Run 'praisonai doctor runtime --fix' to migrate automatically"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Apply fixes (dry-run or execute)
|
|
167
|
+
try:
|
|
168
|
+
migrated_config = apply_fixes(yaml_config)
|
|
169
|
+
|
|
170
|
+
# Show what would be changed
|
|
171
|
+
if config.fix and not config.execute:
|
|
172
|
+
# Dry-run mode
|
|
173
|
+
preview = []
|
|
174
|
+
preview.append(f"Would migrate {len(findings)} legacy configuration(s):")
|
|
175
|
+
preview.extend(details)
|
|
176
|
+
preview.append("\nTo apply changes, run with --fix --execute")
|
|
177
|
+
|
|
178
|
+
return CheckResult(
|
|
179
|
+
id="runtime.config_migration",
|
|
180
|
+
title="Runtime Configuration Migration (Dry-Run)",
|
|
181
|
+
category=CheckCategory.RUNTIME,
|
|
182
|
+
status=CheckStatus.INFO,
|
|
183
|
+
message=f"Preview of changes for {config_path.name}",
|
|
184
|
+
details="\n".join(preview),
|
|
185
|
+
severity=CheckSeverity.INFO
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Execute the migration
|
|
189
|
+
if config.fix and config.execute:
|
|
190
|
+
backup_info = _save_config(config_path, migrated_config)
|
|
191
|
+
|
|
192
|
+
return CheckResult(
|
|
193
|
+
id="runtime.config_migration",
|
|
194
|
+
title="Runtime Configuration Migration",
|
|
195
|
+
category=CheckCategory.RUNTIME,
|
|
196
|
+
status=CheckStatus.PASS,
|
|
197
|
+
message=f"Successfully migrated {len(findings)} legacy configuration(s)",
|
|
198
|
+
details=f"Updated: {config_path.name}{backup_info}",
|
|
199
|
+
severity=CheckSeverity.INFO
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
return CheckResult(
|
|
204
|
+
id="runtime.config_migration",
|
|
205
|
+
title="Runtime Configuration Migration",
|
|
206
|
+
category=CheckCategory.RUNTIME,
|
|
207
|
+
status=CheckStatus.ERROR,
|
|
208
|
+
message=f"Failed to apply migration: {e}",
|
|
209
|
+
severity=CheckSeverity.HIGH
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
return CheckResult(
|
|
214
|
+
id="runtime.config_migration",
|
|
215
|
+
title="Runtime Configuration Migration",
|
|
216
|
+
category=CheckCategory.RUNTIME,
|
|
217
|
+
status=CheckStatus.ERROR,
|
|
218
|
+
message=f"Runtime migration check failed: {e}",
|
|
219
|
+
severity=CheckSeverity.HIGH
|
|
220
|
+
)
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Selftest checks for the Doctor CLI module.
|
|
3
|
+
|
|
4
|
+
Performs minimal agent dry-run to validate the system.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
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
|
+
@register_check(
|
|
20
|
+
id="selftest_agent_import",
|
|
21
|
+
title="Agent Import",
|
|
22
|
+
description="Check Agent class can be imported",
|
|
23
|
+
category=CheckCategory.SELFTEST,
|
|
24
|
+
severity=CheckSeverity.HIGH,
|
|
25
|
+
)
|
|
26
|
+
def check_selftest_agent_import(config: DoctorConfig) -> CheckResult:
|
|
27
|
+
"""Check Agent class can be imported."""
|
|
28
|
+
try:
|
|
29
|
+
from praisonaiagents import Agent
|
|
30
|
+
return CheckResult(
|
|
31
|
+
id="selftest_agent_import",
|
|
32
|
+
title="Agent Import",
|
|
33
|
+
category=CheckCategory.SELFTEST,
|
|
34
|
+
status=CheckStatus.PASS,
|
|
35
|
+
message="Agent class imported successfully",
|
|
36
|
+
)
|
|
37
|
+
except ImportError as e:
|
|
38
|
+
return CheckResult(
|
|
39
|
+
id="selftest_agent_import",
|
|
40
|
+
title="Agent Import",
|
|
41
|
+
category=CheckCategory.SELFTEST,
|
|
42
|
+
status=CheckStatus.FAIL,
|
|
43
|
+
message=f"Cannot import Agent: {e}",
|
|
44
|
+
remediation="Ensure praisonaiagents is properly installed",
|
|
45
|
+
severity=CheckSeverity.CRITICAL,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@register_check(
|
|
50
|
+
id="selftest_agent_create",
|
|
51
|
+
title="Agent Creation",
|
|
52
|
+
description="Check Agent can be instantiated",
|
|
53
|
+
category=CheckCategory.SELFTEST,
|
|
54
|
+
severity=CheckSeverity.HIGH,
|
|
55
|
+
dependencies=["selftest_agent_import"],
|
|
56
|
+
)
|
|
57
|
+
def check_selftest_agent_create(config: DoctorConfig) -> CheckResult:
|
|
58
|
+
"""Check Agent can be instantiated."""
|
|
59
|
+
try:
|
|
60
|
+
from praisonaiagents import Agent
|
|
61
|
+
|
|
62
|
+
# Create a minimal agent without making API calls
|
|
63
|
+
agent = Agent(
|
|
64
|
+
name="DoctorTestAgent",
|
|
65
|
+
instructions="You are a test agent.",
|
|
66
|
+
llm="gpt-4o-mini", # Default model
|
|
67
|
+
output="minimal",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return CheckResult(
|
|
71
|
+
id="selftest_agent_create",
|
|
72
|
+
title="Agent Creation",
|
|
73
|
+
category=CheckCategory.SELFTEST,
|
|
74
|
+
status=CheckStatus.PASS,
|
|
75
|
+
message="Agent instantiated successfully",
|
|
76
|
+
metadata={"agent_name": agent.name},
|
|
77
|
+
)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
return CheckResult(
|
|
80
|
+
id="selftest_agent_create",
|
|
81
|
+
title="Agent Creation",
|
|
82
|
+
category=CheckCategory.SELFTEST,
|
|
83
|
+
status=CheckStatus.FAIL,
|
|
84
|
+
message=f"Agent creation failed: {type(e).__name__}",
|
|
85
|
+
details=str(e)[:200],
|
|
86
|
+
remediation="Check configuration and dependencies",
|
|
87
|
+
severity=CheckSeverity.HIGH,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@register_check(
|
|
92
|
+
id="selftest_llm_config",
|
|
93
|
+
title="LLM Configuration",
|
|
94
|
+
description="Check LLM configuration is valid",
|
|
95
|
+
category=CheckCategory.SELFTEST,
|
|
96
|
+
severity=CheckSeverity.MEDIUM,
|
|
97
|
+
)
|
|
98
|
+
def check_selftest_llm_config(config: DoctorConfig) -> CheckResult:
|
|
99
|
+
"""Check LLM configuration is valid."""
|
|
100
|
+
# Check for API key
|
|
101
|
+
openai_key = os.environ.get("OPENAI_API_KEY")
|
|
102
|
+
anthropic_key = os.environ.get("ANTHROPIC_API_KEY")
|
|
103
|
+
google_key = os.environ.get("GOOGLE_API_KEY") or os.environ.get("GEMINI_API_KEY")
|
|
104
|
+
ollama_host = os.environ.get("OLLAMA_HOST")
|
|
105
|
+
|
|
106
|
+
providers = []
|
|
107
|
+
if openai_key:
|
|
108
|
+
providers.append("OpenAI")
|
|
109
|
+
if anthropic_key:
|
|
110
|
+
providers.append("Anthropic")
|
|
111
|
+
if google_key:
|
|
112
|
+
providers.append("Google")
|
|
113
|
+
if ollama_host:
|
|
114
|
+
providers.append("Ollama")
|
|
115
|
+
|
|
116
|
+
if providers:
|
|
117
|
+
return CheckResult(
|
|
118
|
+
id="selftest_llm_config",
|
|
119
|
+
title="LLM Configuration",
|
|
120
|
+
category=CheckCategory.SELFTEST,
|
|
121
|
+
status=CheckStatus.PASS,
|
|
122
|
+
message=f"LLM provider(s) configured: {', '.join(providers)}",
|
|
123
|
+
metadata={"providers": providers},
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
return CheckResult(
|
|
127
|
+
id="selftest_llm_config",
|
|
128
|
+
title="LLM Configuration",
|
|
129
|
+
category=CheckCategory.SELFTEST,
|
|
130
|
+
status=CheckStatus.FAIL,
|
|
131
|
+
message="No LLM provider configured",
|
|
132
|
+
remediation="Set OPENAI_API_KEY or another provider's API key",
|
|
133
|
+
severity=CheckSeverity.HIGH,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@register_check(
|
|
138
|
+
id="selftest_mock_chat",
|
|
139
|
+
title="Mock Chat Test",
|
|
140
|
+
description="Test agent chat with mock response",
|
|
141
|
+
category=CheckCategory.SELFTEST,
|
|
142
|
+
severity=CheckSeverity.MEDIUM,
|
|
143
|
+
requires_deep=True,
|
|
144
|
+
)
|
|
145
|
+
def check_selftest_mock_chat(config: DoctorConfig) -> CheckResult:
|
|
146
|
+
"""Test agent chat with mock response (no API call)."""
|
|
147
|
+
if not config.mock and not config.live:
|
|
148
|
+
# Default to mock in deep mode
|
|
149
|
+
config.mock = True
|
|
150
|
+
|
|
151
|
+
if config.live:
|
|
152
|
+
return CheckResult(
|
|
153
|
+
id="selftest_mock_chat",
|
|
154
|
+
title="Mock Chat Test",
|
|
155
|
+
category=CheckCategory.SELFTEST,
|
|
156
|
+
status=CheckStatus.SKIP,
|
|
157
|
+
message="Skipped (--live mode uses live API)",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
# Test basic agent functionality without making API calls
|
|
162
|
+
from praisonaiagents import Agent
|
|
163
|
+
|
|
164
|
+
agent = Agent(
|
|
165
|
+
name="MockTestAgent",
|
|
166
|
+
instructions="You are a test agent. Always respond with 'OK'.",
|
|
167
|
+
llm="gpt-4o-mini",
|
|
168
|
+
output="minimal",
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Verify agent is properly configured
|
|
172
|
+
if hasattr(agent, 'name') and hasattr(agent, 'instructions'):
|
|
173
|
+
return CheckResult(
|
|
174
|
+
id="selftest_mock_chat",
|
|
175
|
+
title="Mock Chat Test",
|
|
176
|
+
category=CheckCategory.SELFTEST,
|
|
177
|
+
status=CheckStatus.PASS,
|
|
178
|
+
message="Agent mock test passed",
|
|
179
|
+
)
|
|
180
|
+
else:
|
|
181
|
+
return CheckResult(
|
|
182
|
+
id="selftest_mock_chat",
|
|
183
|
+
title="Mock Chat Test",
|
|
184
|
+
category=CheckCategory.SELFTEST,
|
|
185
|
+
status=CheckStatus.FAIL,
|
|
186
|
+
message="Agent missing expected attributes",
|
|
187
|
+
)
|
|
188
|
+
except Exception as e:
|
|
189
|
+
return CheckResult(
|
|
190
|
+
id="selftest_mock_chat",
|
|
191
|
+
title="Mock Chat Test",
|
|
192
|
+
category=CheckCategory.SELFTEST,
|
|
193
|
+
status=CheckStatus.FAIL,
|
|
194
|
+
message=f"Mock test failed: {type(e).__name__}",
|
|
195
|
+
details=str(e)[:200],
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@register_check(
|
|
200
|
+
id="selftest_live_chat",
|
|
201
|
+
title="Live Chat Test",
|
|
202
|
+
description="Test agent chat with live API call",
|
|
203
|
+
category=CheckCategory.SELFTEST,
|
|
204
|
+
severity=CheckSeverity.LOW,
|
|
205
|
+
requires_deep=True,
|
|
206
|
+
)
|
|
207
|
+
def check_selftest_live_chat(config: DoctorConfig) -> CheckResult:
|
|
208
|
+
"""Test agent chat with live API call."""
|
|
209
|
+
if not config.live:
|
|
210
|
+
return CheckResult(
|
|
211
|
+
id="selftest_live_chat",
|
|
212
|
+
title="Live Chat Test",
|
|
213
|
+
category=CheckCategory.SELFTEST,
|
|
214
|
+
status=CheckStatus.SKIP,
|
|
215
|
+
message="Skipped (use --live to enable)",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Check for API key first
|
|
219
|
+
if not os.environ.get("OPENAI_API_KEY"):
|
|
220
|
+
return CheckResult(
|
|
221
|
+
id="selftest_live_chat",
|
|
222
|
+
title="Live Chat Test",
|
|
223
|
+
category=CheckCategory.SELFTEST,
|
|
224
|
+
status=CheckStatus.SKIP,
|
|
225
|
+
message="Skipped (OPENAI_API_KEY not set)",
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
from praisonaiagents import Agent
|
|
230
|
+
|
|
231
|
+
model = config.model or "gpt-4o-mini"
|
|
232
|
+
|
|
233
|
+
agent = Agent(
|
|
234
|
+
name="LiveTestAgent",
|
|
235
|
+
instructions="You are a test agent. Respond with exactly: 'Doctor test OK'",
|
|
236
|
+
llm=model,
|
|
237
|
+
output="minimal",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Make a simple API call
|
|
241
|
+
response = agent.chat("Say hello")
|
|
242
|
+
|
|
243
|
+
if response:
|
|
244
|
+
return CheckResult(
|
|
245
|
+
id="selftest_live_chat",
|
|
246
|
+
title="Live Chat Test",
|
|
247
|
+
category=CheckCategory.SELFTEST,
|
|
248
|
+
status=CheckStatus.PASS,
|
|
249
|
+
message=f"Live API call successful (model: {model})",
|
|
250
|
+
metadata={"model": model, "response_length": len(str(response))},
|
|
251
|
+
)
|
|
252
|
+
else:
|
|
253
|
+
return CheckResult(
|
|
254
|
+
id="selftest_live_chat",
|
|
255
|
+
title="Live Chat Test",
|
|
256
|
+
category=CheckCategory.SELFTEST,
|
|
257
|
+
status=CheckStatus.FAIL,
|
|
258
|
+
message="Live API call returned empty response",
|
|
259
|
+
)
|
|
260
|
+
except Exception as e:
|
|
261
|
+
return CheckResult(
|
|
262
|
+
id="selftest_live_chat",
|
|
263
|
+
title="Live Chat Test",
|
|
264
|
+
category=CheckCategory.SELFTEST,
|
|
265
|
+
status=CheckStatus.FAIL,
|
|
266
|
+
message=f"Live API call failed: {type(e).__name__}",
|
|
267
|
+
details=str(e)[:200],
|
|
268
|
+
remediation="Check API key and network connectivity",
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@register_check(
|
|
273
|
+
id="selftest_tools_wiring",
|
|
274
|
+
title="Tools Wiring",
|
|
275
|
+
description="Check tools can be wired to agent",
|
|
276
|
+
category=CheckCategory.SELFTEST,
|
|
277
|
+
severity=CheckSeverity.LOW,
|
|
278
|
+
)
|
|
279
|
+
def check_selftest_tools_wiring(config: DoctorConfig) -> CheckResult:
|
|
280
|
+
"""Check tools can be wired to agent."""
|
|
281
|
+
try:
|
|
282
|
+
from praisonaiagents import Agent
|
|
283
|
+
|
|
284
|
+
# Define a simple test tool
|
|
285
|
+
def test_tool(x: str) -> str:
|
|
286
|
+
"""A test tool that echoes input."""
|
|
287
|
+
return f"Echo: {x}"
|
|
288
|
+
|
|
289
|
+
agent = Agent(
|
|
290
|
+
name="ToolTestAgent",
|
|
291
|
+
instructions="You are a test agent with tools.",
|
|
292
|
+
tools=[test_tool],
|
|
293
|
+
llm="gpt-4o-mini",
|
|
294
|
+
output="minimal",
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Check tools are registered
|
|
298
|
+
if hasattr(agent, 'tools') or hasattr(agent, '_tools'):
|
|
299
|
+
return CheckResult(
|
|
300
|
+
id="selftest_tools_wiring",
|
|
301
|
+
title="Tools Wiring",
|
|
302
|
+
category=CheckCategory.SELFTEST,
|
|
303
|
+
status=CheckStatus.PASS,
|
|
304
|
+
message="Tools wired to agent successfully",
|
|
305
|
+
)
|
|
306
|
+
else:
|
|
307
|
+
return CheckResult(
|
|
308
|
+
id="selftest_tools_wiring",
|
|
309
|
+
title="Tools Wiring",
|
|
310
|
+
category=CheckCategory.SELFTEST,
|
|
311
|
+
status=CheckStatus.WARN,
|
|
312
|
+
message="Tools wiring could not be verified",
|
|
313
|
+
)
|
|
314
|
+
except Exception as e:
|
|
315
|
+
return CheckResult(
|
|
316
|
+
id="selftest_tools_wiring",
|
|
317
|
+
title="Tools Wiring",
|
|
318
|
+
category=CheckCategory.SELFTEST,
|
|
319
|
+
status=CheckStatus.FAIL,
|
|
320
|
+
message=f"Tools wiring failed: {type(e).__name__}",
|
|
321
|
+
details=str(e)[:200],
|
|
322
|
+
)
|