内容
# LibreFlow
[](https://github.com/MauricioPerera/libreflow/actions/workflows/ci.yml)
一款自主托管的、视觉化的 **工作流自动化** 工具(类似 n8n 风格的引擎)。在节点画布上构建工作流,可以手动、按计划或通过 webhook 运行,并将其公开为 MCP 工具。工作流也是一个 **状态引擎**(具有原子操作的表格 + 反应式触发器),可以运行一个 **AI 代理** 节点,其工具是您自己的工作流。包含 Express + SQLite 后端和 Vue 3 + Vue Flow 前端的多仓库。
## 亮点
- **20种节点类型**,包括 `aiAgent`(LLM 工具调用循环)、`mcpToolCall`(MCP 客户端)、`dataTable`、`vectorStore`(嵌入 + 相似性搜索,用于 **RAG**)、循环、子工作流、HTTP、JS 代码,以及控制/数据基元(`switch`、`filter`、`aggregate`)、文件内容(`extractFromFile`、`convertToFile`)和自定义 HTTP `respond`。
- **RAG / 向量搜索** — `vectorStore` 节点嵌入文本(任何兼容 OpenAI 的端点:LM Studio / Ollama / OpenAI)并对存储在 **LibreFlow 自己的 SQLite** 中的集合进行相似性搜索(引擎:零依赖 `js-vector-store`;单文件备份完整;所有者范围)。索引内联项目或 **数据表的文本列**(`indexTable`)。组合 `vectorStore(搜索)→ aiAgent` 以实现检索增强的生成。
- **多用户身份验证和隔离** — 邮箱/密码登录,颁发会话 **JWT**(每个 `/api` 调用都带有),一个 **admin** 角色可以看到所有内容,普通用户通过 `owner_id` **隔离**:每个用户只能看到自己的流程、凭证、数据表和执行结果,并且流程只能使用其所有者的凭证(在执行、路由和 MCP 中强制执行)。管理员可以通过 UI 进行用户管理(`/api/users`)。单租户安装(无所有者)不受影响。
- **MCP 服务器,双向** — 将整个平台公开给全球,或一个精选的 **命名服务器**(一组流程作为工具,位于其自己的令牌保护的 URL 上)。通过官方 `@modelcontextprotocol/sdk` 实现符合标准的 **可流式传输的 HTTP** 传输。除了工具,全球服务器还提供 **资源** — 您的数据表(`libreflow://datatable/{id}`)和工作流定义(`libreflow://workflow/{id}`)作为只读上下文 — 并且 `aiAgent` 可以从另一个服务器**使用**技能(MCP 资源)和**提示模板**(MCP `prompts`)。
- **自定义 HTTP 响应和网络表单** — webhook 触发器可以是 **同步** 的(`responseMode`:`lastNode` / `respondNode`),并且 `respond` 节点返回自定义状态/头部/正文。**表单触发器** 提供一个自动生成的公共网络表单(`GET/POST /form/:workflowId`),在提交时运行流程。
- **文件内容** — `extractFromFile` 将 **CSV/XLSX/JSON/文本** 解析为结构化行,并从 **PDF 中提取文本**;`convertToFile` 将 CSV/XLSX/JSON/文本生成回可下载的二进制文件(XLSX 通过 **exceljs**,PDF 文本通过 pdf-parse)。
- **集合基元** — `switch`(按规则的 N 路路由)、`filter` 和 `aggregate`(分组 + 计数/求和/平均值/最小值/最大值,排序,限制,重复数据删除)— 本地,确定性,无 LLM。
- **数据表状态引擎** — 唯一键幂等性,原子 `upsert` / `increment` / 获取或默认值,一个事务中的全有或全无 **`batch`** 混合操作,丰富查询(运算符 + 排序 + 限制),和 **反应式触发器**(在行插入/更新时运行流程)。
- **流式触发器** — 持久的长期连接(SSE,WebSocket,MQTT,IMAP),每个入站消息触发一个流程,具有自动指数退避重连。
- **持久执行** — `wait` 节点挂起运行并返回恢复令牌;稍后通过 `POST /hooks/resume/:token` 继续。引擎从缓存的输出重放已经运行的节点(无双重副作用),并从 `wait` 节点恢复。
- **粒度调试** — **固定** 节点的输出,以便手动运行重用它而不是重新执行(跳过昂贵/外部调用,同时迭代),并且 **从节点重新运行**(重用缓存的上游输出,仅重新运行节点及其后代)。固定仅适用于手动运行,绝不在生产环境中。
- **二进制文件** — `httpRequest` 可以下载到 / 上传到二进制存储;节点输出携带轻量级引用(`_lfBinary`)而不是内联字节,可以通过 `/api/binaries/:id` 下载。由 `LF_MAX_BINARY_MB` 限制。
- **大数据助手** — `loop` 支持 `batchSize`(分块处理项目)和 `jsCode` 接受每个节点的内存/超时覆盖。
- **流程一致性验证和 AI 错误上下文** — 结构验证器捕获悬空表达式(重命名破坏),未知类型和错误句柄(`POST /api/workflows/validate`,在保存时也会运行)。失败的执行公开一个 **预装的 LLM 提示**(`GET /api/executions/:id/llm-context`),表现为一个“🤖 Contexto IA”按钮。
## 技术栈
- **后端**(`backend/`)— Node + Express + TypeScript,SQLite(WAL),`node-cron`,`@modelcontextprotocol/sdk`。端口 **3000**。
- **前端**(`frontend/`)— Vue 3 + Vue Flow + Vite。端口 **5173**(代理 `/api` 和 `/mcp` → 后端)。
## 要求
- Node **20.6+**(在 Node 24 上开发)和 npm。
## 安装
```bash
npm install # 根目录 + 工作空间
npm install -w backend
npm install -w frontend
```
```bash
cp .env.example .env # 然后编辑;查看文件中的每个变量
```
**登录(多用户)**:UI 由登录屏幕控制,因此您需要至少一个用户。设置 `LF_ADMIN_EMAIL` + `LF_ADMIN_PASSWORD` 以 **引导第一个管理员** 启动(在开发环境中也有效);然后使用这些凭证登录并从 **Usuarios** 管理视图创建更多用户。没有它们,无法通过登录屏幕。
生产环境(`NODE_ENV=production`)所需:`ENCRYPTION_KEY`,`LF_API_KEY`,`LF_WEBHOOK_SECRET` 和 `LF_JWT_SECRET`(签名会话 JWT — 应用程序在生产环境中拒绝颁发/验证令牌)。所有其他变量都是可选的,具有合理的默认值 — 请参阅 [.env.example](.env.example)。
## 运行(开发)
```bash
npm run dev # 后端(:3000)+ 前端(:5173)一起
# 或单独:
npm run dev:backend
npm run dev:frontend
```
打开 http://localhost:5173。 后端在第一次运行创建 `backend/database.sqlite`。
## 构建和测试
```bash
npm run build # 后端(tsc)+ 前端(vue-tsc 和 vite 构建)
npm test # 后端(vitest)+ 前端(vitest + @vue/test-utils + jsdom)
```
## 使用 Docker 部署(单容器)
一个容器运行后端,也提供构建的前端。 状态(SQLite + 二进制文件)存储在命名卷中 — 通过复制该文件备份。
```bash
cp .env.example .env # 然后设置 ENCRYPTION_KEY, LF_API_KEY (和 LF_PUBLIC_URL 用于 OAuth)
docker compose up -d --build
# → http://localhost:3000
```
- **持久性**:SQLite 在 `/data/database.sqlite`(环境变量 `LF_DB_PATH`)位于 `libreflow-data` 卷;二进制表在同一文件中。 备份 = 停止 + 复制文件。
- **可移植性**:导出一个流程为 JSON(Flujos → *Exportar*,或 `GET /api/workflows/:id/export`)并在其他地方导入它(*Importar*,或 `POST /api/workflows/import`)— 凭证通过 ID 引用,绝不导出。
- **前端**:由后端从 `LF_STATIC_DIR`(`/app/frontend/dist`)提供;API 在 `/api` 处是同源的,因此在生产环境中不需要代理。
- **机密**:`ENCRYPTION_KEY` 和 `LF_API_KEY` 是必需的(docker 组合拒绝启动它们)。 设置 `LF_PUBLIC_URL` 为您的真实 URL 以进行交互式 OAuth 和 webhook/表单链接。
## 以编程方式驱动它
在 [.claude/skills/run-libreflow/](.claude/skills/run-libreflow) 处有一个运行/烟雾测试技能:`node .claude/skills/run-libreflow/driver.mjs` 在 API 上运行引擎烟雾测试,并使用无头 Chrome 截图 UI。
## 关键 API 端点
所有 `/api` 下的端点都需要身份验证:会话 **JWT**(来自登录)或全局 `LF_API_KEY`(管理员紧急情况下)。 资源按 `owner_id` 划分范围(管理员可以看到所有内容)。
- `POST /api/auth/login` — 邮箱/密码 → `{ token, user }`;`GET /api/auth/me` — 当前用户;`POST /api/auth/password` — 修改您自己的密码
- `GET|POST|DELETE /api/users[/:id]` — **仅限管理员** 的用户管理(+ `/:id/password` 重置)
- `GET /api/node-types` — 已注册的节点定义
- `POST /api/workflows/run` — 运行临时工作流 `{ workflow, payload }`
- `POST /api/workflows/validate` — 结构一致性检查 `{ nodes, connections }`
- `POST /api/workflows/validate-batch` — 一次验证多个已保存的流程;按 `{ ids }` 或 `{ contains }`(图形子字符串,例如一个 API 主机)过滤以实现“修复所有与一个 API 绑定的流程”
- `GET /api/executions/:id/llm-context` — 为失败的运行提供预装的 LLM 提示 + 上下文
- `GET|POST|DELETE /api/workflows[/:id]` — 工作流 CRUD(+ `/:id/active`,`/:id/versions`,`/:id/versions/:version`,`/:id/versions/:version/restore`)
- `GET /api/workflows/:id/export` / `POST /api/workflows/import` — 导出/导入流程为可移植的 JSON(无 ID/机密;导入创建新流程)
- `GET /api/executions[/:id]`,`GET /api/workflows/:id/executions` — 运行历史
- `GET /api/binaries/:id` — 下载二进制存储对象(由输出中的 `_lfBinary` 引用)
- `POST /hooks/resume/:token` — 恢复暂停的(`wait`)运行;POST 正文成为等待输出
- OAuth2 交互式:`POST /api/credentials/:id/oauth/authorize`(启动)+ 公共 `GET /oauth/callback`(提供者重定向)+ `GET /api/oauth/redirect-uri`(注册 URI)
- `GET|POST|DELETE /api/mcp-servers[/:id]` — 命名 MCP 服务器(精选的工作流组)
- `GET|POST|DELETE /api/credentials[/:id]`,`GET|POST|DELETE /api/data-tables[/:id]`(+ `/rows`)
- `GET /api/vector-stores`,`DELETE /api/vector-stores/:collection` — RAG 集合(所有者范围;由 `vectorStore` 节点的 `index` / `indexTable` 操作填充)
- `* /hooks/:workflowId` — webhook 触发器(当设置 `LF_WEBHOOK_SECRET` 时,进行 HMAC 验证)。 当触发器的 `responseMode` 为 `lastNode` / `respondNode` 时同步;否则立即确认并在后台运行。
- `GET|POST /form/:workflowId` — 公共网络表单(表单触发器);GET 渲染,POST 运行流程
MCP 端点(JSON-RPC,可流式传输的 HTTP):
- `POST /api/mcp` — 全局 MCP 服务器(所有活动工作流 + `libreflow_*` 系统工具)
- `POST /mcp/:serverId` — 命名 MCP 服务器的 URL(其工作流组作为工具,由每个服务器的承载令牌保护,除非标记为公共)。 安装在 `/api` 身份验证之外。
工作流形状:`nodes[] = {id,type,name,parameters}`,`connections[] = {source,target,sourceHandle?,targetHandle?}`。 表达式使用 `{{ $node.<NodeName>.output.<path> }}`。
## 安全说明
- `jsCode` 在 **隔离虚拟机** 沙箱(V8,无主机绑定 — 无 `require` / `process` / `fs` / 网络)中运行用户代码,具有有限的内存和时间。 在生产环境中安全;无需选择加入标志。 使用 `LF_JS_TIMEOUT_MS`(默认值 5000)和 `LF_JS_MEMORY_MB`(默认值 128)全局调整限制,或通过 `jsTimeoutMs` / `jsMemoryMb` 参数逐个节点调整。
- 出站请求(httpRequest / oauth2 / SSE 触发器)通过 `safeFetch` 进行,该函数阻止生产环境中的私有/环回/元数据 IP 并重新验证每个重定向跳转(因此公共主机不能 30x 重定向到您的网络)。 响应正文使用内存上限读取。
- 凭证存储时加密(AES-256-GCM);API 绝不返回解密的机密。 类型:`basicAuth`,`apiKey` 和 `oauth2` — 服务器到服务器(`client_credentials` / `refresh_token`)和交互式 `authorization_code` + PKCE(浏览器同意通过弹出窗口 → `/oauth/callback`),所有这些都具有自动令牌获取/刷新和加密令牌缓存。 交互式流程需要设置 `LF_PUBLIC_URL` 和在提供者处注册的重定向 URI。
- **多用户隔离** 深入实施:执行器线程将运行者的所有者编织到凭证解析中(流程不能使用另一个用户凭证),每个 `/api` 资源路由按 `owner_id` 过滤/授权(外部 → 404),MCP(全局,命名和 `aiAgent` 自己的工具集)仅公开所有者的流程/资源。 密码经过 scrypt 哈希;会话 JWT 由 `LF_JWT_SECRET` 进行 HS256 签名。
- 命名 MCP 服务器使用每个服务器的承载令牌(恒定时间比较);**公共**(无令牌)服务器可能不公开 **任何** `libreflow_*` 系统工具(不仅是破坏性工具 — 服务器拒绝创建启用了系统工具的公共服务器)。