## Context 当前lyxy-runner-python skill要求用户在Python脚本顶部添加PEP 723元数据块来声明依赖,这需要修改用户现有的脚本文件,降低了使用便利性。此外,现有实现总是使用临时文件,即使在用户明确指定路径时也是如此。 该skill目前的工作流程: 1. 要求LLM生成包含PEP 723元数据的Python脚本 2. 使用辅助脚本创建临时文件 3. 写入脚本内容(包含元数据块) 4. 使用`uv run `执行 现有实现的限制: - 用户必须修改现有脚本以添加PEP 723元数据 - 总是使用临时文件,即使用户指定了存储路径 - 无法智能识别uv项目,每次都创建新的虚拟环境 ## Goals / Non-Goals **Goals:** - 无需修改用户现有Python脚本即可使用uv执行 - 自动解析脚本依赖并使用`--with`语法传递 - 智能检测uv项目,复用项目虚拟环境 - 尊重用户指定的脚本路径,仅在未指定时使用临时文件 - 保持跨平台兼容性(Windows/macOS/Linux) - 保持严格错误处理和调试支持 **Non-Goals:** - 不修改用户现有的脚本文件 - 不实现复杂版本约束或依赖冲突解决(交给uv) - 不支持命令行参数或stdin输入(保持现有限制) - 不持久化虚拟环境(每次执行都是新的) ## Decisions ### 决策1:项目检测方法 **选择:** 使用`uv sync --dry-run`命令检测当前目录是否为uv项目 **原因:** - `uv sync --dry-run`是uv提供的官方方法,能准确判断目录是否为有效的uv项目 - 不仅检查pyproject.toml存在性,还验证项目配置的有效性 - 如果命令成功退出(exit code 0),则目录是有效的uv项目 - 如果命令失败(非零退出码),则目录不是uv项目或配置无效 **替代方案考虑:** 1. 仅检查pyproject.toml文件存在 - 优点:简单快速 - 缺点:无法验证文件有效性,可能误判 - **拒绝理由**:不够可靠,可能导致误判 2. 检查.venv目录存在 - 优点:可以检测已初始化的虚拟环境 - 缺点:uv项目可能尚未运行过sync,没有.venv目录 - **拒绝理由**:对未初始化的uv项目不友好 **实现细节:** ```bash # 检测当前目录是否为uv项目 if uv sync --dry-run > /dev/null 2>&1; then # 是uv项目,使用项目环境 uv run else # 不是uv项目,使用--with语法 uv run --with package1 --with package2 fi ``` ### 决策2:依赖解析策略 **选择:** 使用大模型的分析能力直接从脚本内容提取import语句,而非使用外部工具 **原因:** - 大模型已经理解脚本内容,可以直接提取import语句 - 避免引入新的依赖(如ast模块解析工具) - 大模型可以理解各种import语法变体(import x, from x import y, import x as z等) - 可以排除Python标准库模块,只需检查是否为常见标准库名称 **实现细节:** 1. 大模型分析脚本中的所有import语句 2. 提取包名(import pandas → pandas, from numpy import array → numpy) 3. 排除已知的标准库名称(os, sys, json, pathlib, re等) 4. 去重后生成依赖列表 **限制:** - 大模型需要维护标准库列表(可基于Python 3.10+标准库) - 对于动态导入(__import__)和条件导入,可能无法识别 - 不支持解析requirements.txt或其他依赖文件(只解析脚本内容) ### 决策3:路径处理策略 **选择:** 三层路径处理逻辑(用户指定 → 现有脚本 → 临时文件) **原因:** - 优先尊重用户明确指定的路径 - 对现有脚本直接执行,无需修改 - 仅在大模型自主生成且未指定路径时使用临时文件 **决策树:** ``` 用户是否指定脚本存储路径? ├─ 是:写入用户指定路径 → 执行 └─ 否: ├─ 用户是否指定现有脚本路径? │ ├─ 是:直接执行该脚本 │ └─ 否:创建临时文件 → 执行 ``` **实现细节:** - 用户指定路径示例:"在scripts/data.py中写入" → 写入`scripts/data.py` - 用户指定现有脚本:"运行analyze.py" → 执行`analyze.py`(读取内容解析依赖) - 大模型自主生成:使用`get_temp_path.py`辅助脚本创建临时文件 ### 决策4:执行命令构造 **选择:** 根据项目检测和依赖解析结果动态构造`uv run`命令 **命令模式:** | 场景 | 命令格式 | |------|----------| | uv项目内脚本 | `uv run ` | | 非uv项目,有依赖 | `uv run --with pkg1 --with pkg2 ` | | 非uv项目,无依赖 | `uv run ` | **原因:** - uv项目:依赖已在pyproject.toml中管理,不需要`--with` - 非uv项目:使用`--with`逐个指定依赖,uv自动处理隔离环境 - 无依赖:不需要`--with`,使用标准库环境 ### 决策5:不使用辅助脚本进行项目检测 **选择:** 直接使用大模型的命令行工具执行`uv sync --dry-run`进行项目检测 **原因:** - 大模型可以直接执行bash命令,无需额外的辅助脚本 - 简化实现,减少维护成本 - 避免辅助脚本的版本管理问题 **实现细节:** ```bash # 使用大模型的命令行工具执行项目检测 uv sync --dry-run ``` - 如果命令返回exit code 0,则当前目录是有效的uv项目 - 如果命令返回非零退出码,则当前目录不是uv项目 - 检测结果直接由大模型判断,无需解析辅助脚本输出 ## Risks / Trade-offs ### 风险1:uv项目检测失败 **描述:** `uv sync --dry-run`在某些情况下可能误判(如网络问题、依赖解析错误) **缓解措施:** - 检测失败时回退到非uv项目模式(使用`--with`语法) - 记录检测失败日志,但不阻塞脚本执行 - 用户可以手动指定使用项目环境(通过注释或显式指令) ### 风险2:依赖解析不完整 **描述:** 大模型可能遗漏某些import语句或误判标准库模块 **缓解措施:** - 在SKILL.md中提供常见标准库列表供参考 - 当脚本执行失败时,检查是否为缺失依赖,提示用户 - 允许用户手动指定依赖(通过参数或注释) ### 风险3:路径冲突和权限问题 **描述:** 用户指定的路径可能不存在、无写入权限或与现有文件冲突 **缓解措施:** - 写入前检查目录是否存在,不存在则创建(如果允许) - 写入前检查文件权限,失败时提示用户 - 支持覆盖提示(如果文件已存在) ### 风险4:跨平台路径处理复杂 **描述:** Windows和Unix系统的路径分隔符、路径长度限制不同 **缓解措施:** - 使用Python的`pathlib`或`os.path`处理路径,而非字符串拼接 - 保持辅助脚本使用标准库路径处理函数 - 测试覆盖Windows、macOS、Linux三个平台 ### 权衡1:自动依赖解析 vs 用户显式声明 **当前选择:** 自动解析import语句 **权衡:** - 优点:用户无需手动声明依赖,开箱即用 - 缺点:可能遗漏某些隐式依赖(如动态导入) **缓解:** 支持用户通过参数或注释显式指定依赖 ### 权衡2:项目检测成本 vs 准确性 **当前选择:** 使用`uv sync --dry-run`(准确但较慢) **权衡:** - 优点:准确判断uv项目,避免误判 - 缺点:每次执行都需要运行检测命令(约几百毫秒) **缓解:** 可以考虑缓存检测结果(在同一工作目录内) ## Migration Plan ### 步骤1:更新SKILL.md文档 1. 移除PEP 723相关内容 2. 添加依赖解析指导 3. 添加项目检测流程 4. 更新路径处理说明 5. 更新执行命令示例 6. 保持错误处理和调试支持部分 ### 步骤2:更新工作流示例 在SKILL.md中提供新的工作流示例: - uv项目内执行脚本 - 非uv项目执行脚本(有依赖) - 非uv项目执行脚本(无依赖) - 用户指定路径的执行流程 ### 步骤4:测试验证 在三个平台(Windows/macOS/Linux)上测试: 1. uv项目检测 2. 依赖解析准确性 3. 路径处理(临时/指定/现有) 4. 跨平台兼容性 5. 错误处理 ### 回滚策略 如果新实现存在问题,可以直接回退到旧版SKILL.md内容(从git历史恢复)。 ## Open Questions 1. **依赖解析准确性:** 是否需要维护一个更完整的Python标准库模块列表,以减少误判? - 建议:基于Python 3.10+标准库文档维护列表 2. **项目检测缓存:** 是否需要在同一工作目录内缓存项目检测结果,避免重复运行`uv sync --dry-run`? - 建议:初期不实现,观察性能影响后再决定 3. **隐式依赖处理:** 如何处理通过`__import__()`或动态加载的隐式依赖? - 建议:暂不支持,在SKILL.md中说明限制 4. **用户干预机制:** 是否提供机制让用户在脚本中显式声明额外依赖(如通过特殊注释)? - 建议:初期不实现,通过错误提示引导用户 5. **Windows路径长度限制:** Windows路径最大260字符限制如何处理? - 建议:使用长路径前缀(\\?\)或尽量使用相对路径