1
0
Files
Skill/openspec/changes/archive/2026-02-05-js-runner/design.md
2026-02-06 14:55:59 +08:00

5.9 KiB
Raw Blame History

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/<skill-name>/
  • 必须同时支持 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 可以直接运行脚本并自动处理依赖:

  • 自动依赖解析: 当脚本使用 importrequire 引入外部包时Bun 自动下载并缓存该包
  • 无需手动安装: 不需要手动运行 bun installBun 在运行时自动处理
  • 智能缓存: Bun 全局缓存已下载的包,后续运行无需重复下载
  • 简化实现: 不需要生成临时的 package.json,也不需要管理 node_modules

工作流程:

  1. 用户直接运行脚本(内联或从文件)
  2. 脚本中使用 importrequire 引入依赖(如 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 运行(已确保环境就绪)

实现方式:

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 输出
    • 考虑:解析并美化常见错误
    • 决策:从原始输出开始,根据用户需求增强