用途
本技能指导编写 Windmill 平台的 Bun Native 脚本。Native 脚本是运行在原生 worker 上的 Bun 脚本。原生 worker 是一个轻量级 V8 隔离环境,提供 fetch 和 JavaScript 标准库,可被大量并行化。每个脚本的第一行必须写 //native,以便 Windmill 将其路由到原生 worker;没有这一行,完全相同的脚本会在普通 Bun worker 上运行。
主要能力
脚本的输入就是其参数。凭据和配置以资源类型参数传入,绝不硬编码或从环境读取。语言章节展示了该语言如何声明参数。
可以使用 RT 命名空间引用资源类型。使用资源类型前,请检查项目根目录的 rt.d.ts 文件,查看所有可用资源类型及其字段(该文件由 wmill resource-type generate-namespace 生成)。
可以导入 npm 包和其他 Windmill 脚本(如 ./helper.ts)。导入的解析和打包方式与普通 Bun 脚本完全一致,约束在于运行时而非导入列表:原生 worker 只提供 fetch 和 JavaScript 标准库,因此任何导入代码只能依赖这两者。需要 Node/Bun 运行时 API(文件系统、node:* 模块、子进程、原生插件)的库无法在原生 worker 上工作,应改用普通 bun 语言。
HTTP 请求使用全局可用的 fetch。
纯计算脚本可在 //native 之后的头部注释块中声明 //no_network。运行时随后会拒绝脚本尝试的任何连接:对所有主机的 fetch、Windmill API(因此 windmill-client 调用也会失败)、原始套接字和 unix 套接字,并且 WM_TOKEN 不会被设置。该声明仅对原生脚本生效,没有 //native 时会被忽略。仅当脚本除参数外不需要任何外部数据时使用。
windmill-client 可在原生 worker 上工作(其调用通过 fetch 进行),是访问 Windmill 的首选方式——读取资源/变量/状态、运行脚本和流程,以及 S3 辅助函数(loadS3File、loadS3FileStream、writeS3File、S3Object)。它自行处理认证、工作区和基础 URL。仅在调用非 Windmill 的外部 HTTP API 时使用原始 fetch。
使用方式
结构
导出名为 main 的单个异步函数,不要调用它:
//native export async function main(param1: string, param2: number) { // Your code here return { result: param1, count: param2 }; }
预处理器脚本
预处理器脚本在将原始触发数据(webhook、自定义 HTTP 路由、SQS、WebSocket、Kafka、NATS、MQTT、AMQP、Postgres、GCP Pub/Sub、Azure 或 email)传递给流程之前进行处理,从而将触发逻辑与流程逻辑分离,保持自动生成的 UI 简洁。
预处理器用 TypeScript 或 Python 编写:函数名为 preprocessor 而非 main,接收单个名为 event 的参数。返回的对象决定传递给流程的参数值。例如 { b: 1, a: 2 } 会以 a = 2 和 b = 1 调用流程(假设流程有两个名为 a 和 b 的输入)。
CLI 命令
脚本放在文件夹中。编写完成后,告知用户哪个命令适合其目的:
- wmill script preview <script_path> ——在本地迭代脚本时的默认选择。无需部署即可运行本地文件。
- wmill script run <path> ——运行已在工作区部署的脚本。仅在用户明确想测试已部署版本而非本地编辑时使用。
- wmill generate-metadata ——为你修改过的脚本重新生成本地 .script.yaml(输入模式)和 .lock(已解析依赖),并刷新 wmill-lock.yaml 中对应的内容哈希。仅限本地文件,不是部署。
- 将本地更改部署到工作区——通过 git push 或 wmill sync push,取决于仓库的配置方式。仅在用户明确要求部署/发布/推送时建议或执行部署,而不是当用户说“运行”“试试”或“测试”时。
预览与运行的选择
按意图而非习惯选择。如果用户说“运行脚本”“试试它”“测试它”“它能工作吗”,且脚本文件有本地编辑,请使用 script preview。不要先推送脚本再 script run——推送就是部署,仅为了测试而部署会用未测试的更改覆盖工作区版本。
仅在以下情况使用 script run:用户明确说“运行已部署版本”/“运行服务器上的版本”;没有正在编辑的本地脚本(只是调用现有脚本)。
仅在以下情况使用 sync push:用户明确要求部署、发布、推送或交付;预览已验证更改且用户希望其进入工作区。
编辑后保持元数据同步
wmill-lock.yaml 跟踪每个条目的内容哈希。编辑脚本内容——最重要的是添加或删除导入或更改 main 的参数——会使该哈希失效,导致 .lock、.script.yaml 输入模式和哈希行过期。此类编辑后运行 wmill generate-metadata(限定在你触及的范围内),让解析后的锁、自动生成的参数 UI(由 .script.yaml 驱动)和 wmill-lock.yaml 都与代码匹配。保持过期会在 git-sync 和 CI 中产生虚假差异。
此命令只写入本地文件(不是部署),但它会重新解析依赖,因此可能提升未固定版本(与从 UI 部署相同;属预期行为,不是 bug)。所以默认应主动提供并征得用户同意后运行一次,而不是每次编辑后静默运行——除非项目的 AGENTS.md 选择自动运行元数据。无论哪种方式,都由你运行命令,而不是用户。运行后,对重新生成的 .lock / .script.lock 文件做差异比较,并告知用户哪些依赖版本发生了变化(例如 requests 2.31.0 → 2.32.0),以便在部署前发现不想要的版本提升——即使处于 Metadata: auto 下亦然,因为这是信息而非确认门槛。在代码中固定版本可使其保持不变。
不带路径参数时,generate-metadata 只重新生成内容哈希漂移的条目,而非全部。导入会传播:编辑一个被其他脚本导入的脚本会标记每个导入者为过期,因此对共享模块的一行更改可能重新生成许多锁(这是设计使然——它们的锁必须反映导入的代码)。如果触及范围超出预期,运行 wmill generate-metadata --dry-run——它会列出每个过期条目及原因(内容已更改或依赖 <path>)而不做任何更改——然后用路径参数(wmill generate-metadata f/foo)或 --strict-folder-boundaries 缩小范围。
如果磁盘上的 .lock 和 .script.yaml 已经正确,只有 wmill-lock.yaml 需要刷新哈希(哈希漂移,或引导缺失条目),使用 wmill generate-metadata rehash——它从磁盘重新记录哈希,无需后端往返,也不改变依赖。
编写后主动提供测试
如果用户尚未要求你运行/测试/预览脚本,用一句话提供下一步(例如“要我带示例参数运行 wmill script preview 吗?”)。不要呈现多选项菜单。
如果用户已在原始请求中要求测试/运行/尝试脚本,跳过提议,直接执行 wmill script preview <path> -d '<args>'——从脚本声明的参数中选择合理的参数。参数形式因语言而异:代码语言为 main(...),SQL 方言使用自己的占位符语法(PostgreSQL 为 $1,MySQL/Snowflake 为 ?,MSSQL 为 @P1,BigQuery 为 @name 等),Bash 为位置参数 $1、$2、…,PowerShell 为 param(...)。
wmill script preview 不部署,但仍会执行脚本代码并可能产生副作用;当用户要求测试/预览时(或确认确实要执行后)自行运行它。wmill generate-metadata 也不部署——它只写入本地文件(锁、模式、哈希)——但根据上文“保持元数据同步”,运行前应主动提供(或若项目 AGENTS.md 选择自动运行则自动运行)。部署到工作区(git push 或 wmill sync push)是唯一会改变远程状态的步骤——仅在用户明确要求部署/发布/推送时执行。
如需在开发页面中打开脚本的可视化预览(而非 script preview 的运行并打印结果),请使用 preview 技能。
使用 wmill resource-type list --schema 发现可用的资源类型。
适用场景
适用于编写需要在原生 worker 上运行、可大量并行、仅依赖 fetch 与标准库的 Windmill Bun Native 脚本;适用于编写预处理器脚本;适用于通过 windmill-client 与 Windmill 平台交互或进行 S3 对象操作。需要 Node/Bun 运行时 API 的脚本应改用普通 bun 语言。
限制
原生 worker 只提供 fetch 和 JavaScript 标准库。需要 Node/Bun 运行时 API(文件系统、node:* 模块、子进程、原生插件)的库无法在原生 worker 上工作。脚本首行必须是 //native,否则会在普通 Bun worker 上运行。若某服务没有对应资源类型,仍应将其连接作为一个资源类型参数(自定义类型,名为 c_<name>);此外资料中提到,若实例未同步 Windmill Hub 的资源类型,可由超级管理员同步。