feat: 添加自启动机制,移除 --advice 参数

- 创建 bootstrap.py 承载实际 CLI 逻辑
- 重写 lyxy_document_reader.py 为轻量入口,自动检测依赖并启动
- 使用 subprocess.run() 实现跨平台兼容的自启动
- 移除 --advice 参数及相关测试
- 更新文档和规范,简化使用方式
This commit is contained in:
2026-03-11 23:49:39 +08:00
parent e67ec24dfd
commit 229f17bfee
8 changed files with 252 additions and 202 deletions

View File

@@ -1,11 +1,11 @@
## Purpose
CLI 执行建议生成功能,根据文件类型返回 uv 和 python 命令,帮助 AI 快速获取准确的执行建议,无需翻阅文档
CLI 自启动机制,自动检测文件类型、平台和依赖,用正确的 uv 命令执行脚本
## Requirements
### Requirement: 依赖配置结构
依赖配置必须同时包含 python 版本要求和依赖包列表,按文件类型和平台组织。
依赖配置必须同时包含 python 版本要求和依赖包列表,按文件类型和平台组织,供自启动逻辑内部使用
#### Scenario: 配置结构包含 python 和 dependencies
- **WHEN** 访问 `config.DEPENDENCIES`
@@ -19,17 +19,8 @@ CLI 执行建议生成功能,根据文件类型返回 uv 和 python 命令,
---
### Requirement: CLI 支持 --advice 参数
命令行工具必须支持 `-a/--advice` 参数,当指定该参数时不执行实际解析,仅输出执行建议。
#### Scenario: 用户指定 --advice 参数
- **WHEN** 用户执行 `scripts/lyxy_document_reader.py --advice <input_path>`
- **THEN** 工具输出执行建议,不解析文件内容
---
### Requirement: 轻量文件类型检测
`--advice` 参数必须复用 Reader 实例的 supports 方法识别文件类型,不打开文件。
自启动必须复用 Reader 实例的 supports 方法识别文件类型,不打开文件。
#### Scenario: 复用 Reader 实例
- **WHEN** 检测文件类型时
@@ -69,72 +60,70 @@ CLI 执行建议生成功能,根据文件类型返回 uv 和 python 命令,
#### Scenario: 不验证文件存在
- **WHEN** 输入路径指向不存在的文件
- **THEN** 仍根据 reader.supports() 返回建议,不报错
- **THEN** 仍根据 reader.supports() 识别类型,不报错
---
### Requirement: 平台检测
必须检测当前平台并返回适配的命令
必须检测当前平台并选择适配的依赖配置
#### Scenario: 检测平台格式
- **WHEN** 工具执行时
- **THEN** 返回格式为 `{system}-{machine}`,例如 `Darwin-arm64``Linux-x86_64``Windows-AMD64`
#### Scenario: macOS x86_64 PDF 特殊命令
#### Scenario: macOS x86_64 PDF 特殊配置
- **WHEN** 平台为 `Darwin-x86_64` 且文件类型为 PDF
- **THEN** 返回包含 `--python 3.12` 和特定版本依赖的命令
- **THEN** 使用包含 `--python 3.12` 和特定版本依赖的配置
---
### Requirement: 输出 uv 命令
必须输出使用 `uv run --with ...` 格式的命令
### 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** 输出格式为:`uv run [--python X.Y] --with <dep1> --with <dep2> ... scripts/lyxy_document_reader.py <input_path>`
- **WHEN** 脚本确定需要自启动
- **THEN** 根据文件类型和平台获取依赖配置
- **AND** 生成 `uv run [--python X.Y] --with <dep1> --with <dep2> ... scripts/bootstrap.py <input_path>` 命令
- **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: 输出 python 命令
必须输出直接使用 python 的命令及 pip 安装命令
### Requirement: 降级执行
当 uv 不可用时,脚本必须降级为直接导入并执行 bootstrap.py
#### Scenario: 生成 python 命令
- **WHEN** 检测到文件类型
- **THEN** 输出 python 命令:`python scripts/lyxy_document_reader.py <input_path>`
- **AND** 输出 pip 安装命令:`pip install <dep1> <dep2> ...`
---
### Requirement: 输出格式规范
输出必须包含文件类型、输入路径、平台如需要、uv 命令、python 命令和 pip 安装命令。
#### Scenario: 普通平台输出格式
- **WHEN** 平台无特殊配置
- **THEN** 输出格式为:
```
文件类型: <type>
输入路径: <input>
[uv 命令]
<uv_command>
[python 命令]
python scripts/lyxy_document_reader.py <input>
pip install <deps>
```
#### Scenario: 特殊平台输出格式
- **WHEN** 平台有特殊配置
- **THEN** 输出格式为:
```
文件类型: <type>
输入路径: <input>
平台: <system-machine>
[uv 命令]
<uv_command>
[python 命令]
python scripts/lyxy_document_reader.py <input>
pip install <deps>
```
#### Scenario: uv 不可用时降级
- **WHEN** uv 不在 PATH 中
- **THEN** 脚本直接导入 bootstrap 模块
- **AND** 调用 bootstrap.run_normal() 执行
- **AND** 如果缺少依赖,输出正常的 `ModuleNotFoundError`