5.5 PSL(Pop Script Language)脚本
在可视化工作流中,大部分需求可以通过 拖拽节点 + 配置参数 来完成。
但在某些场景下,你仍然需要:
- 对数据做更细粒度的处理(过滤、聚合、映射、重命名字段)
- 按复杂规则组合多个节点的输出
- 对全局变量进行灵活控制
- 写一些“如果……就……”逻辑
为此,Pop 提供了 PSL(Pop Script Language):
一种运行在工作流内部的“脚本化胶水语言”,语法风格接近 TypeScript/JavaScript,
但在运行时注入了input、nodes、globals等特殊对象,专门用于操作工作流数据。
一、脚本运行环境概览
在支持脚本的节点中(如「脚本节点」「自定义表达式」「条件判断脚本」等),PSL 运行时会注入一组常用对象:
| 标识符 | 类型/含义 | 典型用途 |
|---|---|---|
input |
当前节点的输入集合(NodeOutputItem 列表) | 读取上游输出、聚合多个输入 |
nodes |
整个工作流中其他节点的快照索引 | 从任意节点取输出、做交叉计算 |
globals |
全局变量对象,可读可写 | 存储计数器、配置等跨节点共享的数据 |
output |
当前脚本返回值(通过 return 设置) |
决定节点的最终输出 |
你可以把它理解为:
function script({ input, nodes, globals }) {
// 在这里写 PSL 代码
return ...; // 作为当前节点输出
}
PSL 并不是完整的浏览器环境:
- 没有
window、document等 DOM 对象 - 不能直接发起网络请求(请使用 HTTP 节点)
- 不能直接访问本地文件(请使用文件相关节点)
它的职责:专注于 工作流数据处理与逻辑控制。
二、input 对象:访问当前节点输入
input 表示当前节点收到的所有输入端口数据,是 PSL 中最常用的对象之一。
在 PSL 中,你可以像下面这样使用 input:
1. 快速访问首个输出项
input.value; // 首个输入项的值
input.type; // 首个输入项的数据类型,如 "text" / "json" 等
input.meta; // 首个输入项的元信息
input.output; // 首个输出项完整对象 { type, value, meta, ... }
适合只有单一输入的简单场景,比如:对上游一个节点的文本结果做二次处理。
2. 访问所有输入项:input[index] / input.all
当当前节点有多个输入时,可以使用数组访问语法:
input[0].value; // 第 1 个输入的值
input[0].type; // 第 1 个输入的类型
input[0].meta; // 第 1 个输入的元信息
input.all[0].output?.value; // 通过 all 访问完整输出结构
input.all[1].meta; // 访问第 2 个输入的元数据
提示:
input[index]与input.all[index]返回的元素,都支持.output / .value / .type / .meta。
3. 聚合方法:length / first / byPort / from / flatValues / ofType
input 内置了一组聚合方法,用于快速处理多输入场景:
input.length; // 输入项总数
input.first(); // 返回首个输入项(等价于 input[0])
input.byPort("default"); // 按端口 ID 筛选
input.from("node_12"); // 返回来自指定节点 ID 的输入
input.flatValues(); // 收集所有输入项的 value,组成数组
// 按数据类型筛选
input.ofType("text"); // 只保留文本类型的结果
input.ofType("text").length; // 文本类输入数量
input.ofType("text").map((o) => o.value); // 提取所有文本值
典型用法:
// 将所有文本输入拼成一段话
const text = input
.ofType("text")
.map((o) => o.value)
.join("\n");
return text;
三、nodes 对象:访问任意节点输出
nodes 是一个“节点索引表”,可以在脚本里 随时读取工作流中其他节点的输出。
1. 基础用法
nodes[1].output.value; // 第 2 个节点的首个输出值
nodes[8].outputs[0].type; // 第 9 个节点的第 1 个输出类型
nodes.sn(2).output; // 使用 sn(2) 访问第 3 个节点
nodes[3].outputs[1].value; // 第 4 个节点的第 2 个输出值
注意:
nodes[n].output等价于nodes[n].outputs[0]。
典型场景:
- 在一个“汇总节点”中读取多个前序节点的输出进行合并
- 在调试脚本中比对不同节点的值
示例:
// 对比两个节点的处理结果是否一致
const a = nodes[2].output.value;
const b = nodes[5].output.value;
return {
equal: a === b,
a,
b,
};
四、globals 对象:全局变量读写
globals 用于存储 工作流级别的状态与配置:
- 计数器(counter)
- 用户配置(config)
- 上一步执行结果的缓存
1. 读取全局变量
globals.name; // 如:全局用户名
globals.config; // 任意配置对象
2. 更新全局变量(推荐使用 globals.set)
globals.set("name", "lisi");
globals.set("counter", (globals.counter || 0) + 1);
return globals.counter;
建议:始终使用
globals.set(key, value)更新全局状态,方便未来进行行为跟踪与调试。
五、常用辅助方法与代码片段
除了 input / nodes / globals,PSL 在运行时还配合一系列 常用辅助方法,这些方法大多挂在集合对象上(例如 input.ofType、input.flatValues 等)。
1. ofType(type)
按数据类型筛选输出项,返回 NodeOutputItem[]:
const texts = input.ofType("text");
const count = input.ofType("number").length;
return {
textCount: texts.length,
numberCount: count,
};
2. flatValues()
收集当前集合中所有 outputs[*].value:
// 收集所有输入的 value 形成数组
const values = input.flatValues();
// 也可以用于 nodes 某一个节点的 outputs
const nodeValues = nodes[1].outputs.flatValues();
return {
values,
nodeValues,
};
六、常用脚本示例
下面的示例与脚本帮助弹窗(ScriptHelpDialog)中的示例保持一致,方便你在界面与文档之间对照查看。
示例 1:拼接所有文本输入
// 文本拼接
return input
.ofType("text")
.map((o) => o.value)
.join(" ");
示例 2:统一返回结构
// 统一返回
return {
ok: !!input.value,
values: input.flatValues(),
};
示例 3:多类型结果输出
// 多类型结果
return [
{ type: "boolean", value: input.value === "ok" },
{ type: "text", value: String(nodes[1].type) },
];
示例 4:按条件决定输出内容
// 条件处理
if (input.length > 0) {
return input.flatValues().join("\n");
} else {
return "暂无数据";
}
七、编写 PSL 时的注意事项
-
尽量保持脚本纯函数化:
- 相同输入 → 相同输出
- 便于调试和复用
-
不要在脚本中做重型计算:
- 如大规模文件处理、网络请求,应该交给专门节点完成
-
全局变量只放“状态”与“配置”:
- 避免把大型数组或大量中间结果塞进
globals
- 避免把大型数组或大量中间结果塞进
-
善用 Script 帮助面板:
- 编辑脚本时,点击「脚本帮助」,可以快速查看
input / nodes / globals / funcs的说明与示例
- 编辑脚本时,点击「脚本帮助」,可以快速查看
八、小结
PSL(Pop Script Language)是 Pop 工作流中处理数据与控制细节逻辑的核心能力之一:
- 通过
input/nodes/globals访问整个工作流的数据与状态 - 通过聚合方法(
ofType、flatValues等)简化数组和多输出处理 - 通过简洁的脚本实现条件分支、格式转换、结果包装
推荐使用方式:
- 优先使用节点组合 完成大部分流程;
- 仅在需要细节处理时,引入 PSL 作为“胶水层”;
- 将常用脚本整理为片段(Snippets),在多个工作流中复用。
熟练掌握 PSL,可以大幅提升你在 Pop 中构建复杂自动化与 AI 流程的效率。