Skip to main content
ClaudeWave
Skill28.4k repo starsupdated today

deprecate-workflow-node

This Claude Code skill standardizes the deprecation workflow for FastGPT pipeline nodes, allowing teams to retire nodes while maintaining backward compatibility and hiding them from new workflow templates. Use this skill when a node like LoopNode or RunAppModule needs to be sunset: existing workflows continue to function, the node disappears from template panels for new workflows, and the type enum value is preserved so legacy workflows can still load and render the node. The skill covers systematic changes across templates, dispatchers, UI references, and configuration files.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/labring/FastGPT /tmp/deprecate-workflow-node && cp -r /tmp/deprecate-workflow-node/.agents/skills/core/workflow/deprecate_workflow_node ~/.claude/skills/deprecate-workflow-node
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

## When to Use This Skill

当用户需要"弃用 / 废弃 / 下线 / 不再推荐使用"某个工作流节点(例如 `LoopNode`、`RunAppModule` 等)时触发。

弃用的目标:
- 已存在的工作流仍能正常加载和运行(保持运行时兼容)。
- 新建工作流时,模板面板**不再展示**该节点。
- 节点的类型枚举值(FlowNodeTypeEnum)必须保留,否则旧工作流会找不到节点定义。

## 核心理念

弃用 ≠ 删除。**只断"新增入口",不断"运行通路"**。

| 维度          | 处理方式                                       |
| ------------- | ---------------------------------------------- |
| 类型枚举值    | 保留(旧工作流引用)                           |
| 模板定义      | 移到 `abandoned/` 目录,从模板面板列表中移除 |
| Dispatcher    | 移到 `abandoned/` 目录,添加 `@deprecated` 注释 |
| moduleTemplatesFlat | 必须保留,否则节点无法在画布上渲染       |
| **节点级 UI 徽章** | 模板加 `status: PluginStatusEnum.SoonOffline`,节点头部出现黄色"即将下线"标签 + tooltip"请尽快替换" |
| 子节点 / 关联节点 | 仅当确认无其他节点共享时才一并弃用         |
| i18n key      | 不动(旧工作流仍会读取 name/intro 文案)       |

> ℹ️ 字段级 `deprecated: true`(`FlowNodeInputItemType.deprecated` / `FlowNodeOutputItemType.deprecated`)是**独立机制**,用于在保留节点的前提下淘汰单个字段(旧字段保留兼容、新字段替代)。**整节点弃用时不要用它** —— 节点级徽章已经足够指示,再加字段级会让信号过度冗余。

## 参考案例

仓库内已有一个完整的弃用案例可参考:`FlowNodeTypeEnum.runApp`。可通过对比 `git log --diff-filter=R -- "**/abandoned/runApp/**"` 找到当时的迁移 commit。

## TODO 模板(执行前先复制并填写)

> 操作目标:弃用 `<NodeTemplateName>`(FlowNodeTypeEnum.`<enumKey>`)

- [ ] 1. **确认影响面**
- [ ] 2. **移动模板定义**到 abandoned 目录
- [ ] 3. **移动 Dispatcher**到 abandoned 目录
- [ ] 4. **更新 `template/constants.ts`**:从 `systemNodes` 移除,确保留在 `moduleTemplatesFlat`
- [ ] 5. **更新 `dispatch/constants.ts`**:加 `@deprecated` 注释,移到 callbackMap 末尾
- [ ] 6. **节点级徽章**:模板加 `status: PluginStatusEnum.SoonOffline`(节点头部显示"即将下线"黄色标签)
- [ ] 7. **检查 UI / Hook 引用**(不一定需要改)
- [ ] 8. **运行 lint + typecheck + 局部测试**

---

## 详细步骤

### 1. 确认影响面(必做)

在动手之前,**先用 grep/Explore 全局搜索**节点的所有引用,确认改动范围。需要查的关键字:

```bash
# 类型枚举使用点
grep -rn "FlowNodeTypeEnum\.<enumKey>\b" packages/ projects/ --include="*.ts" --include="*.tsx"

# 模板对象(如 LoopNode)
grep -rn "<TemplateExport>\b" packages/ projects/ --include="*.ts"

# 子节点是否被其他容器复用(重要!)
grep -rn "FlowNodeTypeEnum\.<childEnum>" packages/ projects/
```

