脚本 API 参考
GateLLM 内置 JavaScript 脚本引擎(基于 QuickJS),可对请求和响应的 JSON body 做自定义变换。脚本运行在沙箱中,有严格资源限制,安全且可控。
本章是 API 参考。入门见 写第一个脚本变换,配置参考见 脚本配置。
基本结构
每个脚本定义一个 transform 函数,接收 body 和 context,必须返回 body:
function transform(body, context) {
// 读取和修改 body
// 读取 context 获取元数据(只读)
return body; // 必须!
}| 参数 | 可修改 | 说明 |
|---|---|---|
body | 是 | JSON 请求体或响应体 |
context | 否 | 请求/响应元数据(模型名、headers 等) |
Context 对象
context 提供当前请求/响应的元数据,只读:
请求和响应阶段均可用
| 字段 | 类型 | 说明 |
|---|---|---|
context.clientModel | string | 客户端看到的模型名 |
context.upstreamModel | string | 发送给上游的模型 ID |
context.upstreamName | string | 上游分组名 |
context.sourceProtocol | string | 客户端协议(如 "OpenAIChatCompletions") |
context.targetProtocol | string | 上游协议(如 "Anthropic") |
context.stream | boolean | 是否流式请求 |
context.headers | object | 请求 headers(敏感头已过滤) |
context.query | object | URL 查询参数 |
context.requestId | string | 唯一请求 ID |
context.clientIp | string | 客户端 IP |
context.accessKeyName | string | 访问密钥名 |
context.accessKeyGroup | string | 访问密钥分组 |
仅响应阶段可用
| 字段 | 类型 | 说明 |
|---|---|---|
context.responseStatus | number | 上游 HTTP 状态码 |
context.responseHeaders | object | 上游响应 headers |
context.elapsedMs | number | 耗时(毫秒) |
安全:
authorization、cookie、x-api-key等敏感 headers 在脚本可见之前已被移除。
context.useModel 切换路由
context.useModel("model-name");完整路由切换:base_url、协议、凭证一起换。body.model = "X" 仅改请求体的字段,不改路由——用 context.useModel 才能跨端点/跨协议切换。
请求脚本的两个槽(before / after)
请求侧脚本不再是一个脚本加位置开关,而是两个独立槽,各自可空、可同时配置:
| 槽 | 字段 | 运行时机 | 看到的 body | useModel 能力 |
|---|---|---|---|---|
| 翻译后 | request_transform_after | 协议翻译之后 | 上游协议格式 | 仅同协议切换 |
| 翻译前 | request_transform_before | 协议翻译之前 | 客户端原始格式 | 支持跨协议切换 |
request_transform_after:在协议转换后运行,body 已是上游格式。适合简单的字段修改、上游方言改写。request_transform_before:在协议转换前运行,body 是客户端原始格式。适合需要检测客户端输入(如图片、搜索、plan 模式标记)并切换路由的场景。- 两个槽可同时配置:同一路由的 before 与 after 各自独立合并(model 覆盖 upstream),两个脚本都会运行——before 先跑(可触发跨协议 立即
useModel切换),after 后跑。注意:一旦 before 槽触发了 立即useModel切换路由,原路由的 after 槽不再执行(整套 pipeline 换成目标路由的);after 槽声明的useModel是同协议 延后切换。response_transform无槽概念,保持单字段。
执行顺序
before 槽与 after 槽各自独立运行;同一路由两者都配时,before 先在翻译前阶段跑,after 在翻译后阶段跑。下面分别给出两槽在管线中的位置。
请求侧 — after 槽(翻译后)
客户端请求 → 协议转换 → 自动归一化 → request_payload 规则 → 上游脚本 → 模型脚本 → 缓存注入 → 发送到上游请求侧 — before 槽(翻译前)
客户端请求 → 上游脚本 → 模型脚本 → (useModel swap) → 协议转换 → 自动归一化 → request_payload 规则 → 缓存注入 → 发送到上游响应侧(仅非流式)
上游响应 → 响应脚本 → 反向协议转换 → 返回客户端流式请求的响应脚本暂不支持。
内置函数
JSON Path 操作
// 读取嵌套值
const temp = json_path(body, "generation_config.temperature");
// 设置值(自动创建中间对象)
set_path(body, "generation_config.max_output_tokens", 4096);
// 删除字段
remove_path(body, "deprecated_field");
// 仅当字段不存在时添加
add_if_absent_path(body, "temperature", 1.0);
// 向数组追加
append_path(body, "messages", { role: "system", content: "Be concise." });字符串函数
str_len("Hello, 世界!"); // 9(字符数,非字节数)
str_contains("hello world", "world"); // true
str_replace("foo-bar", "-", "_"); // "foo_bar"
str_starts_with("hello", "he"); // true
str_trim(" hello "); // "hello"正则表达式
regex_match("abc123", "[0-9]+"); // true
regex_replace("foo123bar", "[0-9]+", "N"); // "fooNbar"
regex_extract("a=1 b=2", "([a-z]+)="); // ["a", "b"]编码与哈希
base64_encode("hello"); // "aGVsbG8="
base64_decode("aGVsbG8="); // "hello"
sha256("hello"); // "2cf24dba5fb0..."
json_encode(body.messages); // 序列化为字符串
json_parse(jsonStr); // 从字符串解析数组函数
array_sort([3, 1, 2]); // [1, 2, 3]
array_unique([1, 2, 2, 3]); // [1, 2, 3]
array_filter_by(items, "active", true); // 保留 active=true 的元素
array_find(users, "name", "alice"); // 找到第一个 name=alice 的元素
array_pluck(users, "name"); // 提取所有 name 字段
array_sum([1.5, 2.5, 3.0]); // 7.0深拷贝与合并
const backup = deep_clone(body); // 独立副本
const merged = deep_merge(defaults, overrides); // 递归合并UUID 与时间
uuid(); // "550e8400-e29b-41d4-a716-..."
now(); // 1748620800(秒级时间戳)
now_ms(); // 毫秒级
format_time(now(), "%Y-%m-%d %H:%M:%S"); // "2025-05-31 00:00:00"运行限制、错误处理与测试
脚本的沙箱能力边界(可做 / 不能做)、资源限制表(操作数、堆上限、并发执行槽、懒投影语义)、script_error_mode 错误处理、常见报错与排查、测试接口(POST /console/api/scripts/test)及性能建议,统一见 脚本运行限制与配置——那是脚本配置与限制的唯一权威页,本页不再重复。
常见问题
Q:脚本改了 body.model,为什么路由没变?body.model 只改请求体的字段,不改路由。要切换路由用 context.useModel("模型名")。
Q:流式请求的响应脚本生效吗? 暂不支持流式响应的脚本。请求脚本对流式请求有效,但响应脚本仅在非流式时生效。
Q:Before 和 After 脚本位置怎么选?
- 只改上游格式 body 的字段 → After(默认)
- 需要检测客户端原始格式(如不同协议的图片字段不同)且判定超出
switch-route能表达的范围 → Before - 「检测图片/联网→切模型」这类纯路由决策(含跨协议)→ 优先用原生
switch-route规则,见 把含图片的请求路由到视觉模型
下一步:写第一个脚本变换 看入门结构;用脚本做协议翻译修正 与 用脚本做响应脱敏 看实战示例;脚本运行限制与配置 看沙箱、资源限制、错误处理与测试。
