moai-adk 0.3.0__tar.gz

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.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (86) hide show
  1. moai_adk-0.3.0/.gitignore +60 -0
  2. moai_adk-0.3.0/LICENSE +21 -0
  3. moai_adk-0.3.0/PKG-INFO +20 -0
  4. moai_adk-0.3.0/pyproject.toml +73 -0
  5. moai_adk-0.3.0/src/moai_adk/__init__.py +8 -0
  6. moai_adk-0.3.0/src/moai_adk/__main__.py +86 -0
  7. moai_adk-0.3.0/src/moai_adk/cli/__init__.py +2 -0
  8. moai_adk-0.3.0/src/moai_adk/cli/commands/__init__.py +16 -0
  9. moai_adk-0.3.0/src/moai_adk/cli/commands/backup.py +56 -0
  10. moai_adk-0.3.0/src/moai_adk/cli/commands/doctor.py +184 -0
  11. moai_adk-0.3.0/src/moai_adk/cli/commands/init.py +284 -0
  12. moai_adk-0.3.0/src/moai_adk/cli/commands/restore.py +77 -0
  13. moai_adk-0.3.0/src/moai_adk/cli/commands/status.py +79 -0
  14. moai_adk-0.3.0/src/moai_adk/cli/commands/update.py +133 -0
  15. moai_adk-0.3.0/src/moai_adk/cli/main.py +12 -0
  16. moai_adk-0.3.0/src/moai_adk/cli/prompts/__init__.py +5 -0
  17. moai_adk-0.3.0/src/moai_adk/cli/prompts/init_prompts.py +159 -0
  18. moai_adk-0.3.0/src/moai_adk/core/__init__.py +2 -0
  19. moai_adk-0.3.0/src/moai_adk/core/git/__init__.py +24 -0
  20. moai_adk-0.3.0/src/moai_adk/core/git/branch.py +26 -0
  21. moai_adk-0.3.0/src/moai_adk/core/git/branch_manager.py +137 -0
  22. moai_adk-0.3.0/src/moai_adk/core/git/checkpoint.py +140 -0
  23. moai_adk-0.3.0/src/moai_adk/core/git/commit.py +68 -0
  24. moai_adk-0.3.0/src/moai_adk/core/git/event_detector.py +81 -0
  25. moai_adk-0.3.0/src/moai_adk/core/git/manager.py +127 -0
  26. moai_adk-0.3.0/src/moai_adk/core/project/__init__.py +2 -0
  27. moai_adk-0.3.0/src/moai_adk/core/project/backup_utils.py +84 -0
  28. moai_adk-0.3.0/src/moai_adk/core/project/checker.py +302 -0
  29. moai_adk-0.3.0/src/moai_adk/core/project/detector.py +105 -0
  30. moai_adk-0.3.0/src/moai_adk/core/project/initializer.py +174 -0
  31. moai_adk-0.3.0/src/moai_adk/core/project/phase_executor.py +297 -0
  32. moai_adk-0.3.0/src/moai_adk/core/project/validator.py +118 -0
  33. moai_adk-0.3.0/src/moai_adk/core/quality/__init__.py +6 -0
  34. moai_adk-0.3.0/src/moai_adk/core/quality/trust_checker.py +441 -0
  35. moai_adk-0.3.0/src/moai_adk/core/quality/validators/__init__.py +6 -0
  36. moai_adk-0.3.0/src/moai_adk/core/quality/validators/base_validator.py +19 -0
  37. moai_adk-0.3.0/src/moai_adk/core/template/__init__.py +8 -0
  38. moai_adk-0.3.0/src/moai_adk/core/template/backup.py +95 -0
  39. moai_adk-0.3.0/src/moai_adk/core/template/config.py +95 -0
  40. moai_adk-0.3.0/src/moai_adk/core/template/languages.py +44 -0
  41. moai_adk-0.3.0/src/moai_adk/core/template/merger.py +117 -0
  42. moai_adk-0.3.0/src/moai_adk/core/template/processor.py +310 -0
  43. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/cc-manager.md +474 -0
  44. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/code-builder.md +534 -0
  45. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/debug-helper.md +302 -0
  46. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/doc-syncer.md +175 -0
  47. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/git-manager.md +200 -0
  48. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/project-manager.md +152 -0
  49. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/spec-builder.md +256 -0
  50. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/tag-agent.md +247 -0
  51. moai_adk-0.3.0/src/moai_adk/templates/.claude/agents/alfred/trust-checker.md +332 -0
  52. moai_adk-0.3.0/src/moai_adk/templates/.claude/commands/alfred/0-project.md +523 -0
  53. moai_adk-0.3.0/src/moai_adk/templates/.claude/commands/alfred/1-spec.md +531 -0
  54. moai_adk-0.3.0/src/moai_adk/templates/.claude/commands/alfred/2-build.md +413 -0
  55. moai_adk-0.3.0/src/moai_adk/templates/.claude/commands/alfred/3-sync.md +552 -0
  56. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/README.md +238 -0
  57. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +165 -0
  58. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/core/__init__.py +79 -0
  59. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +271 -0
  60. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/core/context.py +110 -0
  61. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/core/project.py +284 -0
  62. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/core/tags.py +244 -0
  63. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +23 -0
  64. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/compact.py +51 -0
  65. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +25 -0
  66. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/session.py +80 -0
  67. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +71 -0
  68. moai_adk-0.3.0/src/moai_adk/templates/.claude/hooks/alfred/handlers/user.py +41 -0
  69. moai_adk-0.3.0/src/moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +635 -0
  70. moai_adk-0.3.0/src/moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +691 -0
  71. moai_adk-0.3.0/src/moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +469 -0
  72. moai_adk-0.3.0/src/moai_adk/templates/.claude/settings.json +135 -0
  73. moai_adk-0.3.0/src/moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +68 -0
  74. moai_adk-0.3.0/src/moai_adk/templates/.github/workflows/moai-gitflow.yml +255 -0
  75. moai_adk-0.3.0/src/moai_adk/templates/.gitignore +41 -0
  76. moai_adk-0.3.0/src/moai_adk/templates/.moai/config.json +89 -0
  77. moai_adk-0.3.0/src/moai_adk/templates/.moai/memory/development-guide.md +367 -0
  78. moai_adk-0.3.0/src/moai_adk/templates/.moai/memory/spec-metadata.md +277 -0
  79. moai_adk-0.3.0/src/moai_adk/templates/.moai/project/product.md +121 -0
  80. moai_adk-0.3.0/src/moai_adk/templates/.moai/project/structure.md +150 -0
  81. moai_adk-0.3.0/src/moai_adk/templates/.moai/project/tech.md +221 -0
  82. moai_adk-0.3.0/src/moai_adk/templates/CLAUDE.md +733 -0
  83. moai_adk-0.3.0/src/moai_adk/templates/__init__.py +2 -0
  84. moai_adk-0.3.0/src/moai_adk/utils/__init__.py +8 -0
  85. moai_adk-0.3.0/src/moai_adk/utils/banner.py +42 -0
  86. moai_adk-0.3.0/src/moai_adk/utils/logger.py +152 -0
