""" 此文件为命令行入口。 避免在此文件中引用 router 和 service 模块内的代码。 """ import os from typing import Annotated import typer from rich.table import Table from nyahome import __version__ from nyahome.cli.cli import console from nyahome.cli.cli_aii import aii_app from nyahome.cli.cli_config import config_app from nyahome.cli.cli_env import ENV_PATH, env_app app = typer.Typer( name="NyaHome", help="🌸 为你而存在的故事之家 ~", rich_markup_mode="rich", no_args_is_help=True, ) def version_callback(value: bool = False) -> None: if value: console.print(f"[green]NyaHome[/green] version {__version__}") @app.callback(invoke_without_command=True) def main( version: bool = typer.Option( False, "--version", "-v", help="显示版本号并退出,没有其他命令会被执行。", callback=version_callback, is_eager=True, ), ) -> None: console.print("(!) [bright_black]NyaHome 仍然处于极早期的阶段。如果遇到任何问题,请告诉芒果帆帆喵![/bright_black]") @app.command() def run() -> None: """ 运行 NyaHome。 """ import os import uvicorn from dotenv import load_dotenv load_dotenv(ENV_PATH) uvicorn.run( "nyahome.server:app", reload=os.getenv("NYAHOME_UVICORN_RELOAD", "false") in ["True", "true", "1"], host=os.getenv("NYAHOME_UVICORN_HOST", "0.0.0.0"), port=int(os.getenv("NYAHOME_UVICORN_PORT", "9000")), timeout_graceful_shutdown=2, log_config=".nyahome/logging.yaml", log_level="debug", ) @app.command() def openapi( path: Annotated[str, typer.Argument(help="导出的 json 格式 openapi.json 应该保存为……")] = "openapi.json", ) -> None: """ 根据代码导出 NyaHome 的 openapi.json 。 """ from dotenv import load_dotenv load_dotenv(ENV_PATH) from nyahome.server import save_openapi_json save_openapi_json(path) console.print(f"[cyan]已经保存 openapi.json 到 {path} 。[/cyan]") @app.command() def init() -> None: """ 交互式初始化 NyaHome。 """ from dotenv import set_key from rich.prompt import Confirm, IntPrompt, Prompt from nyahome.cli.cli import DATA_DIR, ENV_PATH, LOGGING_YAML from nyahome.cli.cli_check import LOGGING_YAML_CONTENT from nyahome.config import config_manager from nyahome.data import db_driver_available, db_type_allowlist console.print("\n准备初始化 NyaHome。") # 1.数据目录初始化 if DATA_DIR.is_dir(): console.print("\n1.数据目录 [cyan].nyahome[/cyan] 已存在,跳过创建。") else: DATA_DIR.mkdir() console.print("\n1.已创建数据目录 [cyan].nyahome[/cyan]。") # 2.日志配置文件初始化 if LOGGING_YAML.is_file(): console.print("\n2.日志配置文件 [cyan]logging.yaml[/cyan] 已存在,跳过创建。") if Confirm.ask("需要[yellow]覆盖其至默认值[/yellow]吗?", default=False): with open(LOGGING_YAML, "w") as f: f.write(LOGGING_YAML_CONTENT) console.print("已覆盖至默认值。") else: with open(LOGGING_YAML, "w") as f: f.write(LOGGING_YAML_CONTENT) console.print("\n2.已创建日志配置文件 [cyan]logging.yaml[/cyan]。") # 3.环境变量初始化 console.print("\n3.一些必须的环境变量需要设置。") if Confirm.ask("\n设置[yellow]数据库连接[/yellow](环境变量)?", default=True): db_type = Prompt.ask( "NYAHOME_DB_TYPE - 数据库协议", default="sqlite", choices=db_type_allowlist, console=console ) al = db_driver_available.get(db_type, []) db_driver = Prompt.ask("NYAHOME_DB_DRIVER - 数据库驱动库", default=al[0], choices=al, console=console) set_key(ENV_PATH, "NYAHOME_DB_TYPE", db_type) set_key(ENV_PATH, "NYAHOME_DB_DRIVER", db_driver) console.print("已设置数据库类型和驱动程序。") if db_type == "sqlite": console.print("采用 [cyan]sqlite[/cyan] 数据库,无需再额外配置。") else: console.print("接下来,需要继续设置数据库的连接凭证。") db_name = Prompt.ask("NYAHOME_DB_NAME - 数据库名称", default="nyahome", console=console) db_user = Prompt.ask("NYAHOME_DB_USER - 数据库用户", default="nyahome", console=console) db_password = Prompt.ask("NYAHOME_DB_PASSWORD - 密码", default="nyahome", console=console) db_host = Prompt.ask("NYAHOME_DB_HOST - 主机名", default="localhost", console=console) db_port = Prompt.ask("NYAHOME_DB_PORT - 端口", default="3006", console=console) if db_password == "nyahome": console.print("[yellow]使用了默认数据库密码。如果是生产环境,建议更换。[/yellow]") set_key(ENV_PATH, "NYAHOME_DB_NAME", db_name) set_key(ENV_PATH, "NYAHOME_DB_USER", db_user) set_key(ENV_PATH, "NYAHOME_DB_PASSWORD", db_password) set_key(ENV_PATH, "NYAHOME_DB_HOST", db_host) set_key(ENV_PATH, "NYAHOME_DB_PORT", db_port) console.print("已设置数据库连接凭证。") if Confirm.ask("\n设置 [yellow]uvicorn[/yellow] 启动配置?", default=True): un_host = Prompt.ask("NYAHOME_UVICORN_HOST - 绑定主机名", default="0.0.0.0", console=console) un_port = IntPrompt.ask("NYAHOME_UVICORN_PORT - 绑定端口", default=9000, console=console) un_reload = Confirm.ask("NYAHOME_UVICORN_RELOAD - 自动重载", default=False, console=console) if un_reload: console.print("[yellow]启用了 uvicorn reload。如果是生产环境,建议关闭。[/yellow]") set_key(ENV_PATH, "NYAHOME_UVICORN_HOST", un_host) set_key(ENV_PATH, "NYAHOME_UVICORN_PORT", str(un_port)) set_key(ENV_PATH, "NYAHOME_UVICORN_RELOAD", "true" if un_reload else "false") console.print("已设置 uvicorn 启动配置。") # 4.NyaHome 设置初始化 console.print("\n4. NyaHome 设置初始化") try: config_manager.sync_load_config() except FileNotFoundError: console.print("配置文件 [cyan].nyahome/config.json[/cyan] 不存在,创建默认配置。") config_manager.sync_save_config() else: console.print("配置文件已存在,跳过。") @app.command() def check() -> None: """ 详细自检查环境变量与设置,得到检查报告,可能有用。 """ from dotenv import load_dotenv from nyahome.cli.cli import DATA_DIR, ENV_PATH from nyahome.cli.cli_check import ( check_database_connector, check_database_type, check_nyahome_status, check_uvicorn, cw, ) def _(step: int, description: str) -> str: return f"\n[cyan]> Step {step}[/cyan]: {description}" console.print(_(1, "检查可用的数据库驱动程序")) table1 = Table(title="数据库驱动库") table1.add_column("驱动库", style="cyan") table1.add_column("状态与描述") database_connectors = check_database_connector() for key, value in database_connectors.items(): table1.add_row(key, value) console.print(table1) console.print(_(2, "检查环境变量")) load_dotenv(ENV_PATH) check_database_type(os.environ) check_uvicorn(os.environ) console.print(_(3, "检查 NyaHome 安装模式与运行环境")) check_nyahome_status() console.print(_(4, "检查 NyaHome 数据目录可用性")) if not DATA_DIR.is_dir(): cw.warning("NyaHome 数据目录 .nyahome 不存在。") else: if not (DATA_DIR / "logging.yaml").is_file(): cw.warning(".nyahome/logging.yaml 日志配置文件不存在。") if not (DATA_DIR / "contents").is_dir(): cw.warning(".nyahome/contents 上传目录不存在。") cw.info("可以运行 [cyan]nyahome init[/cyan] 命令来重新初始化数据目录。") console.print(f"\n[yellow]完成自检,共有 {cw.counter} 个警告。[/yellow]") app.add_typer(config_app, name="config", no_args_is_help=True, help="设置 NyaHome 的设置。(需要初始化)") app.add_typer(env_app, name="env", no_args_is_help=True, help="设置 NyaHome 应用的环境变量。(需要初始化)") app.add_typer(aii_app, name="aii", no_args_is_help=True, help="添加、设置、修改 AI 提供商和模型。(需要初始化)") if __name__ == "__main__": app()