From 9e42c2ccd901ee35556045bd81b4ee17bd037c2e Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Thu, 5 Feb 2026 11:25:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0js-runner=E7=9A=84skill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-02-05-bun-js-runner/.openspec.yaml | 2 + .../2026-02-05-bun-js-runner/design.md | 143 ++++++++++ .../2026-02-05-bun-js-runner/proposal.md | 32 +++ .../specs/js-runner/spec.md | 101 +++++++ .../archive/2026-02-05-bun-js-runner/tasks.md | 51 ++++ openspec/config.yaml | 1 + openspec/specs/js-runner/spec.md | 107 +++++++ skills/js-runner/SKILL.md | 266 ++++++++++++++++++ skills/js-runner/scripts/get_temp_path.js | 14 + 9 files changed, 717 insertions(+) create mode 100644 openspec/changes/archive/2026-02-05-bun-js-runner/.openspec.yaml create mode 100644 openspec/changes/archive/2026-02-05-bun-js-runner/design.md create mode 100644 openspec/changes/archive/2026-02-05-bun-js-runner/proposal.md create mode 100644 openspec/changes/archive/2026-02-05-bun-js-runner/specs/js-runner/spec.md create mode 100644 openspec/changes/archive/2026-02-05-bun-js-runner/tasks.md create mode 100644 openspec/specs/js-runner/spec.md create mode 100644 skills/js-runner/SKILL.md create mode 100644 skills/js-runner/scripts/get_temp_path.js diff --git a/openspec/changes/archive/2026-02-05-bun-js-runner/.openspec.yaml b/openspec/changes/archive/2026-02-05-bun-js-runner/.openspec.yaml new file mode 100644 index 0000000..1c4dfdf --- /dev/null +++ b/openspec/changes/archive/2026-02-05-bun-js-runner/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-02-05 diff --git a/openspec/changes/archive/2026-02-05-bun-js-runner/design.md b/openspec/changes/archive/2026-02-05-bun-js-runner/design.md new file mode 100644 index 0000000..340f50e --- /dev/null +++ b/openspec/changes/archive/2026-02-05-bun-js-runner/design.md @@ -0,0 +1,143 @@ +## Context(背景) + +本项目在 `skills/` 目录下开发用于大模型工具的技能(skills),每个子目录代表一个技能。目前,项目已经有一个 `python-runner` 技能,它使用 `uv` 提供了隔离的 Python 执行环境,支持依赖管理和临时文件隔离。 + +`js-runner/` 目录已存在但未完成,只包含一个测试文件(`test/axios.js`)。目前项目中还没有功能完整的 JavaScript/TypeScript 执行能力。 + +**当前状态:** +- `python-runner` 技能已完整实现(基于 uv 的隔离) +- `js-runner` 目录骨架存在但缺少实现 +- 没有 JavaScript/TypeScript 的依赖管理机制 +- 没有 JS/TS 脚本的临时文件生命周期管理 + +**约束条件:** +- 必须保持环境隔离(不污染系统包) +- 应遵循 `python-runner` 建立的模式以保持一致性 +- 技能结构必须符合项目规范(`skills//`) +- 必须同时支持 JavaScript 和 TypeScript 执行 + +## Goals / Non-Goals(目标 / 非目标) + +**目标:** +- 提供辅助脚本供大模型调用(使用 JavaScript 编写,与 skill 主题一致) +- 在 SKILL.md 中清晰描述完整的调用流程 +- 利用 Bun 的自动依赖管理能力 +- 匹配 `python-runner` 的工作流程和用户体验,保持一致性 + +**非目标:** +- 提供完整的 IDE 或开发环境 +- 脚本的长期存储或持久化 +- 超越 JavaScript/TypeScript 的多语言支持 +- 替换或修改现有的 `python-runner` 技能 +- 构建自定义的 Bun 运行时包装器(直接使用 Bun) + +## Decisions(技术决策) + +### 1. 使用 Bun 作为 JavaScript 运行时 + +**理由:** Bun 相比替代方案具有显著优势: +- **Bun:** 比 Node.js 快约 100 倍的冷启动,内置包管理器(bun install),原生 TypeScript 支持,兼容 Node.js API +- **Node.js + npm/yarn:** 启动慢,需要外部包管理器,没有原生 TypeScript 支持 +- **Deno:** 不同的 API 表面(不兼容 Node.js),生态系统较小,Node.js 用户学习曲线陡峭 + +**考虑的替代方案:** +- **Node.js with npm:** 因启动速度慢且无原生 TypeScript 支持而被拒绝 +- **Deno:** 因 API 与 Node.js 生态不兼容且包管理不熟悉而被拒绝 + +### 2. 基于临时文件的执行模型 + +**理由:** 遵循 `python-runner` 的模式,在临时文件中执行脚本可以: +- 在执行之间保持干净的隔离 +- 自动清理产物 +- 不需要跨运行的状态管理 +- 比内存执行实现更简单 + +**考虑的替代方案:** +- **通过 Bun 的 `Bun.transpileString()` 进行内存执行:** 因对模块导入和外部依赖支持不好而被拒绝 +- **持久化目录结构:** 因避免执行之间的状态泄漏而被拒绝 + +### 3. 使用 Bun 的自动依赖管理 + +**理由:** Bun 可以直接运行脚本并自动处理依赖: +- **自动依赖解析:** 当脚本使用 `import` 或 `require` 引入外部包时,Bun 自动下载并缓存该包 +- **无需手动安装:** 不需要手动运行 `bun install`,Bun 在运行时自动处理 +- **智能缓存:** Bun 全局缓存已下载的包,后续运行无需重复下载 +- **简化实现:** 不需要生成临时的 `package.json`,也不需要管理 `node_modules` + +**工作流程:** +1. 用户直接运行脚本(内联或从文件) +2. 脚本中使用 `import` 或 `require` 引入依赖(如 `import axios from 'axios'`) +3. Bun 自动检测到未安装的依赖 +4. Bun 下载并缓存依赖到 Bun 的全局缓存(`~/.bun/install/cache`) +5. 执行脚本 +6. 清理临时脚本文件(Bun 的缓存保持不变) + +**考虑的替代方案:** +- **手动 package.json + bun install:** 因 Bun 已经提供自动依赖处理而被拒绝(过度设计) +- **要求用户提供 package.json:** 因增加用户负担而被拒绝 + +### 4. 用于路径管理的辅助脚本 + +**理由:** `get_temp_path.js` 辅助脚本将: +- 为脚本生成唯一的临时文件路径 +- 遵循特定于操作系统的临时目录约定 +- 使用 JavaScript 编写,与 js-runner 主题一致 +- 使用 Bun 运行(已确保环境就绪) + +**实现方式:** +```javascript +import { tmpdir } from "os"; +import { join } from "path"; + +export function getTempPath(extension) { + const timestamp = Date.now(); + const random = Math.random().toString(36).substring(7); + return join(tmpdir(), `js-runner-${timestamp}-${random}.${extension}`); +} +``` + +## Risks / Trade-offs(风险 / 权衡) + +### 风险:需要安装 Bun + +**风险:** 用户必须单独安装 Bun,这增加了设置障碍。 + +**缓解措施:** +- 在 SKILL.md 中清晰记录安装过程(`curl -fsSL https://bun.sh/install | bash`) +- 如果未找到 Bun,提供有用的错误消息 +- 考虑添加 "check" 命令来验证 Bun 安装 + +## Migration Plan(迁移计划) + +由于这是一个没有现有生产使用的新技能: + +1. **第一阶段:实现** + - 创建 `scripts/get_temp_path.js` 辅助脚本(使用 JavaScript 编写) + - 编写完整的 `SKILL.md` 文档,包含必要的 frontmatter + - 描述完整调用流程 + +2. **第二阶段:验证** + - 验证 `get_temp_path.js` 辅助脚本工作正常 + - 验证 SKILL.md 格式符合 Agent Skills 规范 + - 验证 SKILL.md 中的调用流程准确无误 + +3. **第三阶段:文档** + - 确保 SKILL.md 涵盖所有用例 + - 为常见场景提供示例 + - 记录错误处理和故障排除 + +**回滚策略:** +- 如果实现有问题,删除 `skills/js-runner/` 目录 +- 对项目其他部分无影响,因为这是一个新的隔离技能 + +## Open Questions(待解决的问题) + +1. **我们是否应该支持持久化项目目录?** + - 当前方法:只有临时文件 + - 考虑:允许用户指定工作目录 + - 决策:推迟到未来增强;首先专注于简单的脚本执行 + +2. **需要什么级别的错误报告?** + - 当前计划:按原样转发 Bun 的 stderr 输出 + - 考虑:解析并美化常见错误 + - 决策:从原始输出开始,根据用户需求增强 diff --git a/openspec/changes/archive/2026-02-05-bun-js-runner/proposal.md b/openspec/changes/archive/2026-02-05-bun-js-runner/proposal.md new file mode 100644 index 0000000..cb77b5f --- /dev/null +++ b/openspec/changes/archive/2026-02-05-bun-js-runner/proposal.md @@ -0,0 +1,32 @@ +## Why + +当前项目已有基于uv的Python执行环境(python-runner),但缺少相应的JavaScript/TypeScript执行能力。Bun作为现代JavaScript运行时,具有极快的启动速度、内置包管理器和对标准库的完整支持,非常适合创建一个类似python-runner的隔离式JS/TS执行环境,保持系统环境整洁。 + +## What Changes + +- 完善现有的`skills/js-runner/`目录(目前仅有test/axios.js文件) +- 基于Bun实现JavaScript/TypeScript脚本执行能力,使用临时文件和环境隔离 +- 参考python-runner的工作流,支持依赖管理(通过package.json或内联声明) +- 提供辅助脚本生成临时文件路径 +- 创建完整的SKILL.md文档 + +## Capabilities + +### New Capabilities +- `js-runner`: 提供基于Bun的JavaScript/TypeScript脚本执行能力,支持依赖管理、环境隔离和临时文件清理 + +### Modified Capabilities +- None + +## Impact + +**新增文件**: +- `skills/js-runner/SKILL.md` - Skill文档 +- `skills/js-runner/scripts/get_temp_path.js` - 临时路径生成辅助脚本 + +**外部依赖**: +- 需要安装Bun运行时(https://bun.sh) + +**不影响的范围**: +- 不影响现有的python-runner skill +- 不修改其他skill的实现 diff --git a/openspec/changes/archive/2026-02-05-bun-js-runner/specs/js-runner/spec.md b/openspec/changes/archive/2026-02-05-bun-js-runner/specs/js-runner/spec.md new file mode 100644 index 0000000..2d171a6 --- /dev/null +++ b/openspec/changes/archive/2026-02-05-bun-js-runner/specs/js-runner/spec.md @@ -0,0 +1,101 @@ +## ADDED Requirements + +### Requirement: 生成临时文件路径 +辅助脚本 MUST 提供为脚本生成唯一临时文件路径的功能。 + +#### Scenario: 生成 JavaScript 临时路径 +- **WHEN** 调用 `scripts/get_temp_path.js` 并传入参数 `'js'` +- **THEN** 返回操作系统的临时目录路径 +- **THEN** 路径包含时间戳和随机字符串以确保唯一性 +- **THEN** 文件扩展名为 `.js` + +#### Scenario: 生成 TypeScript 临时路径 +- **WHEN** 调用 `scripts/get_temp_path.js` 并传入参数 `'ts'` +- **THEN** 返回操作系统的临时目录路径 +- **THEN** 路径包含时间戳和随机字符串以确保唯一性 +- **THEN** 文件扩展名为 `.ts` + +### Requirement: 文档描述完整调用流程 +SKILL.md MUST 清晰描述大模型如何使用 js-runner 技能执行 JavaScript/TypeScript 脚本的完整流程。 + +#### Scenario: 执行脚本的标准流程 +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档描述以下标准流程: + 1. 执行 `bun --version` 检查环境 + 2. 调用 `scripts/get_temp_path.js` 生成临时文件路径 + 3. 将脚本内容写入临时文件 + 4. 使用 `bun ` 执行脚本 + 5. Bun 自动处理依赖和 TypeScript 转译 + 6. 临时文件由系统自动清理 + +#### Scenario: 文档中的示例代码 +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档提供完整的示例代码,展示: + - 如何检查 Bun 安装(`bun --version`) + - 如何调用辅助脚本生成临时文件路径 + - 如何执行脚本 + - 如何处理输出和错误 + +### Requirement: 错误处理和诊断 +系统 MUST 提供清晰的错误信息和诊断功能,帮助用户识别和解决问题。 + +#### Scenario: 未安装 Bun 时的错误 +- **WHEN** 系统未检测到 Bun 运行时 +- **THEN** 系统输出友好的错误消息,说明需要安装 Bun +- **THEN** 系统提供安装指令(`curl -fsSL https://bun.sh/install | bash`) +- **THEN** 退出码指示依赖缺失 + +#### Scenario: 脚本语法错误 +- **WHEN** 脚本包含语法错误 +- **THEN** Bun 输出详细的语法错误信息(包括文件名、行号、错误描述) +- **THEN** 系统将这些信息传递给用户 +- **THEN** 退出码指示语法错误 + +#### Scenario: 运行时错误 +- **WHEN** 脚本执行过程中抛出运行时错误 +- **THEN** 系统输出完整的错误堆栈跟踪 +- **THEN** 临时文件路径被正确映射以便用户调试 +- **THEN** 退出码指示运行时错误 + +### Requirement: 输出处理 +系统 MUST 正确处理脚本的 stdout 和 stderr 输出,将其传递给用户终端。 + +#### Scenario: 标准输出 +- **WHEN** 脚本使用 `console.log()` 或 `console.error()` 输出 +- **THEN** 系统将输出实时传递到用户终端的 stdout 或 stderr +- **THEN** 不修改或过滤输出内容 + +#### Scenario: 退出码传递 +- **WHEN** 脚本使用 `process.exit(n)` 显式退出 +- **THEN** 系统使用该退出码 +- **WHEN** 脚本正常完成且不调用 `process.exit()` +- **THEN** 系统使用退出码 0 + +### Requirement: 文档完整性 +系统 MUST 包含完整的 SKILL.md 文档,说明如何使用 js-runner。 + +#### Scenario: SKILL.md 包含必要的 frontmatter +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档顶部包含 YAML frontmatter +- **THEN** 包含 `name` 字段,值为 `js-runner` +- **THEN** 包含 `description` 字段,描述技能的功能和使用场景 +- **THEN** 可选包含 `compatibility` 字段,说明 Bun 依赖 + +#### Scenario: 安装说明 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档包含 Bun 的安装说明和命令 +- **THEN** 文档说明 js-runner 的依赖要求 + +#### Scenario: 使用示例 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档提供基本使用示例(执行简单脚本) +- **THEN** 文档提供使用外部依赖的示例(通过 import 直接引入,Bun 自动处理) +- **THEN** 文档提供 JavaScript 和 TypeScript 执行示例(同样流程) +- **THEN** 文档提供错误处理示例 + +#### Scenario: API 参考 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档列出所有可用命令行标志 +- **THEN** 文档说明每个标志的作用和用法 +- **THEN** 文档说明 `get_temp_path()` 辅助函数的用法 +- **THEN** 文档说明 Bun 的自动依赖管理机制 diff --git a/openspec/changes/archive/2026-02-05-bun-js-runner/tasks.md b/openspec/changes/archive/2026-02-05-bun-js-runner/tasks.md new file mode 100644 index 0000000..a364474 --- /dev/null +++ b/openspec/changes/archive/2026-02-05-bun-js-runner/tasks.md @@ -0,0 +1,51 @@ +## 1. 项目设置和目录结构 + +- [x] 1.1 验证 `skills/js-runner/` 目录结构 +- [x] 1.2 创建 `skills/js-runner/scripts/` 目录(注意是复数 scripts/) +- [x] 1.3 确认现有测试文件 `skills/js-runner/test/axios.js` 的状态 +- [x] 1.4 验证 Bun 运行时是否已安装(本地开发环境) + +## 2. 实现临时路径生成辅助脚本 + +- [x] 2.1 创建 `skills/js-runner/scripts/get_temp_path.js` 文件(使用 JavaScript) +- [x] 2.2 实现 `getTempPath(extension)` 函数 +- [x] 2.3 确保函数生成唯一路径(包含时间戳和随机字符串) +- [x] 2.4 测试辅助脚本的输出格式正确性 +- [x] 2.5 使用 `bun scripts/get_temp_path.js` 验证脚本可执行 + +## 3. 编写 SKILL.md 文档 + +- [x] 3.1 创建 `skills/js-runner/SKILL.md` 文档 +- [x] 3.2 添加必要的 YAML frontmatter: + - `name: js-runner` + - `description` 描述功能和场景 + - 可选 `compatibility` 说明 Bun 依赖 +- [x] 3.3 编写 Bun 安装说明和先决条件 +- [x] 3.4 描述完整的调用流程(供大模型使用): + - 执行 `bun --version` 检查环境 + - 调用 `scripts/get_temp_path.js` 生成临时文件路径 + - 写入脚本内容到临时文件 + - 使用 `bun ` 执行脚本 + - 输出结果到 stdout/stderr +- [x] 3.5 添加调用流程的完整示例代码 +- [x] 3.6 添加依赖管理示例(通过 import 直接引入,Bun 自动处理) +- [x] 3.7 添加 JavaScript 和 TypeScript 执行示例(同样流程) +- [x] 3.8 添加错误处理和故障排除指南 +- [x] 3.9 添加辅助函数 API 参考 +- [x] 3.10 说明不主动清理临时文件,由系统自动处理 + +## 4. 验证 SKILL.md 格式 + +- [x] 4.1 使用 `skills-ref validate ./skills/js-runner` 验证格式(如果可用) +- [x] 4.2 确认 frontmatter 符合 Agent Skills 规范 +- [x] 4.3 确认 name 字段格式正确(小写、数字、连字符) +- [x] 4.4 确认 description 字段长度在 1024 字符以内 +- [x] 4.5 确认文档内容清晰且易于理解 + +## 5. 集成和最终验证 + +- [x] 5.1 手动测试 `scripts/get_temp_path.js` 辅助脚本 +- [x] 5.2 验证 SKILL.md 格式符合规范 +- [x] 5.3 验证调用流程的可行性 +- [x] 5.4 验证与 `python-runner` 模式的一致性 +- [x] 5.5 提交所有更改到版本控制(如适用) diff --git a/openspec/config.yaml b/openspec/config.yaml index 29ac51a..0e0875e 100644 --- a/openspec/config.yaml +++ b/openspec/config.yaml @@ -4,3 +4,4 @@ context: | 忽略项目目录下的「.opencode」和「opencode」两个目录,与开发的skill无关; 这个项目是专门用于开发用于大模型工具的 skill; 所有开发的 skill 都放在「skills」目录下,每个子目录都代表一个 skill,目录名为 skill 的名称; + 开发过程中的文档使用中文,面向中文开发者进行交流; diff --git a/openspec/specs/js-runner/spec.md b/openspec/specs/js-runner/spec.md new file mode 100644 index 0000000..a6ebe97 --- /dev/null +++ b/openspec/specs/js-runner/spec.md @@ -0,0 +1,107 @@ +# JS Runner Spec + +## Purpose + +Define requirements for the js-runner skill, which enables execution of JavaScript and TypeScript scripts using Bun runtime with automatic dependency management and temporary file handling. + +## Requirements + +### Requirement: 生成临时文件路径 +辅助脚本 MUST 提供为脚本生成唯一临时文件路径的功能。 + +#### Scenario: 生成 JavaScript 临时路径 +- **WHEN** 调用 `scripts/get_temp_path.js` 并传入参数 `'js'` +- **THEN** 返回操作系统的临时目录路径 +- **THEN** 路径包含时间戳和随机字符串以确保唯一性 +- **THEN** 文件扩展名为 `.js` + +#### Scenario: 生成 TypeScript 临时路径 +- **WHEN** 调用 `scripts/get_temp_path.js` 并传入参数 `'ts'` +- **THEN** 返回操作系统的临时目录路径 +- **THEN** 路径包含时间戳和随机字符串以确保唯一性 +- **THEN** 文件扩展名为 `.ts` + +### Requirement: 文档描述完整调用流程 +SKILL.md MUST 清晰描述大模型如何使用 js-runner 技能执行 JavaScript/TypeScript 脚本的完整流程。 + +#### Scenario: 执行脚本的标准流程 +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档描述以下标准流程: + 1. 执行 `bun --version` 检查环境 + 2. 调用 `scripts/get_temp_path.js` 生成临时文件路径 + 3. 将脚本内容写入临时文件 + 4. 使用 `bun ` 执行脚本 + 5. Bun 自动处理依赖和 TypeScript 转译 + 6. 临时文件由系统自动清理 + +#### Scenario: 文档中的示例代码 +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档提供完整的示例代码,展示: + - 如何检查 Bun 安装(`bun --version`) + - 如何调用辅助脚本生成临时文件路径 + - 如何执行脚本 + - 如何处理输出和错误 + +### Requirement: 错误处理和诊断 +系统 MUST 提供清晰的错误信息和诊断功能,帮助用户识别和解决问题。 + +#### Scenario: 未安装 Bun 时的错误 +- **WHEN** 系统未检测到 Bun 运行时 +- **THEN** 系统输出友好的错误消息,说明需要安装 Bun +- **THEN** 系统提供安装指令(`curl -fsSL https://bun.sh/install | bash`) +- **THEN** 退出码指示依赖缺失 + +#### Scenario: 脚本语法错误 +- **WHEN** 脚本包含语法错误 +- **THEN** Bun 输出详细的语法错误信息(包括文件名、行号、错误描述) +- **THEN** 系统将这些信息传递给用户 +- **THEN** 退出码指示语法错误 + +#### Scenario: 运行时错误 +- **WHEN** 脚本执行过程中抛出运行时错误 +- **THEN** 系统输出完整的错误堆栈跟踪 +- **THEN** 临时文件路径被正确映射以便用户调试 +- **THEN** 退出码指示运行时错误 + +### Requirement: 输出处理 +系统 MUST 正确处理脚本的 stdout 和 stderr 输出,将其传递给用户终端。 + +#### Scenario: 标准输出 +- **WHEN** 脚本使用 `console.log()` 或 `console.error()` 输出 +- **THEN** 系统将输出实时传递到用户终端的 stdout 或 stderr +- **THEN** 不修改或过滤输出内容 + +#### Scenario: 退出码传递 +- **WHEN** 脚本使用 `process.exit(n)` 显式退出 +- **THEN** 系统使用该退出码 +- **WHEN** 脚本正常完成且不调用 `process.exit()` +- **THEN** 系统使用退出码 0 + +### Requirement: 文档完整性 +系统 MUST 包含完整的 SKILL.md 文档,说明如何使用 js-runner。 + +#### Scenario: SKILL.md 包含必要的 frontmatter +- **WHEN** 大模型阅读 SKILL.md +- **THEN** 文档顶部包含 YAML frontmatter +- **THEN** 包含 `name` 字段,值为 `js-runner` +- **THEN** 包含 `description` 字段,描述技能的功能和使用场景 +- **THEN** 可选包含 `compatibility` 字段,说明 Bun 依赖 + +#### Scenario: 安装说明 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档包含 Bun 的安装说明和命令 +- **THEN** 文档说明 js-runner 的依赖要求 + +#### Scenario: 使用示例 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档提供基本使用示例(执行简单脚本) +- **THEN** 文档提供使用外部依赖的示例(通过 import 直接引入,Bun 自动处理) +- **THEN** 文档提供 JavaScript 和 TypeScript 执行示例(同样流程) +- **THEN** 文档提供错误处理示例 + +#### Scenario: API 参考 +- **WHEN** 用户阅读 SKILL.md +- **THEN** 文档列出所有可用命令行标志 +- **THEN** 文档说明每个标志的作用和用法 +- **THEN** 文档说明 `get_temp_path()` 辅助函数的用法 +- **THEN** 文档说明 Bun 的自动依赖管理机制 diff --git a/skills/js-runner/SKILL.md b/skills/js-runner/SKILL.md new file mode 100644 index 0000000..8f40e12 --- /dev/null +++ b/skills/js-runner/SKILL.md @@ -0,0 +1,266 @@ +--- +name: js-runner +description: Any task that requires Javascript/Typescript processing should use this skill. +compatibility: Requires Bun runtime (https://bun.sh) +--- + +# js-runner + +基于 Bun 的 JavaScript/TypeScript 执行技能,提供隔离的脚本执行和自动依赖管理。 + +## 前置条件 + +### 安装 Bun + +js-runner 需要安装 Bun。Bun 是一个快速的 JavaScript 运行时,内置包管理器。 + +**macOS/Linux:** + +```bash +curl -fsSL https://bun.sh/install | bash +``` + +**Windows:** + +```powershell +powershell -c "irm bun.sh/install.ps1 | iex" +``` + +**验证安装:** + +```bash +bun --version +``` + +## 使用流程 + +执行 JavaScript/TypeScript 脚本的完整工作流程: + +1. **检查环境** - 验证 Bun 是否已安装 +2. **生成临时路径** - 调用辅助脚本获取唯一的临时文件路径 +3. **写入脚本** - 将脚本内容保存到临时文件 +4. **执行脚本** - 使用 Bun 运行脚本 +5. **捕获输出** - 从执行结果读取 stdout/stderr +6. **清理** - 临时文件由系统自动处理 + +### 完整示例 + +```bash +# 步骤 1: 检查 Bun 是否已安装 +bun --version + +# 步骤 2: 生成临时文件路径 +TEMP_FILE=$(bun skills/js-runner/scripts/get_temp_path.js js) + +# 步骤 3: 将脚本内容写入临时文件 +cat < "$TEMP_FILE" +const greeting = "Hello from js-runner!"; +console.log(greeting); +EOF + +# 步骤 4: 执行脚本 +bun "$TEMP_FILE" + +# 步骤 5: 输出已在上面捕获 +# 临时文件将由系统自动清理 +``` + +### 使用依赖 + +```bash +# 生成临时文件 +TEMP_FILE=$(bun skills/js-runner/scripts/get_temp_path.js js) + +# 写入包含外部依赖的脚本 +cat < "$TEMP_FILE" +import axios from 'axios'; + +const response = await axios.get('https://api.github.com'); +console.log('GitHub API status:', response.status); +EOF + +# 执行 - Bun 首次运行时会自动下载依赖 +bun "$TEMP_FILE" +``` + +Bun 会自动: + +- 检测 `import` 语句 +- 下载并缓存依赖(到 `~/.bun/install/cache`) +- 根据需要处理 TypeScript 编译 +- 无需 `package.json` 或手动安装 + +## JavaScript 与 TypeScript + +JavaScript 和 TypeScript 使用相同的工作流程: + +```bash +# JavaScript +TEMP_JS=$(bun skills/js-runner/scripts/get_temp_path.js js) +cat < "$TEMP_JS" +console.log('JavaScript execution'); +EOF +bun "$TEMP_JS" + +# TypeScript +TEMP_TS=$(bun skills/js-runner/scripts/get_temp_path.js ts) +cat < "$TEMP_TS" +const message: string = 'TypeScript execution'; +console.log(message); +EOF +bun "$TEMP_TS" +``` + +Bun 会自动即时转译 TypeScript。 + +## 依赖管理 + +Bun 提供自动依赖管理,无需手动配置: + +### 导入外部包 + +```javascript +// ESM import(推荐) +import axios from 'axios' +import lodash from 'lodash' + +// CommonJS import(也支持) +const axios = require('axios') +``` + +首次执行带有外部导入的脚本时,Bun 会: + +1. 分析导入 +2. 从 npm 下载缺失的依赖 +3. 全局缓存到 `~/.bun/install/cache` +4. 后续运行使用缓存版本 + +### 不需要 package.json + +与 Node.js 不同,你无需创建 `package.json` 或单独运行 `bun install`。Bun 在运行时自动处理所有操作。 + +## 辅助函数 API + +### `get_temp_path.js` + +为脚本执行生成唯一的临时文件路径。 + +**CLI 使用方式:** + +```bash +bun skills/js-runner/scripts/get_temp_path.js +``` + +**参数:** + +- `extension` (可选): 文件扩展名。默认为 `js`。常用值: `js`, `ts`, `mjs`, `mts` + +**输出:** 返回类似 `/var/folders/.../js-runner-1234567890-abc123.js` 的路径 + +**路径格式:** + +- 使用操作系统临时目录(Unix 上为 `/tmp`,Windows 上为 `%TEMP%`) +- 前缀: `js-runner-` +- 时间戳: 自纪元以来的毫秒数 +- 随机字符串: 7 字符字母数字 +- 扩展名: 参数中提供的值 + +**示例:** + +```bash +$ bun skills/js-runner/scripts/get_temp_path.js js +/var/folders/8m/0hm18pdd7ts2bwp0530drz500000gn/T/js-runner-1770257905333-na6ujx.js + +$ bun skills/js-runner/scripts/get_temp_path.js ts +/var/folders/8m/0hm18pdd7ts2bwp0530drz500000gn/T/js-runner-1770257905333-v8yzt.ts +``` + +## 错误处理 + +### 未安装 Bun + +**症状:** `command not found: bun` + +**解决方案:** + +提示用户 Bun 没有安装,并说明安装方式,禁止直接自动安装 + +### 脚本语法错误 + +Bun 提供详细的语法错误信息: + +```bash +$ bun "$TEMP_FILE" +error: Unexpected token + --> /var/folders/.../script.js:2:10 + | + 2 | const = 123; + | ^ +``` + +错误信息包括: + +- 文件路径和行号 +- 错误的确切位置 +- 问题描述 + +### 运行时错误 + +运行时错误包含完整的堆栈跟踪: + +```bash +$ bun "$TEMP_FILE" +ReferenceError: foo is not defined + at script.js:3:5 + at main (script.js:1:1) +``` + +### 其他错误 + +其他任何形式的错误都原样输出 + +## 输出处理 + +### 标准输出 + +所有 `console.log()`, `console.info()`, `console.warn()` 输出都到 stdout: + +```bash +bun "$TEMP_FILE" # stdout 由调用代码捕获 +``` + +### 错误输出 + +`console.error()` 输出到 stderr: + +```bash +bun "$TEMP_FILE" 2>error.log # 单独捕获 stderr +``` + +### 退出码 + +脚本可以设置自定义退出码: + +```javascript +process.exit(1) // 错误 +process.exit(0) // 成功 +``` + +调用者接收这些退出码以确定执行状态。 + +## 临时文件管理 + +执行后 **不会主动删除** 临时文件。这是设计使然: + +- 操作系统自动管理临时目录空间 +- 文件可以保留用于调试目的 +- 大多数操作系统定期清理旧的临时文件 + +## 最佳实践 + +1. **始终检查 Bun 是否已安装**,然后再尝试执行脚本 +2. **使用辅助脚本为每次执行生成唯一的临时路径** +3. **单独处理 stdout/stderr** 以区分输出和错误 +4. **检查退出码** 以检测脚本失败 +5. **使用 ESM imports** (`import from`) 编写现代 JavaScript +6. **捕获并显示错误** 以帮助用户调试问题 diff --git a/skills/js-runner/scripts/get_temp_path.js b/skills/js-runner/scripts/get_temp_path.js new file mode 100644 index 0000000..87784c8 --- /dev/null +++ b/skills/js-runner/scripts/get_temp_path.js @@ -0,0 +1,14 @@ +import { tmpdir } from "os"; +import { join } from "path"; + +export function getTempPath(extension) { + const timestamp = Date.now(); + const random = Math.random().toString(36).substring(7); + return join(tmpdir(), `js-runner-${timestamp}-${random}.${extension}`); +} + +// CLI interface: accepts extension as first argument +if (import.meta.main) { + const extension = process.argv[2] || "js"; + console.log(getTempPath(extension)); +}