@@ -0,0 +1,60 @@
1
+ # Build artifacts
2
+ build/
3
+ dist/
4
+ *.egg-info/
5
+ *.egg
6
+
7
+ # Cache
8
+ __pycache__/
9
+ .pytest_cache/
10
+ *.pyc
11
+ *.pyo
12
+ node_modules/
13
+ *.tsbuildinfo
14
+ .tscache/
15
+
16
+ # Backups
17
+ .moai-backups/
18
+ *.backup
19
+ *.bak
20
+
21
+ # Test coverage
22
+ .coverage
23
+ .coverage.*
24
+ coverage.json
25
+ htmlcov/
26
+ .pytest_cache/
27
+
28
+ # Documentation builds
29
+ site/
30
+ docs/_build/
31
+
32
+ # Reports (keep .gitkeep)
33
+ .moai/reports/*.md
34
+ .moai/reports/*.json
35
+ .moai/reports/*.html
36
+
37
+ # Virtual environment
38
+ venv/
39
+ .venv/
40
+ env/
41
+ .env/
42
+
43
+ # IDE
44
+ .vscode/
45
+ .idea/
46
+ *.swp
47
+ *.swo
48
+ *~
49
+
50
+ # OS
51
+ .DS_Store
52
+ Thumbs.db
53
+
54
+ # Logs
55
+ *.log
56
+ logs/
57
+
58
+ # Temporary files
59
+ *.tmp
60
+ *.temp
moai_adk-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 MoAI-ADK Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.4
2
+ Name: moai-adk
3
+ Version: 0.3.0
4
+ Summary: MoAI Agentic Development Kit - SPEC-First TDD with Alfred SuperAgent
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: click>=8.1.0
8
+ Requires-Dist: gitpython>=3.1.45
9
+ Requires-Dist: pyfiglet>=1.0.2
10
+ Requires-Dist: questionary>=2.0.0
11
+ Requires-Dist: rich>=13.0.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: mypy>=1.7.0; extra == 'dev'
14
+ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
15
+ Requires-Dist: pytest-xdist>=3.8.0; extra == 'dev'
16
+ Requires-Dist: pytest>=8.4.2; extra == 'dev'
17
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
18
+ Provides-Extra: security
19
+ Requires-Dist: bandit>=1.8.0; extra == 'security'
20
+ Requires-Dist: pip-audit>=2.7.0; extra == 'security'
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "moai-adk"
3
+ version = "0.3.0"
4
+ description = "MoAI Agentic Development Kit - SPEC-First TDD with Alfred SuperAgent"
5
+ requires-python = ">=3.13"
6
+ dependencies = [
7
+ "click>=8.1.0",
8
+ "rich>=13.0.0",
9
+ "pyfiglet>=1.0.2",
10
+ "questionary>=2.0.0",
11
+ "gitpython>=3.1.45"
12
+ ]
13
+
14
+ [project.optional-dependencies]
15
+ dev = [
16
+ "pytest>=8.4.2",
17
+ "pytest-cov>=7.0.0",
18
+ "pytest-xdist>=3.8.0",
19
+ "ruff>=0.1.0",
20
+ "mypy>=1.7.0"
21
+ ]
22
+ security = [
23
+ "pip-audit>=2.7.0",
24
+ "bandit>=1.8.0"
25
+ ]
26
+
27
+ [tool.pytest.ini_options]
28
+ testpaths = ["tests"]
29
+ python_files = "test_*.py"
30
+ python_classes = "Test*"
31
+ python_functions = "test_*"
32
+ addopts = "-v --cov=src/moai_adk --cov-report=html --cov-report=term-missing"
33
+
34
+ [tool.coverage.run]
35
+ source = ["src/moai_adk"]
36
+ omit = ["tests/*", "*/__pycache__/*"]
37
+ parallel = true
38
+ concurrency = ["multiprocessing"]
39
+
40
+ [tool.coverage.report]
41
+ precision = 2
42
+ show_missing = true
43
+ skip_covered = false
44
+ fail_under = 85
45
+
46
+ [tool.ruff]
47
+ line-length = 120
48
+ target-version = "py313"
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "F", "W", "I", "N"]
52
+ ignore = []
53
+
54
+ [build-system]
55
+ requires = ["hatchling"]
56
+ build-backend = "hatchling.build"
57
+
58
+ [tool.hatch.build.targets.wheel]
59
+ # Include Python packages and templates
60
+ packages = ["src/moai_adk"]
61
+
62
+ # Ensure template files are included in both wheel and editable installs
63
+ [tool.hatch.build]
64
+ include = [
65
+ "src/moai_adk/**/*.py",
66
+ "src/moai_adk/templates/**/*",
67
+ "src/moai_adk/templates/.claude/**/*",
68
+ "src/moai_adk/templates/.moai/**/*",
69
+ "src/moai_adk/templates/.github/**/*"
70
+ ]
71
+
72
+ [project.scripts]
73
+ moai-adk = "moai_adk.__main__:main"
@@ -0,0 +1,8 @@
1
+ # @CODE:PY314-001 | SPEC: SPEC-PY314-001.md | TEST: tests/unit/test_foundation.py
2
+ """MoAI Agentic Development Kit
3
+
4
+ SPEC-First TDD Framework with Alfred SuperAgent
5
+ """
6
+
7
+ __version__ = "0.3.0"
8
+ __all__ = ["__version__"]
@@ -0,0 +1,86 @@
1
+ # @CODE:CLI-001 | SPEC: SPEC-CLI-001.md | TEST: tests/unit/test_cli_commands.py
2
+ """MoAI-ADK CLI Entry Point
3
+
4
+ Implements the CLI entry point:
5
+ - Click-based CLI framework
6
+ - Rich console terminal output
7
+ - ASCII logo rendering
8
+ - --version and --help options
9
+ - Six core commands: init, doctor, status, backup, restore, update
10
+ """
11
+
12
+ import sys
13
+
14
+ import click
15
+ import pyfiglet
16
+ from rich.console import Console
17
+
18
+ from moai_adk import __version__
19
+ from moai_adk.cli.commands.backup import backup
20
+ from moai_adk.cli.commands.doctor import doctor
21
+ from moai_adk.cli.commands.init import init
22
+ from moai_adk.cli.commands.restore import restore
23
+ from moai_adk.cli.commands.status import status
24
+ from moai_adk.cli.commands.update import update
25
+
26
+ console = Console()
27
+
28
+
29
+ def show_logo() -> None:
30
+ """Render the MoAI-ADK ASCII logo with Pyfiglet"""
31
+ # Generate the "MoAI-ADK" banner using the ansi_shadow font
32
+ logo = pyfiglet.figlet_format("MoAI-ADK", font="ansi_shadow")
33
+
34
+ # Print with Rich styling
35
+ console.print(logo, style="cyan bold", highlight=False)
36
+ console.print(" Modu-AI's Agentic Development Kit w/ SuperAgent 🎩 Alfred", style="yellow bold")
37
+ console.print()
38
+ console.print(" Version: ", style="green", end="")
39
+ console.print(__version__, style="cyan bold")
40
+ console.print()
41
+ console.print(" Tip: Run ", style="yellow", end="")
42
+ console.print("python -m moai_adk --help", style="cyan", end="")
43
+ console.print(" to see available commands", style="yellow")
44
+
45
+
46
+ @click.group(invoke_without_command=True)
47
+ @click.version_option(version=__version__, prog_name="MoAI-ADK")
48
+ @click.pass_context
49
+ def cli(ctx: click.Context) -> None:
50
+ """MoAI Agentic Development Kit
51
+
52
+ SPEC-First TDD Framework with Alfred SuperAgent
53
+ """
54
+ # Display the logo when no subcommand is invoked
55
+ if ctx.invoked_subcommand is None:
56
+ show_logo()
57
+
58
+ cli.add_command(init)
59
+ cli.add_command(doctor)
60
+ cli.add_command(status)
61
+ cli.add_command(restore)
62
+ cli.add_command(backup)
63
+ cli.add_command(update)
64
+
65
+
66
+ def main() -> int:
67
+ """CLI entry point"""
68
+ try:
69
+ cli(standalone_mode=False)
70
+ return 0
71
+ except click.Abort:
72
+ # User cancelled with Ctrl+C
73
+ return 130
74
+ except click.ClickException as e:
75
+ e.show()
76
+ return e.exit_code
77
+ except Exception as e:
78
+ console.print(f"[red]Error:[/red] {e}")
79
+ return 1
80
+ finally:
81
+ # Flush the output buffer explicitly
82
+ console.file.flush()
83
+
84
+
85
+ if __name__ == "__main__":
86
+ sys.exit(main())
@@ -0,0 +1,2 @@
1
+ # @CODE:PY314-001 | SPEC: SPEC-PY314-001.md | TEST: tests/unit/test_foundation.py
2
+ """CLI module: Click-based command-line interface"""
@@ -0,0 +1,16 @@
1
+ # @CODE:CLI-001 | SPEC: SPEC-CLI-001.md | TEST: tests/unit/test_cli_commands.py
2
+ """CLI command module
3
+
4
+ Four core commands:
5
+ - init: initialize the project
6
+ - doctor: run system diagnostics
7
+ - status: show project status
8
+ - restore: restore backups
9
+ """
10
+
11
+ from moai_adk.cli.commands.doctor import doctor
12
+ from moai_adk.cli.commands.init import init
13
+ from moai_adk.cli.commands.restore import restore
14
+ from moai_adk.cli.commands.status import status
15
+
16
+ __all__ = ["init", "doctor", "status", "restore"]
@@ -0,0 +1,56 @@
1
+ """Backup command"""
2
+ from pathlib import Path
3
+
4
+ import click
5
+ from rich.console import Console
6
+
7
+ from moai_adk.core.template.processor import TemplateProcessor
8
+
9
+ console = Console()
10
+
11
+
12
+ @click.command()
13
+ @click.option(
14
+ "--path",
15
+ type=click.Path(exists=True),
16
+ default=".",
17
+ help="Project path (default: current directory)"
18
+ )
19
+ def backup(path: str) -> None:
20
+ """Create a backup of the current project.
21
+
22
+ Includes:
23
+ - .claude/ (entire directory)
24
+ - .moai/ (excluding specs and reports)
25
+ - CLAUDE.md
26
+
27
+ Backup location: .moai-backup/YYYYMMDD-HHMMSS/
28
+ """
29
+ try:
30
+ project_path = Path(path).resolve()
31
+
32
+ # Verify the project has been initialized
33
+ if not (project_path / ".moai").exists():
34
+ console.print("[yellow]⚠ Project not initialized[/yellow]")
35
+ raise click.Abort()
36
+
37
+ # Create the backup
38
+ console.print("[cyan]💾 Creating backup...[/cyan]")
39
+ processor = TemplateProcessor(project_path)
40
+ backup_path = processor.create_backup()
41
+
42
+ # Success message
43
+ console.print(f"[green]✓ Backup completed: {backup_path.relative_to(project_path)}[/green]")
44
+
45
+ # Show backup contents
46
+ backup_items = list(backup_path.iterdir())
47
+ for item in backup_items:
48
+ if item.is_dir():
49
+ file_count = len(list(item.rglob("*")))
50
+ console.print(f" ├─ {item.name}/ ({file_count} files)")
51
+ else:
52
+ console.print(f" └─ {item.name}")
53
+
54
+ except Exception as e:
55
+ console.print(f"[red]✗ Backup failed: {e}[/red]")
56
+ raise click.ClickException(str(e)) from e
@@ -0,0 +1,184 @@
1
+ # @CODE:CLI-001 | SPEC: SPEC-CLI-001.md | TEST: tests/unit/test_doctor.py
2
+ """MoAI-ADK doctor command
3
+
4
+ System diagnostics command:
5
+ - Check the Python version
6
+ - Verify Git installation
7
+ - Validate project structure
8
+ - Inspect language-specific tool chains
9
+ """
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import click
15
+ import questionary
16
+ from rich.console import Console
17
+ from rich.table import Table
18
+
19
+ from moai_adk.core.project.checker import SystemChecker, check_environment
20
+ from moai_adk.core.project.detector import detect_project_language
21
+
22
+ console = Console()
23
+
24
+
25
+ @click.command()
26
+ @click.option("--verbose", "-v", is_flag=True, help="Show detailed tool versions and language detection")
27
+ @click.option("--fix", is_flag=True, help="Suggest fixes for missing tools")
28
+ @click.option("--export", type=click.Path(), help="Export diagnostics to JSON file")
29
+ @click.option("--check", type=str, help="Check specific tool only")
30
+ def doctor(verbose: bool, fix: bool, export: str | None, check: str | None) -> None:
31
+ """Check system requirements and project health
32
+
33
+ Verifies:
34
+ - Python version (>= 3.13)
35
+ - Git installation
36
+ - Project structure (.moai directory)
37
+ - Language-specific tool chains (20+ languages)
38
+ """
39
+ try:
40
+ console.print("[cyan]Running system diagnostics...[/cyan]\n")
41
+
42
+ # Run basic environment checks
43
+ results = check_environment()
44
+ diagnostics_data: dict = {"basic_checks": results}
45
+
46
+ # In verbose mode, verify language-specific toolchains
47
+ if verbose or fix:
48
+ language = detect_project_language()
49
+ diagnostics_data["detected_language"] = language
50
+
51
+ if verbose:
52
+ console.print(f"[dim]Detected language: {language or 'Unknown'}[/dim]\n")
53
+
54
+ if language:
55
+ checker = SystemChecker()
56
+ language_tools = checker.check_language_tools(language)
57
+ diagnostics_data["language_tools"] = language_tools
58
+
59
+ if verbose:
60
+ _display_language_tools(language, language_tools, checker)
61
+
62
+ # Specific tool check
63
+ if check:
64
+ _check_specific_tool(check)
65
+ return
66
+
67
+ # Build the base results table
68
+ table = Table(show_header=True, header_style="bold magenta")
69
+ table.add_column("Check", style="dim", width=40)
70
+ table.add_column("Status", justify="center")
71
+
72
+ for check_name, status in results.items():
73
+ icon = "✓" if status else "✗"
74
+ color = "green" if status else "red"
75
+ table.add_row(check_name, f"[{color}]{icon}[/{color}]")
76
+
77
+ console.print(table)
78
+
79
+ # In fix mode, suggest installation commands for missing tools
80
+ if fix and "language_tools" in diagnostics_data:
81
+ _suggest_fixes(diagnostics_data["language_tools"], diagnostics_data.get("detected_language"))
82
+
83
+ # When exporting, write diagnostics to JSON
84
+ if export:
85
+ _export_diagnostics(export, diagnostics_data)
86
+
87
+ # Summarize the overall result
88
+ all_passed = all(results.values())
89
+ if all_passed:
90
+ console.print("\n[green]✓ All checks passed[/green]")
91
+ else:
92
+ console.print("\n[yellow]⚠ Some checks failed[/yellow]")
93
+ console.print("[dim]Run [cyan]python -m moai_adk doctor --verbose[/cyan] for detailed diagnostics[/dim]")
94
+
95
+ except Exception as e:
96
+ console.print(f"[red]✗ Diagnostic failed: {e}[/red]")
97
+ raise
98
+
99
+
100
+ def _display_language_tools(language: str, tools: dict[str, bool], checker: SystemChecker) -> None:
101
+ """Display a table of language-specific tools (helper)"""
102
+ table = Table(show_header=True, header_style="bold cyan", title=f"{language.title()} Tools")
103
+ table.add_column("Tool", style="dim")
104
+ table.add_column("Status", justify="center")
105
+ table.add_column("Version", style="blue")
106
+
107
+ for tool, available in tools.items():
108
+ icon = "✓" if available else "✗"
109
+ color = "green" if available else "red"
110
+ version = checker.get_tool_version(tool) if available else "not installed"
111
+
112
+ table.add_row(tool, f"[{color}]{icon}[/{color}]", version or "")
113
+
114
+ console.print(table)
115
+ console.print()
116
+
117
+
118
+ def _check_specific_tool(tool: str) -> None:
119
+ """Check only a specific tool (helper)"""
120
+ checker = SystemChecker()
121
+ available = checker._is_tool_available(tool)
122
+ version = checker.get_tool_version(tool) if available else None
123
+
124
+ if available:
125
+ console.print(f"[green]✓ {tool} is installed[/green]")
126
+ if version:
127
+ console.print(f" Version: {version}")
128
+ else:
129
+ console.print(f"[red]✗ {tool} is not installed[/red]")
130
+
131
+
132
+ def _suggest_fixes(tools: dict[str, bool], language: str | None) -> None:
133
+ """Suggest installation commands for missing tools (helper)"""
134
+ missing_tools = [tool for tool, available in tools.items() if not available]
135
+
136
+ if not missing_tools:
137
+ console.print("\n[green]✓ All tools are installed[/green]")
138
+ return
139
+
140
+ console.print(f"\n[yellow]⚠ Missing {len(missing_tools)} tool(s)[/yellow]")
141
+
142
+ try:
143
+ proceed = questionary.confirm(
144
+ "Would you like to see install suggestions for missing tools?",
145
+ default=True,
146
+ ).ask()
147
+ except Exception:
148
+ proceed = True
149
+
150
+ if not proceed:
151
+ console.print("[yellow]User skipped install suggestions[/yellow]")
152
+ return
153
+
154
+ for tool in missing_tools:
155
+ install_cmd = _get_install_command(tool, language)
156
+ console.print(f" [red]✗[/red] {tool}")
157
+ if install_cmd:
158
+ console.print(f" Install: [cyan]{install_cmd}[/cyan]")
159
+
160
+
161
+ def _get_install_command(tool: str, language: str | None) -> str:
162
+ """Return the install command for a given tool (helper)"""
163
+ # Common tools
164
+ install_commands = {
165
+ "pytest": "pip install pytest",
166
+ "mypy": "pip install mypy",
167
+ "ruff": "pip install ruff",
168
+ "vitest": "npm install -D vitest",
169
+ "biome": "npm install -D @biomejs/biome",
170
+ "eslint": "npm install -D eslint",
171
+ "jest": "npm install -D jest",
172
+ }
173
+
174
+ return install_commands.get(tool, f"# Install {tool} for {language}")
175
+
176
+
177
+ def _export_diagnostics(export_path: str, data: dict) -> None:
178
+ """Export diagnostic results to a JSON file (helper)"""
179
+ try:
180
+ output = Path(export_path)
181
+ output.write_text(json.dumps(data, indent=2))
182
+ console.print(f"\n[green]✓ Diagnostics exported to {export_path}[/green]")
183
+ except Exception as e:
184
+ console.print(f"\n[red]✗ Failed to export diagnostics: {e}[/red]")