# fyflow-plugin-sdk 中文文档

规范地址：https://npmcn.com/package/fyflow-plugin-sdk/

版本：0\.7\.0
npm 元数据更新时间：2026-11-03T17:13:57.632Z
中文译文更新时间：2026-11-03T18:06:50.232Z
软件包许可：MIT

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/fyflow-plugin-sdk
原文对照：https://npmcn.com/package/fyflow-plugin-sdk/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：68.6 kB，6 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：fyflow-orchestration ^0\.13\.0
- 首次发布：2026-10-24T08:31:52.039Z
- 最新版本发布：2026-11-03T17:13:57.482Z
- 已发布版本数：6（近 12 个月 6 个）

## 中文简介

fyflow-app插件的类型和definePlugin：节点类型，工人，门类型和资源组

## 安装

```sh
npm install fyflow-plugin-sdk
```

也可以使用：`pnpm add fyflow-plugin-sdk`、`yarn add fyflow-plugin-sdk`、`bun add fyflow-plugin-sdk`

## README

# fyflow-插件-sdk

类型和 `definePlugin` 写作 **插件** 对于fyflow-app， visual builder和Host为 [fyflow-编排](https://www.npmjs.com/package/fyflow-orchestration) 流。插件提供节点类型（与运行其任务的工人），门类型，资源组类型和资源组。

```sh
npm install --save-peer fyflow-plugin-sdk
npm install --save-dev fyflow-orchestration   # its types, for type checking; the Host brings its own at run time
```

## 合同

插件是一个模块，其默认导出是一个普通对象。 `definePlugin` 返回参数不变；它只提供类型检查。依赖SDK作为对等体，不要捆绑它：主机在运行时提供它（见下文），并且您自己的副本只会报告它自己的 `SDK_VERSION`而不是宿主的。

```ts
import { definePlugin } from "fyflow-plugin-sdk";

export default definePlugin({
  id: "acme.signer", // stable and unique across Plugins
  version: "1.0.0",
  base: import.meta.url, // what Worker `url`s resolve against
  // Set on the Host's Profiles, once for every Node Type that takes them (see Profiles and secrets).
  profile: {
    schema: {
      type: "object",
      properties: { key: { type: "string", writeOnly: true } }, // a secret
    },
    startup: ["key"], // read once, when a Worker starts
  },
  workers: {
    sign: {
      url: "./sign.worker.js",
      settingsSchema: { type: "object", properties: { field: { type: "string" } } },
    },
  },
  nodeTypes: {
    Sign: {
      worker: "sign",
      inline: true,
      profile: ["key"], // the fields of `profile` its Workers get
      groups: ["acme.signing"],
      icon: "signature", // from the app's icon set, below
      description: "Signs a field with HMAC.",
    },
  },
  groups: { "acme.signing": { type: "ConcurrentLimitGroup", config: { limit: 2 } } },
  gateTypes: {
    threshold: {
      routes: ["below", "at-or-above"],
      defaultRoute: "below",
      fn: ({ key, settings }) => (Number(key) >= Number(settings.at) ? "at-or-above" : "below"),
    },
  },
});
```

| 场 | 它是什么？ |
| --- | --- |
| `profile` | 插件的Profile字段，从0.5.0开始：一个对象 `schema`， `defaults` 对于没有配置文件集的字段， `startup` 它的worker在启动时读取的字段，并且只有Profile可以设置每个任务字段(`profileOnly`）. 看到 [配置文件和秘密](https://npmcn.com/package/fyflow-plugin-sdk/#readme-profiles-and-secrets)。 |
| `workers` | 工作模块按键。Worker模块的默认导出是一个类：它的构造函数获取Node Type接受的启动字段，以及 `run({ settings, input }, context)` 执行一项任务 (请参见 [工人](https://npmcn.com/package/fyflow-plugin-sdk/#readme-workers)）。一名工人宣布不 `configSchema` 从0.5.0开始：它的配置是插件的 `profile`。模式是fyflow子集中的JSON模式。一个工人的 `outputSchema`,什么 `run` 返回（被每个版本的SDK接受，作为fyflow自己的Worker条目）是一个人填写的表单，用于标记失败的任务完成，以及编辑器在任何运行之前为其节点边缘和门的条件建议的路径。给 `inputSchema` 和 `outputSchema` 每个字段的描述和一个 `examples` list：一个节点的面板显示了它的Worker接收和返回的内容，并检查到达节点的内容与接收的内容。在任何运行之前，首先运行 `outputSchema`的 `examples` 是尝试并检查下一个节点的转换的示例; 如果没有一个，编辑器将从模式中生成更粗略的值。 |
| `nodeTypes` | 节点类型的名称，每个命名这个插件的一个 `workers`，使用fyflow的声明字段(`inline`， `pool`， `settings` 违约, `retryPolicy`， `groups`;否 `config` 自0.5.0起)，自0.2.0起应用程序如何显示它 (可选 `icon` 一行字 `description`)，并且自0.5.0起 `profile` 它占用的域。 |
| `dataDir` | `true` 从0.6.0开始，要求主机提供插件自己的数据目录。见 [插件的数据目录](https://npmcn.com/package/fyflow-plugin-sdk/#readme-a-plugins-data-directory)。 |
| `status` | 一个函数说插件是如何的，显示在插件页面上的卡片上，自0.6.0以来。见 [插件的状态](https://npmcn.com/package/fyflow-plugin-sdk/#readme-a-plugins-status)。 |
| `gateTypes` | 按名称的门类型: 它们的路由、默认路由、设置架构和决策 `fn`。 |
| `groupTypes` | 按名称划分资源组类型：a `create(config, key)` 用于调度程序限制的工厂，以及 `configSchema`。 |
| `groups` | fyflow内置类型的按键资源组(`ConcurrentLimitGroup`， `RateLimitGroup`， `KeyedRateLimitGroup`) 或这个插件自己的。节点类型可以使用其自己的插件的组，并且内置插件的 `disk`， `cpu` 和 `gpu` 组(下图)。 |

不要将设置命名为每个JavaScript对象的成员 (`constructor`， `toString`， `valueOf`， `hasOwnProperty`， `__proto__`）. 主机将流定义的形状交给代理，作为一个JSON模式，其中包括您的 `settingsSchema`,并且一些JSON模式验证器误读了这样的属性: 他们拒绝或抛出有效的流。

插件提供的每个名称（节点类型，门类型，资源组类型，资源组）必须在主机加载的插件中是唯一的：主机首先看到的插件保留一个名称，之后重复的插件将被跳过。

## 插件目录

主机从它的插件目录(`<dataDir>/plugins` 除非 `pluginDir`， `FYFLOW_PLUGIN_DIR` 或 `--plugin-dir` 否则):

-   一个 **文件夹** 持有 `plugin.ts` 或 `plugin.js`，或包裹(`package.json` 及其条目)，因为主机布局了从应用程序安装的插件；
-   一个 **包** 命名 `fyflow-plugin-*` 或 `@scope/fyflow-plugin-*` 在目录的 `node_modules`，用npm安装。一个包必须附带JavaScript: Node不会剥离TypeScript `node_modules`。

插件自己的导入从插件目录的 `node_modules`,所以 `npm install` 您在那里的其他依赖项（或捆绑它们）。SDK是主机提供的：在服务器上， `npm install fyflow-plugin-sdk` 在那里 (npm也安装它作为你的包的同行); 桌面应用程序把它自己在那里。更改在主机被告知时生效 **重新加载**。

## 对等范围

将插件使用的SDK版本声明为对等依赖：

```json
{ "peerDependencies": { "fyflow-plugin-sdk": "^0.5.0" } }
```

主机实现其SDK版本(`SDK_VERSION`，在此导出)以及与之兼容的早期版本(`SDK_COMPATIBLE`）。它跳过，原因是，一个插件的范围不包括它们。0.5.0更改了配置文件，因此它与早期版本不兼容: 跳过为0.4或之前编写的插件，直到升级为止，因为 [UPGRADING.md](https://npmcn.com/package/fyflow-plugin-sdk/UPGRADING.md) 描述.0.6.0和0.7.0仅添加到0.5.0，因此0.7上的主机加载一个声明插件 `^0.5.0` 或 `^0.6.0`． 从0.5开始，只对主机在运行时必须做的事情引发范围：请求数据目录的插件说 `^0.6.0`,因为0.5上的主机会加载它并给它none。

## 图标

节点类型的 `icon` 命名应用程序的图标之一，从 [Lucide](https://lucide.dev/icons/)： `activity`， `archive`， `bell`， `bot`， `box`， `braces`， `brain`， `calculator`， `calendar`， `camera`， `chart-bar`， `check`， `clock`， `cloud`， `code`， `cpu`， `credit-card`， `database`， `download`， `file`， `file-text`， `filter`， `flag`， `folder`， `git-branch`， `globe`， `hash`， `image`， `key`， `link`， `list`， `lock`， `mail`， `map-pin`， `message-square`， `package`， `pen-tool`， `play`， `plug`， `repeat`， `search`， `send`， `server`， `settings`， `shield`， `shopping-cart`， `signature`， `sparkles`， `table`， `tag`， `terminal`， `timer`， `trash`， `upload`， `user`， `users`， `wand-sparkles`， `webhook`， `zap`。集合之外的名称不是错误: 节点类型显示其种类的图标，插件页面显示警告。

## 工人

Worker模块的默认导出是一个类。主机用它的Node Type从配置文件中获取的启动字段来构建每个实例（池的每个worker：一个线程，或者在内联池中使用主机自己线程上的对象），并跨任务重用它，因此请将每个任务状态从字段中删除。 `run` 获取任务的信封（节点的信封） `settings` 和Task输入)和上下文；它返回的是Task的结果，而throw会带着错误消息使Task失败。自0.3.0以来，SDK类型的所有：

```ts
import type { TaskEnvelope, Worker, WorkerContext } from "fyflow-plugin-sdk";

type Config = { key?: string };
type Settings = { field?: string };

export default class Sign implements Worker<Settings> {
  readonly #config: Config;

  constructor(config: Config) {
    this.#config = config;
  }

  async run({ settings, input }: TaskEnvelope<Settings>, context: WorkerContext) {
    if (this.#config.key === undefined) throw new Error("No key: set `key` on this Node's Profile");
    context.sendProgress(0, "signing"); // a fraction from 0 to 1, not a percentage
    context.signal.throwIfAborted(); // aborted when the Task is Cancelled
    const value = settings.field === undefined ? input : (input as Record<string, unknown>)[settings.field];
    return { signed: await hmac(this.#config.key, value) }; // hmac: your own signing function
  }
}
```

`WorkerClass<Config, Settings, Input, Output>` 类型类本身，包括构造函数。检查 `context.signal` 步骤之间，或将其传递给任何需要一个 (`fetch`,streams): 立即停止的Worker会更快地释放其插槽，并且在取消后返回的内容将被丢弃。使用 `import type`因此，Worker模块在运行时不需要来自SDK的任何东西。上下文提供了Host显示的内容（进度）和Cancel；fyflow的调度程序传递更多信息，但SDK只承诺传递这些信息。

### 工人的生命周期

从0.5.0开始，SDK还承诺了任务之间的实例发生的情况，对于拥有长期存在的东西（子进程，连接，加载的模型）的Worker：

1.  **建造的**： `new Worker(config, pool)`,在那里 `config` 它的创业领域是什么 `pool` 一个 `PoolContext`。
2.  **`setup()`**,如果它有一个: 一次，在它的第一个任务之前等待。在这里启动它拥有的东西，而不是在构造函数中。
3.  **`run`**，用于任意数量的任务。
4.  **`teardown()`**，如果有的话：一次，当池退出实例时。那是当它已经闲置过了它的池子 `idleTimeout` (池每5秒检查一次，所以最多5秒后)，当它要求被替换时，以及当它的运行时关闭时: 主机停止，或者在一次重新加载后，一旦被替换的运行时上一次运行结束。

```ts
import type { PoolContext, Worker } from "fyflow-plugin-sdk";

export default class Thumbnails implements Worker {
  readonly #pool: PoolContext | undefined;
  #service: Service | undefined; // Service, start: your own

  constructor(_config: object, pool?: PoolContext) {
    this.#pool = pool;
  }

  async setup() {
    // Port 0: another copy of this Worker may be running (see below).
    this.#service = await start({ port: 0, onExit: (error) => this.#pool?.terminateWithError(error, { canRestart: true }) });
  }

  async teardown() {
    await this.#service?.stop(); // undefined when setup() did not get that far
  }

  async run() {
    return this.#service?.thumbnail();
  }
}
```

依靠什么，不依靠什么:

-   **一个 `setup()` ,抛出** 每个给定实例的Task都失败，包括它的消息和它的 `teardown()` 立即运行。它不会在该实例上再次尝试: 只有在重新加载时退役这一池时，或者一旦没有任务达到它的 `idleTimeout`这是源源不断的任务所不允许的。所以一个 `setup()` 这可能会因为一个传递的原因（端口被占用，服务仍在启动）而失败，应该在抛出之前在自身内部重试 `teardown()` 必须应付一个 `setup()` 那永远不会结束。
-   **`pool.terminateWithError(error, { canRestart: true })`** 要求池替换实例，说它拥有的进程死亡后。它一次返回，从不抛出，所以从回调或计时器调用它。实例的 `teardown()` 运行时，其仍在运行的任务回到队列中，在新实例上再次运行，并且该实例已构建和设置。与 `canRestart: false` 这些任务反而失败了。池仅多次替换实例 (3，fyflue-scheduler的 `maxWorkerRestarts`）; 之后，它不再构建，它的任务等待直到重新加载。因此，询问实例何时中断，而不是因为Task失败：throw from `run` 的。
-   **永远不要假设一个副本。** 每个概要文件都有它自己的池，一个池可以容纳几个实例（最多为它的实例） `maxThreads`)，并且在重新加载之后，被替换的运行时的实例保持运行它的运行，而新的运行时设置它自己的。绑定端口0，而不是固定端口，并保持Worker之外的任何共享。
-   **`idleTimeout`** 默认为5秒。对于设置成本高昂的工作人员，请给出其节点类型的 `pool` 长一点的(`pool: { idleTimeout: 60_000 }`）; 配置文件可以为该节点类型覆盖它。 `0` 保留实例，直到其运行时关闭。

### 插件的数据目录

一个保持状态超过一个主机进程的插件（它的服务需要一个缓存，一个禁止等待结束的记录）集 `dataDir: true` (自0.6.0起)。然后主机给它一个自己的文件夹， `plugin-data/<plugin id>/` 在主机的data目录下，并在构建插件的Workers之前创建它。插件的每个Worker在它的配置中找到它的绝对路径，如 `host.dataDir`,在内联池或线程池中:

```ts
import { join } from "node:path";
import type { HostConfig, Worker } from "fyflow-plugin-sdk";

type Config = { host: HostConfig; ttlHours?: number };

export default class Lookup implements Worker {
  readonly #cache: string;

  constructor(config: Config) {
    this.#cache = join(config.host.dataDir, "answers.sqlite");
  }
  // …
}
```

-   该文件夹保存在重新加载、更新和卸载然后重新安装之间。应用程序永远不会删除它：要重新开始，请在主机停止时手动删除它。
-   因此，路径在配置中有一个地方，一个请求一个的插件可能没有名为的启动字段 `host`;Host跳过了它，并给出了理由。一个插件，不要求得到没有文件夹和没有 `host` 在它的配置中，以及它自己的 `host` 领域是它自己的。
-   几个实例，并在运行时重新加载替换，可以一次运行: 写入文件夹作为一个共享的地方 (一个SQLite数据库，一个文件被原子替换)，而不是作为一个工人自己的。

## 插件的状态

一个在任务（连接，会话，速率限制后的队列）之间保持运行的插件可以说明它是如何运行的 `status()` （自0.6.0版起）。主持人在其插件页面上的插件卡上显示答案，在页面打开时每5秒再次询问一次，并将其提供给代理。一个没有插件 `status()` 显示无。

```ts
import { definePlugin } from "fyflow-plugin-sdk";
import { session } from "./session.ts"; // your own module, shared with the inline Workers

export default definePlugin({
  // …
  status: () =>
    session.blockedUntil === null
      ? { level: "ok", summary: `Logged in · ${session.queued} queued` }
      : {
          level: "warning",
          summary: "Blocked after a ban",
          details: [{ label: "Blocked until", value: session.blockedUntil.toLocaleTimeString() }],
        },
});
```

-   `level` 是 `ok`， `info`， `warning` 或 `error`； `summary` 是一行； `details` 是可选的标签和值对。它是数据：主机绘制它，所以插件仍然没有提供UI代码。
-   它运行在主机自己的线程上，主机加载了插件的模块。它看到该模块与共享的内容 `inline` 工人，而不是线程工人持有的东西。
-   一秒钟内回答。一个 `status()` 扔，拒绝，用别的东西回答，或者花更长的时间显示 `error` 有原因的状态。当一个答案仍然悬而未决时，主机不再询问。
-   它是手握的 `{ dataDir }` 当插件请求数据目录时，并且 `{}` 否则。
-   主机从答案中删除其秘密，就像从错误中删除一样，但不要将其放在那里。

## 这个 `disk`， `cpu` 和 `gpu` 小组

主机的内置插件声明了三个资源组，任何插件的节点类型都可以命名，每个资源组都有一个主机可以在其资源组页面上覆盖的并发限制：

-   `disk` (出口 `DISK_GROUP` 从0.3.0开始)，在读取或写入主机磁盘的任务上。它是4。当您的任务执行繁重的磁盘工作 (复制，转码，索引) 时，将其命名，以便它们与主机自己的文件系统节点类型共享一个预算，而不是在它们旁边打转磁盘。
-   `cpu` (出口 `CPU_GROUP` 从0.4.0开始)，用于使处理器忙碌的任务（散列，编码，图像工作）。这是主机的逻辑处理器计数，因此来自每个插件的任务加在一起不会占用更多的处理器。
-   `gpu` (出口 `GPU_GROUP` 从0.7.0开始)，在使用GPU (推理，渲染，GPU编码) 的任务上。它是1，因为主机不能计算它的gpu; 一个人在一台机器上提出更多。它只计数: 一个任务不告诉它持有哪个GPU，所以当限制高于1时，你的插件选择每个任务的设备 (从其设置，或通过跟踪本身)。

同时做这两件事的Task：

```ts
import { CPU_GROUP, DISK_GROUP, definePlugin } from "fyflow-plugin-sdk";

export default definePlugin({
  // …
  nodeTypes: { Transcode: { worker: "transcode", groups: [DISK_GROUP, CPU_GROUP] } },
});
```

其他插件的组保持遥不可及，所以禁用一个插件永远不会打破另一个。键是值，因此导入它们的插件在运行时需要SDK; 编写 `"disk"`， `"cpu"` 或 `"gpu"` 而是在具有组的任何主机上工作。SDK 0.4.0之前的主机没有 `cpu` 并跳过一个插件命名它，所以一个插件，它的名字说 `^0.4.0` 在其对等范围内；这同样适用于 `gpu` 和 `^0.7.0`。

## 在工人生活时举行小组活动

`groups` 保存一个任务的每个组的一个单位，从开始到结束。一个Worker在它的生命周期内持有一些东西，比如一个在任务之间加载在GPU内存中的模型，在它的Node Type中命名这个组 `pool.residentGroups` 相反 (自0.7.0起): 池在构建实例时获取单元，并在实例退役时将其返回 (空闲超过其 `idleTimeout`（重新加载或主机停止）。另一个池只在它需要的东西还合适的时候才构建实例，它的任务同时等待：直到持有者的 `idleTimeout` 在持有者完成最后一个任务后5秒。因此，持有组驻留的节点类型需要一个 `idleTimeout` 以上0;主机拒绝0个插件或配置文件中的一个。

```ts
import { definePlugin, GPU_GROUP } from "fyflow-plugin-sdk";

export default definePlugin({
  // …
  groups: { "imagegen.vram": { type: "ConcurrentLimitGroup", config: { limit: 24 } } }, // GB
  workers: { model: { url: "./model.worker.ts" } },
  nodeTypes: {
    // Keeps its model loaded for 10 minutes after its last Task, holding the GPU and 16 GB of its memory meanwhile.
    Generate: {
      worker: "model",
      pool: { maxThreads: 1, idleTimeout: 600_000, residentGroups: { [GPU_GROUP]: 1, "imagegen.vram": 16 } },
    },
  },
});
```

`residentGroups` 是一个键列表 (每个键的一个单元) 或每个键包含多少个单元，并且可以命名相同的组 `groups` 五月: 插件自己的和 `disk`， `cpu` 和 `gpu`。主机拒绝命名任何其他插件。每个实例都有单位，所以一个带有 `maxThreads: 2` 有两个;并且每个概要文件都有自己的节点类型池，因此在两个概要文件下运行的任务的节点类型为每个保存单元。保持 `maxThreads` 对于持有整个设备的Worker，以及在多个配置文件下运行它的主机，需要的单元数量与一次有活动池的数量一样多。

## 配置文件和秘密

插件的配置存在于主机上，而不是流中: A **配置文件** 是一个命名的配置与部分的每个插件，编辑在主机的用户界面的形式，从插件的 `profile.schema`． 每个主机都有一个默认配置文件。声明您的字段一次，在 `profile`,并在每个节点类型上列出它需要的节点: 几个节点类型需要的字段设置一次，用于所有节点类型。没有配置文件集的字段是其 `defaults` 价值。

一个 **启动字段** (列在 `profile.startup`) 在Worker启动时读取: 节点类型采用的启动字段是其Worker的配置，构造函数的参数，并且更改在主机的下一次重新加载时生效。使用一个工人设置一次: 一个连接，一个加载的模型。

每个其他字段都是一个 **每个任务字段**：主机在每个任务被分派时读取它，并将节点类型占用的任务交给主机 `run` 作为 `settings.profile` （`{}` （当它不需要时），因此更改到达下一个任务时不需要重新加载。输入 `TaskEnvelope<Settings, Input, ProfileFields>`． 你的 `settingsSchema` 不能命名 `profile`． 列表中 `profile.profileOnly` 每个任务的字段只有一个配置文件可以设置: 一个授权，如文件夹任务可以达到，旁边的字段流可以设置为缩小它，您的工作人员检查授权。每个任务字段永远不会达到运行的记录，但什么 `run` 退货是记录的，所以不要退货。

标记的属性 `profile.schema` `writeOnly: true` 把它变成 **秘密**: 主机永远不会再次显示它，仅显示它是否已设置，并从错误和日志中编辑其值。只有架构的属性可以是机密。

## 版本控制

这个包遵循semver。 `SDK_VERSION` 始终等于包版本。

## 常见问题

### fyflow-plugin-sdk 是什么？

fyflow-app插件的类型和definePlugin：节点类型，工人，门类型和资源组

### 如何安装 fyflow-plugin-sdk？

在项目目录运行 npm install fyflow-plugin-sdk，或使用 pnpm add / yarn add / bun add。

### fyflow-plugin-sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### fyflow-plugin-sdk 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### fyflow-plugin-sdk 可以商用吗？

fyflow-plugin-sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### fyflow-plugin-sdk 还在维护吗？

最新版本 0\.7\.0 发布于 2026/11/04（今天）；至今共发布 6 个版本，其中过去 12 个月发布了 6 个；首次发布于 2026/10/24。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