输出一份"需要改动 / 无需改动"分类清单。**通常无需改动**:
- `useWorkflow.tsx` 里嵌入到 PARENT_NODE_TYPES / unsupportedInLoop 这种"运行时识别"列表 —— 旧实例仍要工作。
- `Flow/index.tsx` 的 `nodeTypes` 映射 —— 旧实例需要 UI 渲染。
- i18n 文案 —— 旧实例仍读取。

### 2. 移动模板定义到 abandoned 目录

源路径:`packages/global/core/workflow/template/system/<dir>/`
目标路径:`packages/global/core/workflow/template/system/abandoned/<dir>/`

操作:
1. 用 `git mv`(或 Bash `mv`)整个目录或仅 parent 节点的 `index.ts`/`type.ts`。
2. 修改文件内的相对 import 路径(深度多了一层 `../`)。
3. 如果只弃用容器节点而保留子节点(例如 `loopStart`/`loopEnd` 仍被 `parallelRun` 共用),**只移动 parent 节点文件**,子节点留在原位置。

### 3. 移动 Dispatcher 到 abandoned 目录

源路径:`packages/service/core/workflow/dispatch/<dir>/<file>.ts`
目标路径:`packages/service/core/workflow/dispatch/abandoned/<file>.ts`

操作:
1. `git mv` 文件。
2. 文件首行加上 `/* Abandoned */` 注释(与 `dispatch/abandoned/runApp.ts` 一致)。
3. 修改文件内的相对 import 路径。

### 4. 更新 `packages/global/core/workflow/template/constants.ts`

```ts
// 旧
import { LoopNode } from './system/loop/loop';

// 新
import { LoopNode } from './system/abandoned/loop/index';
```

```ts
// 从 systemNodes 移除(这是模板面板的来源)
const systemNodes: FlowNodeTemplateType[] = [
  ...
  // LoopNode,  ← 删除这一行
  ...
];
```

```ts
// 在 moduleTemplatesFlat 中保留 / 添加(保证旧工作流能解析)
export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
  ...,
  LoopNode,  // ← 这里要有
];
```

> ⚠️ 验证点:`moduleTemplatesFlat` 是节点 ID → 模板对象的查找源。**必须留**,否则旧工作流加载时会找不到节点,画布报错。

### 5. 更新 `packages/service/core/workflow/dispatch/constants.ts`

```ts
// 把 import 路径改成 abandoned 子目录
import { dispatchLoop } from './abandoned/runLoop';
```

把对应的 callbackMap 条目移到对象末尾,并加 `/** @deprecated */` 注释:

```ts
export const callbackMap: Record<FlowNodeTypeEnum, Function> = {
  // ...其他正常节点...

  /** @deprecated */
  [FlowNodeTypeEnum.loop]: dispatchLoop
};
```

### 6. 节点级徽章 `status: PluginStatusEnum.SoonOffline`

`FlowNodeTemplateTypeSchema.status` 是节点级的弃用 UI 信号,挂在 `NodeCard.tsx` 头部由 `<NodeStatusBadge />` 渲染:

| 值 | 标签 | 颜色 | tooltip | 适用场景 |
| --- | --- | --- | --- | --- |
| `Normal = 1` | 正常 | 蓝 | — | 不弃用 |
| `SoonOffline = 2` | 即将下线 | 黄 | "请尽快替换" | **弃用但仍可运行**(推荐用这个) |
| `Offline = 3` | 已下线 | 红 | "已无法使用,将中断应用运行,请立即替换" | 强制下线(运行时报错) |

由于弃用的核心理念是"运行通路保留",应当用 `SoonOffline`;只有当节点被改成"运行时直接抛错"时才用 `Offline`。

```ts
import { PluginStatusEnum } from '../../../../../plugin/type';

export const FooNode: FlowNodeTemplateType = {
  id: FlowNodeTypeEnum.foo,
  // ...
  status: PluginStatusEnum.SoonOffline,   // ← 加这个
  // ...
};
```

> ⚠️ 注意:这字段挂在 `FlowNodeTemplateTypeSchema`(即 `system` 模板的扩展)上,不在 `FlowNodeCommonTypeSchema` 上。意思是只对**系统节点模板**生效,store 里保存的 nodeData 不带 status,每次打开通过 `moduleTemplatesFlat.find(...)` 从模板查到。所以**只需改模板,不需要数据迁移**。

