Coverage for  / home / runner / work / bijux-cli / bijux-cli / src / bijux_cli / cli / commands / __init__.py: 100%

49 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-01-26 17:59 +0000

1# SPDX-License-Identifier: Apache-2.0 

2# Copyright © 2025 Bijan Mousavi 

3 

4"""Constructs the command structure for the Bijux CLI application.""" 

5 

6from __future__ import annotations 

7 

8import logging 

9 

10from typer import Typer 

11 

12from bijux_cli.cli.commands.config import config_app 

13from bijux_cli.cli.commands.dev import dev_app 

14from bijux_cli.cli.commands.diagnostics.audit import audit_app 

15from bijux_cli.cli.commands.diagnostics.docs_command import docs_app 

16from bijux_cli.cli.commands.diagnostics.doctor import doctor_app 

17from bijux_cli.cli.commands.help_command import help_app 

18from bijux_cli.cli.commands.history import history_app 

19from bijux_cli.cli.commands.memory import memory_app 

20from bijux_cli.cli.commands.repl import repl_app 

21from bijux_cli.cli.commands.sleep import sleep_app 

22from bijux_cli.cli.commands.status import status_app 

23from bijux_cli.cli.commands.version import version_app 

24from bijux_cli.cli.plugins.commands import plugins_app 

25 

26logger = logging.getLogger(__name__) 

27 

28_CORE_COMMANDS = { 

29 "audit": audit_app, 

30 "config": config_app, 

31 "dev": dev_app, 

32 "docs": docs_app, 

33 "doctor": doctor_app, 

34 "help": help_app, 

35 "history": history_app, 

36 "memory": memory_app, 

37 "plugins": plugins_app, 

38 "repl": repl_app, 

39 "status": status_app, 

40 "version": version_app, 

41 "sleep": sleep_app, 

42} 

43_REGISTERED_COMMANDS: set[str] = set(_CORE_COMMANDS.keys()) 

44 

45 

46def register_commands(app: Typer) -> list[str]: 

47 """Registers all core, built-in commands with the main Typer application.""" 

48 _REGISTERED_COMMANDS.clear() 

49 _REGISTERED_COMMANDS.update(_CORE_COMMANDS.keys()) 

50 for name, cmd in sorted(_CORE_COMMANDS.items()): 

51 app.add_typer(cmd, name=name, invoke_without_command=True) 

52 _REGISTERED_COMMANDS.add(name) 

53 return sorted(_CORE_COMMANDS.keys()) 

54 

55 

56def register_dynamic_plugins(app: Typer) -> None: 

57 """Discovers and registers all third-party plugins.""" 

58 import inspect 

59 

60 from bijux_cli.plugins.loader import activate_plugin 

61 from bijux_cli.plugins.metadata import discover_plugins 

62 

63 try: 

64 if "strict" in inspect.signature(discover_plugins).parameters: 

65 plugins = discover_plugins(strict=False) 

66 else: 

67 plugins = discover_plugins() 

68 except Exception as exc: 

69 logger.warning("Plugin discovery failed: %s", exc) 

70 return 

71 

72 for meta in plugins: 

73 if meta.name in _REGISTERED_COMMANDS: 

74 raise RuntimeError(f"Plugin name collision: {meta.name!r}") 

75 try: 

76 app.add_typer(activate_plugin(meta), name=meta.name) 

77 except Exception as exc: 

78 logger.warning("Plugin %s failed to register: %s", meta.name, exc) 

79 continue 

80 _REGISTERED_COMMANDS.add(meta.name) 

81 

82 

83def list_registered_command_names() -> list[str]: 

84 """Returns a list of all registered command names.""" 

85 return sorted(_REGISTERED_COMMANDS) 

86 

87 

88__all__ = [ 

89 "register_commands", 

90 "register_dynamic_plugins", 

91 "list_registered_command_names", 

92]