config.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import configparser
  2. from pathlib import Path
  3. import asyncclick as click
  4. from rich.box import ROUNDED
  5. from rich.console import Console
  6. from rich.table import Table
  7. console = Console()
  8. def get_config_dir():
  9. """Create and return the config directory path."""
  10. config_dir = Path.home() / ".r2r"
  11. config_dir.mkdir(exist_ok=True)
  12. return config_dir
  13. def get_config_file():
  14. """Get the config file path."""
  15. return get_config_dir() / "config.ini"
  16. class Config:
  17. _instance = None
  18. _config = configparser.ConfigParser()
  19. _config_file = get_config_file()
  20. @classmethod
  21. def load(cls):
  22. """Load the configuration file."""
  23. if cls._config_file.exists():
  24. cls._config.read(cls._config_file)
  25. @classmethod
  26. def save(cls):
  27. """Save the configuration to file."""
  28. with open(cls._config_file, "w") as f:
  29. cls._config.write(f)
  30. @classmethod
  31. def get_credentials(cls, service):
  32. """Get credentials for a specific service."""
  33. cls.load() # Ensure we have latest config
  34. return dict(cls._config[service]) if service in cls._config else {}
  35. @classmethod
  36. def set_credentials(cls, service, credentials):
  37. """Set credentials for a specific service."""
  38. cls.load() # Ensure we have latest config
  39. if service not in cls._config:
  40. cls._config[service] = {}
  41. cls._config[service].update(credentials)
  42. cls.save()
  43. @click.group()
  44. def configure():
  45. """Configuration management commands."""
  46. pass
  47. @configure.command()
  48. @click.confirmation_option(
  49. prompt="Are you sure you want to reset all settings?"
  50. )
  51. async def reset():
  52. """Reset all configuration to defaults."""
  53. if Config._config_file.exists():
  54. Config._config_file.unlink() # Delete the config file
  55. Config._config = configparser.ConfigParser() # Reset the config in memory
  56. # Set default values
  57. Config.set_credentials(
  58. "Base URL", {"base_url": "https://api.cloud.sciphi.ai"}
  59. )
  60. console.print(
  61. "[green]Successfully reset configuration to defaults[/green]"
  62. )
  63. @configure.command()
  64. @click.option(
  65. "--api-key",
  66. prompt="SciPhi API Key",
  67. hide_input=True,
  68. help="API key for SciPhi cloud",
  69. )
  70. async def key(api_key):
  71. """Configure SciPhi cloud API credentials."""
  72. Config.set_credentials("SciPhi", {"api_key": api_key})
  73. console.print(
  74. "[green]Successfully configured SciPhi cloud credentials[/green]"
  75. )
  76. @configure.command()
  77. @click.option(
  78. "--base-url",
  79. prompt="R2R Base URL",
  80. default="https://api.cloud.sciphi.ai",
  81. hide_input=False,
  82. help="Host URL for R2R",
  83. )
  84. async def host(host):
  85. """Configure R2R host URL."""
  86. Config.set_credentials("Host", {"R2R_HOST": host})
  87. console.print("[green]Successfully configured R2R host URL[/green]")
  88. @configure.command()
  89. async def view():
  90. """View current configuration."""
  91. Config.load()
  92. table = Table(
  93. title="[bold blue]R2R Settings[/bold blue]",
  94. show_header=True,
  95. header_style="bold white on blue",
  96. border_style="blue",
  97. box=ROUNDED,
  98. pad_edge=False,
  99. collapse_padding=True,
  100. )
  101. table.add_column(
  102. "Section", justify="left", style="bright_yellow", no_wrap=True
  103. )
  104. table.add_column(
  105. "Key", justify="left", style="bright_magenta", no_wrap=True
  106. )
  107. table.add_column(
  108. "Value", justify="left", style="bright_green", no_wrap=True
  109. )
  110. # Group related configurations together
  111. config_groups = {
  112. "API Credentials": ["SciPhi"],
  113. "Server Settings": ["Base URL", "Port"],
  114. }
  115. for group_name, sections in config_groups.items():
  116. has_items = any(section in Config._config for section in sections)
  117. if has_items:
  118. table.add_row(
  119. f"[bold]{group_name}[/bold]", "", "", style="bright_blue"
  120. )
  121. for section in sections:
  122. if section in Config._config:
  123. for key, value in Config._config[section].items():
  124. # Mask API keys for security
  125. displayed_value = (
  126. f"****{value[-4:]}"
  127. if "api_key" in key.lower()
  128. else value
  129. )
  130. table.add_row(
  131. f" {section}", key.lower(), displayed_value
  132. )
  133. console.print("\n")
  134. console.print(table)
  135. console.print("\n")