## Purpose CLI 自启动机制,自动检测文件类型、平台和依赖,用正确的 uv 命令执行脚本。 ## Requirements ### Requirement: 依赖配置结构 依赖配置必须同时包含 python 版本要求和依赖包列表,按文件类型和平台组织,供自启动逻辑内部使用。 #### Scenario: 配置结构包含 python 和 dependencies - **WHEN** 访问 `config.DEPENDENCIES` 时 - **THEN** 每个文件类型配置包含多个平台配置 - **AND** 每个平台配置包含 `python` 字段(可为 None)和 `dependencies` 列表字段 #### Scenario: default 平台配置 - **WHEN** 平台无特殊配置时 - **THEN** 使用 `default` 配置 - **AND** `python` 为 `None` 表示不需要指定 `--python` 参数 --- ### Requirement: 轻量文件类型检测 自启动必须复用 Reader 实例的 supports 方法识别文件类型,不打开文件。 #### Scenario: 复用 Reader 实例 - **WHEN** 检测文件类型时 - **THEN** 使用已实例化的 readers 列表 - **AND** 调用每个 reader 的 supports() 方法 - **AND** 根据第一个支持的 reader 类名识别文件类型 #### Scenario: 检测 PDF 文件 - **WHEN** 输入路径以 `.pdf` 结尾(不区分大小写) - **THEN** PdfReader.supports() 返回 True - **AND** 识别为 PDF 类型 #### Scenario: 检测 DOCX 文件 - **WHEN** 输入路径以 `.docx` 结尾(不区分大小写) - **THEN** DocxReader.supports() 返回 True - **AND** 识别为 DOCX 类型 #### Scenario: 检测 XLSX 文件 - **WHEN** 输入路径以 `.xlsx` 结尾(不区分大小写) - **THEN** XlsxReader.supports() 返回 True - **AND** 识别为 XLSX 类型 #### Scenario: 检测 PPTX 文件 - **WHEN** 输入路径以 `.pptx` 结尾(不区分大小写) - **THEN** PptxReader.supports() 返回 True - **AND** 识别为 PPTX 类型 #### Scenario: 检测 HTML 文件 - **WHEN** 输入路径以 `.html` 或 `.htm` 结尾(不区分大小写) - **THEN** HtmlReader.supports() 返回 True - **AND** 识别为 HTML 类型 #### Scenario: 检测 URL - **WHEN** 输入路径以 `http://` 或 `https://` 开头 - **THEN** HtmlReader.supports() 返回 True - **AND** 识别为 HTML 类型 #### Scenario: 不验证文件存在 - **WHEN** 输入路径指向不存在的文件 - **THEN** 仍根据 reader.supports() 识别类型,不报错 --- ### Requirement: 平台检测 必须检测当前平台并选择适配的依赖配置。 #### Scenario: 检测平台格式 - **WHEN** 工具执行时 - **THEN** 返回格式为 `{system}-{machine}`,例如 `Darwin-arm64`、`Linux-x86_64`、`Windows-AMD64` #### Scenario: macOS x86_64 PDF 特殊配置 - **WHEN** 平台为 `Darwin-x86_64` 且文件类型为 PDF - **THEN** 使用包含 `--python 3.12` 和特定版本依赖的配置 --- ### Requirement: 自启动检测 脚本必须自动检测文件类型、当前平台和 uv 可用性,如 uv 可用则用正确的 uv 命令启动 bootstrap.py。 #### Scenario: 检测文件类型 - **WHEN** 脚本启动时 - **THEN** 复用 Reader 的 supports() 方法识别文件类型 - **AND** 不打开文件,仅做轻量检测 #### Scenario: 检测平台 - **WHEN** 脚本启动时 - **THEN** 检测当前平台,格式为 `{system}-{machine}` - **AND** 根据平台选择正确的依赖配置 #### Scenario: 检测 uv 是否可用 - **WHEN** 准备自启动前 - **THEN** 使用 `shutil.which("uv")` 检测 uv 是否在 PATH 中 - **AND** 如果 uv 不可用,降级为直接执行 bootstrap.py --- ### Requirement: 自启动执行 脚本必须使用 `subprocess.run()` 启动子进程,用正确的 uv 命令启动 bootstrap.py。 #### Scenario: 生成 uv 命令 - **WHEN** 脚本确定需要自启动 - **THEN** 根据文件类型和平台获取依赖配置 - **AND** 生成 `uv run [--python X.Y] --with --with ... scripts/bootstrap.py ` 命令 - **AND** 目标脚本是 bootstrap.py,不是 lyxy_document_reader.py #### Scenario: 自启动设置环境变量 - **WHEN** 执行 `subprocess.run()` 自启动 - **THEN** 必须设置 `PYTHONPATH=.` - **AND** 不需要设置 `LYXY_IN_UV`(自启动直接调用 bootstrap.py) - **AND** 必须传递退出码给父进程 #### Scenario: 静默自启动 - **WHEN** 脚本执行自启动 - **THEN** 不输出任何额外提示信息 - **AND** 不干扰正常的 Markdown 输出 --- ### Requirement: 降级执行 当 uv 不可用时,脚本必须降级为直接导入并执行 bootstrap.py。 #### Scenario: uv 不可用时降级 - **WHEN** uv 不在 PATH 中 - **THEN** 脚本直接导入 bootstrap 模块 - **AND** 调用 bootstrap.run_normal() 执行 - **AND** 如果缺少依赖,输出正常的 `ModuleNotFoundError`