> ⚠️ schema 上还有一个看似相关的 `abandon: z.boolean().optional()`(`FlowNodeCommonTypeSchema:72`)—— **不要用它**,整个仓库没有任何 UI/runtime 代码读取它,是死字段。

### 7. 检查 UI / Hook 引用

通常以下文件**保持原样**(运行时兼容需要):
- `projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx` — `nodeTypes` 中的 React 渲染映射。
- `projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx` — `PARENT_NODE_TYPES`、`unSupportedInLoop` 等运行时校验。

如果该节点在前端有"添加按钮"快捷入口(不通过模板面板触发),那种入口可以删除。

### 8. 运行 lint + typecheck + 局部测试

```bash
# typescript 检查
pnpm lint

# 跑相关单测(按改动文件局部跑)
cd packages/service && pnpm test ...
```

不要全量跑测试,只跑改动相关的。

## 验证清单

弃用完成后,确认以下场景:

- [ ] 模板面板("添加节点"侧边栏)里**搜不到**该节点。
- [ ] 已有该节点的旧工作流可以**打开、加载、运行**,UI 正常渲染。
- [ ] 旧工作流中该节点头部右侧出现黄色 **"即将下线"** 徽章,hover 显示替换提示。
- [ ] `pnpm lint` 通过。
- [ ] dispatch/constants.ts 里 callbackMap 仍是 `Record<FlowNodeTypeEnum, Function>` 完整覆盖(不能删 key,否则 TS 报错)。

## 反模式(不要做)

- ❌ 删除 `FlowNodeTypeEnum.<enumKey>` —— 旧工作流的 JSON 仍写着这个值。
- ❌ 从 `moduleTemplatesFlat` 移除 —— 旧工作流加载时找不到模板。
- ❌ 从 `dispatch/constants.ts` 的 callbackMap 删条目 —— 运行时报"unknown node type"。
- ❌ 删除 i18n 的 name / intro key —— 旧工作流的 tooltip / 节点标题会变成 raw key。
- ❌ 删除 React 节点组件(`Flow/index.tsx` 的 nodeTypes 映射)—— 画布渲染崩。
- ❌ 一并弃用共享子节点(如 `nestedStart`/`nestedEnd` 同时被多个容器使用)。
- ❌ 整节点弃用时**给 inputs/outputs 加字段级 `deprecated: true`** —— 节点级徽章已足够,字段级是独立机制(用于"留住节点、淘汰单个字段"的场景)。
prompt-optimizeSkill

Expert prompt engineering skill that transforms Claude into "Alpha-Prompt" - a master prompt engineer who collaboratively crafts high-quality prompts through flexible dialogue. Activates when user asks to "optimize prompt", "improve system instruction", "enhance AI instruction", or mentions prompt engineering tasks.

doc-i18nSkill

将 FastGPT 文档从中文翻译为面向北美用户的英文。当用户提到翻译文档、i18n、国际化、translate docs、新增/修改了中文文档需要同步英文版时,使用此 skill。也适用于用户要求检查文档翻译缺失、批量翻译、或对比中英文文档差异的场景。

add-permissionSkill

为 FastGPT 新资源接入权限管理。当用户需要为新资源(如 AgentSkill、Plugin 等)添加权限支持时触发。

api-developmentSkill

FastGPT API 开发规范。重点强调使用 zod schema 定义入参和出参,在 API 文档中声明路由信息,编写对应的 OpenAPI 文档,以及在 API 路由中使用 schema.parse 进行验证。

pr-reviewSkill

仅当用户明确手动指定使用 pr-review skill 时触发;不要因为用户传入 PR 链接、要求 review 或要求代码审查而自动触发。

test-caseSkill

当用户需要编写一个单元测试时,触发该 skill,编写单元测试。

pr-change-analysisSkill

手动触发的 FastGPT PR 或本地分支变更梳理技能。仅当用户显式调用 $pr-change-analysis 时使用;用于 reviewer 分析一个 GitHub PR 或当前本地分支相对 upstream/main 的需求变更、影响范围、代码质量与代码风格,不用于自动审查触发。