diff --git a/openspec/changes/archive/2026-02-04-uv-python-runner/proposal.md b/openspec/changes/archive/2026-02-04-uv-python-runner/proposal.md index 59cd821..29e6006 100644 --- a/openspec/changes/archive/2026-02-04-uv-python-runner/proposal.md +++ b/openspec/changes/archive/2026-02-04-uv-python-runner/proposal.md @@ -9,7 +9,9 @@ ## What Changes -- 创建新的skill:`uv-python-runner` +**注:** 实现时将技能名称从 `uv-python-runner` 简化为 `python-runner`,以保持命名更通用和简洁,避免与未来可能的其他 Python runner 实现名称冲突。 + +- 创建新的skill:`python-runner` (proposal中为 `uv-python-runner`) - 指导大模型按照PEP 723规范编写Python脚本 - 提供临时文件创建和uv run执行的标准流程 - 严格错误处理模式 diff --git a/openspec/specs/uv-python-runner/spec.md b/openspec/specs/uv-python-runner/spec.md new file mode 100644 index 0000000..e01b41c --- /dev/null +++ b/openspec/specs/uv-python-runner/spec.md @@ -0,0 +1,125 @@ +# UV Python Runner Spec + +## Purpose + +Define requirements for the uv-python-runner skill, which enables execution of Python scripts with PEP 723 metadata using uv for isolated dependency management and cross-platform temporary file handling. + +## Requirements + +### 需求:生成符合PEP 723规范的Python脚本 + +Skill SHALL指导LLM生成符合PEP 723内联元数据规范的Python脚本。脚本SHALL在顶部包含`# /// script`块,使用`dependencies`字段声明所有外部依赖。依赖SHALL使用不带版本约束的包名,允许uv选择兼容的最新版本。没有依赖的脚本SHALL声明空的依赖列表。 + +#### 场景:包含外部依赖的脚本 +- **WHEN** LLM需要执行需要外部包的Python代码(例如:pandas、requests、numpy) +- **THEN** skill SHALL指导LLM包含列出所有必需包的PEP 723元数据块 +- **THEN** 依赖列表SHALL只包含包名,不带版本约束 +- **THEN** 脚本SHALL是有效的Python代码,顶部包含元数据块 + +#### 场景:仅使用标准库的脚本 +- **WHEN** LLM需要执行只使用标准库模块的Python代码 +- **THEN** skill SHALL指导LLM包含空依赖的PEP 723元数据块:`# dependencies = []` +- **THEN** 脚本SHALL是有效的Python代码,顶部包含元数据块 + +### 需求:在隔离的uv环境中执行脚本 + +Skill SHALL指导LLM在系统临时目录中创建临时Python文件,并使用`uv run`命令执行它们。临时文件SHALL使用包含时间戳和随机标识符的唯一名称创建。Skill SHALL确保所有脚本参数和逻辑都嵌入在脚本本身中,没有命令行参数或stdin输入。 + +#### 场景:成功执行脚本 +- **WHEN** LLM生成符合PEP 723的有效Python脚本 +- **THEN** skill SHALL指导LLM在`/tmp/uv_script__.py`创建临时文件 +- **THEN** skill SHALL指导LLM使用`uv run /tmp/uv_script_XXX.py`执行脚本 +- **THEN** uv SHALL自动创建隔离的虚拟环境,安装依赖,并执行脚本 +- **THEN** skill SHALL捕获并返回stdout/stderr输出 +- **THEN** 临时文件使用系统目录,系统自动清理 + +#### 场景:脚本执行失败 +- **WHEN** 脚本执行失败(运行时错误、依赖解析失败等) +- **THEN** skill SHALL保留临时文件用于调试 +- **THEN** skill SHALL显示包含traceback的完整错误消息 +- **THEN** skill SHALL显示保留的临时文件路径 +- **THEN** skill SHALL停止任务(严格错误处理模式) + +### 需求:跨平台临时目录支持 + +Skill SHALL使用`skills/uv-python-runner/script/get_temp_path.py`辅助脚本来获取平台特定的临时目录。Skill SHALL在创建临时Python文件之前,先调用此辅助脚本获取临时目录路径。Skill SHALL支持Windows、macOS、Linux三个平台。 + +#### 场景:获取临时目录路径 +- **WHEN** LLM需要为Python脚本创建临时文件 +- **THEN** skill SHALL指导LLM先调用辅助脚本获取临时目录 +- **THEN** skill SHALL指导LLM导入并使用`get_temp_dir()`函数 +- **THEN** skill SHALL指导LLM使用`get_temp_file_path()`函数生成唯一文件路径(可选) +- **THEN** 辅助脚本SHALL使用`tempfile.gettempdir()`自动返回平台特定的路径 + +#### 场景:Windows平台 +- **WHEN** 辅助脚本在Windows平台运行 +- **THEN** skill SHALL指导LLM调用辅助脚本会返回Windows临时目录(例如:`C:\Users\\AppData\Local\Temp`) +- **THEN** skill SHALL确保大模型不需要检测或硬编码Windows路径 + +#### 场景:macOS/Linux平台 +- **WHEN** 辅助脚本在macOS或Linux平台运行 +- **THEN** skill SHALL指导LLM调用辅助脚本会返回`/tmp`路径 +- **THEN** skill SHALL确保大模型不需要检测或硬编码Unix路径 + +### 需求:严格错误处理 + +Skill SHALL强制执行严格错误处理模式。任何错误条件SHALL导致任务停止并显示清晰错误消息。错误条件SHALL包括:uv未安装、生成的脚本中的Python语法错误、uv的依赖解析失败、以及脚本运行时错误。 + +#### 场景:uv未安装 +- **WHEN** LLM尝试执行脚本但系统中未找到uv命令 +- **THEN** skill SHALL显示清晰错误消息:"uv not found" +- **THEN** skill SHALL提供uv安装链接:https://docs.astral.sh/uv/getting-started/installation/ +- **THEN** skill SHALL停止任务 + +#### 场景:Python语法错误 +- **WHEN** LLM生成包含语法错误的Python代码 +- **THEN** skill SHALL在创建临时文件之前检测语法错误 +- **THEN** skill SHALL显示包含行号和Python错误描述的错误消息 +- **THEN** skill SHALL停止任务而不创建临时文件 + +#### 场景:依赖解析失败 +- **WHEN** uv无法解析或安装声明的依赖 +- **THEN** skill SHALL显示完整的uv错误输出 +- **THEN** skill SHALL显示临时文件路径,用户可手动删除调试 +- **THEN** skill SHALL停止任务 + +#### 场景:脚本运行时错误 +- **WHEN** Python脚本执行但在运行时抛出异常 +- **THEN** skill SHALL显示完整的Python traceback +- **THEN** skill SHALL显示临时文件路径,用户可手动删除调试 +- **THEN** skill SHALL停止任务 + +### 需求:无外部输入或参数 + +Skill SHALL要求所有输入、参数和数据源都直接嵌入在Python脚本中。Skill SHALL不支持传递给脚本的命令行参数。Skill SHALL不支持从stdin读取输入。所有必要的数据SHALL硬编码或从脚本引用的文件中读取。 + +#### 场景:数据处理任务 +- **WHEN** LLM需要处理数据(例如:CSV文件分析) +- **THEN** skill SHALL指导LLM将文件路径作为字符串字面量包含在脚本中 +- **THEN** skill SHALL不接受文件路径或参数的外部命令行参数 +- **THEN** 所有数据处理逻辑SHALL嵌入在脚本中 + +#### 场景:API交互任务 +- **WHEN** LLM需要与API交互(例如:对特定URL的GET请求) +- **THEN** skill SHALL指导LLM将URL和参数作为字符串字面量包含在脚本中 +- **THEN** skill SHALL不接受作为命令行参数的API端点或身份验证令牌 +- **THEN** 所有API交互逻辑SHALL嵌入在脚本中 + +### 需求:通用任务适用性 + +Skill SHALL适用于任何可以用Python脚本完成的任务。Skill SHALL不限于特定领域,但SHALL为常见用例提供指导,包括数据处理(pandas、numpy)、API交互(requests、httpx)、文件操作(pathlib、shutil)、科学计算(scipy、sympy)和数据转换(json、yaml、csv)。 + +#### 场景:数据分析任务 +- **WHEN** 用户请求数据分析或统计计算 +- **THEN** skill SHALL提供生成具有适当依赖(例如:pandas)的脚本的指导 +- **THEN** skill SHALL不基于任务领域进行限制或过滤 + +#### 场景:文件操作任务 +- **WHEN** 用户请求文件操作(重命名、转换、格式化) +- **THEN** skill SHALL提供生成具有适当标准库或外部模块的脚本的指导 +- **THEN** skill SHALL不基于任务领域进行限制或过滤 + +#### 场景:API测试任务 +- **WHEN** 用户请求API测试或数据检索 +- **THEN** skill SHALL提供生成具有适当HTTP客户端库的脚本的指导 +- **THEN** skill SHALL不基于任务领域进行限制或过滤 diff --git a/skills/python-runner/SKILL.md b/skills/python-runner/SKILL.md index f75e3db..2d00a73 100644 --- a/skills/python-runner/SKILL.md +++ b/skills/python-runner/SKILL.md @@ -352,7 +352,7 @@ for i, file in enumerate(glob.glob('*.txt')): ```bash # 1. 获取临时脚本文件路径 -temp_file_path=$(uv run skills/uv-python-runner/script/get_temp_path.py) +temp_file_path=$(uv run ./script/get_temp_path.py) # 2. 写入PEP 723脚本内容 # 使用大模型的Write工具在 temp_file_path 中写入...