脚本运行机制
盒子把脚本跑起来,靠两样东西:一个 TOML 声明文件,一个 JSON 参数文件。TOML 告诉盒子"脚本是什么",JSON 负责"传数据、传参数、传结果"。
理解这段机制,是读懂后续所有文档的基础。它的主线只有三步:
- TOML 声明——你用
bm-scripts-box-rc.toml声明脚本,盒子据此装好环境 - JSON 传入——盒子把数据、参数、环境信息写进 JSON,把路径传给脚本
- JSON 回传——脚本需要时,把结果写成 JSON 传回给盒子
机制总览
| 环节 | 用什么 | 方向 | 内容 |
|---|---|---|---|
| 声明脚本 | bm-scripts-box-rc.toml | 开发者 → 盒子 | 语言、入口、触发方式、依赖 |
| 传参 | JSON 参数文件 | 盒子 → 脚本 | environment / data / params 三段 |
| 回传结果 | JSON 文件 | 脚本 → 盒子 | 信封:code / msg / 业务键 |
盒子安装运行脚本,用的是 TOML 声明文件。开发者声明后,盒子根据声明的配置进行环境依赖的安装,并按照声明的规范执行脚本。数据传输、参数传递靠的是 JSON 文件。
第一步:TOML 声明脚本
开发者声明,盒子执行。 你只写一份 bm-scripts-box-rc.toml,声明脚本的形态:
[bmscriptsbox.runtime]
language = "python" # 用什么语言写
language_version = ">=3.8" # 语言版本要求
entry = "main.py" # 入口文件盒子在安装期读这份声明,自动完成:下载匹配的语言运行时、创建虚拟环境、安装依赖、下载外部工具和 AI 模型、注册触发方式。你声明什么,盒子就配什么。
第二步:JSON 传参(盒子 → 脚本)
脚本运行时需要的所有信息,都通过一个 JSON 文件传入。 盒子启动脚本时:
- 把环境信息、业务数据、运行参数,统统按约定规范写入一个临时 JSON 文件
- 把这个 JSON 文件的路径,作为命令行第一个位置参数传给脚本
- 脚本读取位置参数,解析 JSON,一次性拿到所有内容
盒子实际执行的命令只有一行:
python main.py "C:/Users/xxx/AppData/Local/Temp/a1b2c3d4.json"参数文件固定分三段:
| 段 | 内容 | 谁写的 |
|---|---|---|
environment | 盒子信息(api_base、script_dir、invoke_mode…) | 盒子 |
data | 业务数据(选中的文件、剪贴板文本…) | 盒子 |
params | 运行参数(你声明的默认值 / 用户填的值) | 盒子 |
脚本读取位置参数并解析这个 JSON,就能拿到环境信息、数据、参数。整个契约只有一条:命令行第一个参数是 JSON 文件的路径。
JSON 的完整结构、各语言读取方式 → 参数传递机制。
第三步:JSON 回传(脚本 → 盒子)
脚本如需把结果回传给盒子,也是通过 JSON 文件传回。是否回传、怎么回传,取决于谁在等结果:
- 普通触发(右键、快捷键、直接启动):你爱怎么输出都行——打印、弹窗、写文件,盒子不干预
- 被联动调用(作为节点):必须把结果写成信封(
{code, msg, ...业务键}),写入environment.output_json指定的文件,调用方脚本才能读回
为什么用文件传参
盒子是跨语言的脚本管理工具,支持 Python、Node.js、PowerShell、BAT、AutoHotkey、HTML、EXE 七种形态。之所以选择用文件传参,是为了各语言的适用性和传参的稳定性:
- 跨语言通用:文件是七种语言都读得懂的载体,不需要为每种语言做一套 SDK 或参数解析适配
- 传参稳定:命令行直接传参容易遇到转义、长度、编码问题;文件传参不受这些限制,中文、路径、复杂结构都能可靠传递
这也是"脚本本身没有任何 SDK"的原因——它只是普通脚本,盒子替它完成了所有"脚本之外"的部分。脚本换个地方照样能跑,只是没人给它传参数而已。
常见误解
「我需要引入盒子的 SDK 吗?」 不需要。盒子没有任何 SDK。脚本靠 JSON 文件传参,换个地方照样能跑。
「脚本必须叫 main.py 吗?」 不必。入口文件叫什么、放在哪都行,只要在配置文件的 entry 里写对相对路径。
「盒子会等我的脚本跑完吗?」 会。除了 /api/execute 的异步模式,盒子默认同步等待。所以耗时任务请自己控制时长,别把盒子界面卡住。
「我能修改 environment 段吗?」 不能,也不该。environment 是盒子保留区,脚本只读。被联动调用时,盒子会为每个脚本重建 environment,调用方传什么都没用。
「不声明 inputs 会怎样?」 盒子就不给你构造 data 段,直接启动脚本。适合不需要外部输入的脚本(比如清空回收站、打开某个工具)。